aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/tracepoint.tmpl5
-rw-r--r--Documentation/feature-removal-schedule.txt15
-rw-r--r--Documentation/filesystems/proc.txt3
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt13
-rw-r--r--Documentation/sound/alsa/ControlNames.txt3
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt1
-rw-r--r--Documentation/sysctl/ctl_unnumbered.txt22
-rw-r--r--Documentation/trace/kprobetrace.txt149
-rw-r--r--arch/Kconfig7
-rw-r--r--arch/arm/kernel/isa.c17
-rw-r--r--arch/arm/mach-bcmring/arch.c8
-rw-r--r--arch/arm/mach-davinci/include/mach/asp.h8
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c10
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c10
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c10
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c10
-rw-r--r--arch/arm/mach-omap2/board-overo.c10
-rw-r--r--arch/arm/mach-omap2/board-zoom2.c10
-rw-r--r--arch/arm/mach-s3c6400/include/mach/map.h2
-rw-r--r--arch/arm/plat-s3c/include/plat/audio.h48
-rw-r--r--arch/arm/plat-s3c/include/plat/devs.h3
-rw-r--r--arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h2
-rw-r--r--arch/arm/plat-s3c64xx/dev-audio.c101
-rw-r--r--arch/frv/kernel/pm.c114
-rw-r--r--arch/frv/kernel/sysctl.c7
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/ia32/sys_ia32.c55
-rw-r--r--arch/ia64/kernel/crash.c11
-rw-r--r--arch/ia64/kernel/perfmon.c14
-rw-r--r--arch/microblaze/include/asm/prom.h135
-rw-r--r--arch/microblaze/kernel/head.S2
-rw-r--r--arch/microblaze/kernel/prom.c23
-rw-r--r--arch/mips/kernel/linux32.c61
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/lasat/sysctl.c121
-rw-r--r--arch/parisc/kernel/sys_parisc32.c71
-rw-r--r--arch/parisc/kernel/syscall_table.S2
-rw-r--r--arch/powerpc/Kconfig.debug2
-rw-r--r--arch/powerpc/configs/pseries_defconfig2
-rw-r--r--arch/powerpc/include/asm/emulated_ops.h19
-rw-r--r--arch/powerpc/include/asm/hvcall.h2
-rw-r--r--arch/powerpc/include/asm/prom.h147
-rw-r--r--arch/powerpc/include/asm/reg.h2
-rw-r--r--arch/powerpc/include/asm/trace.h133
-rw-r--r--arch/powerpc/kernel/align.c12
-rw-r--r--arch/powerpc/kernel/entry_64.S4
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S3
-rw-r--r--arch/powerpc/kernel/idle.c4
-rw-r--r--arch/powerpc/kernel/irq.c6
-rw-r--r--arch/powerpc/kernel/perf_event.c2
-rw-r--r--arch/powerpc/kernel/power5+-pmu.c4
-rw-r--r--arch/powerpc/kernel/power5-pmu.c6
-rw-r--r--arch/powerpc/kernel/power6-pmu.c2
-rw-r--r--arch/powerpc/kernel/power7-pmu.c6
-rw-r--r--arch/powerpc/kernel/ppc970-pmu.c4
-rw-r--r--arch/powerpc/kernel/prom.c23
-rw-r--r--arch/powerpc/kernel/setup-common.c1
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c52
-rw-r--r--arch/powerpc/kernel/time.c6
-rw-r--r--arch/powerpc/kernel/traps.c18
-rw-r--r--arch/powerpc/lib/copypage_64.S4
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S132
-rw-r--r--arch/powerpc/platforms/pseries/hvCall_inst.c38
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c33
-rw-r--r--arch/s390/appldata/appldata_base.c4
-rw-r--r--arch/s390/kernel/compat_linux.c53
-rw-r--r--arch/s390/kernel/compat_linux.h2
-rw-r--r--arch/s390/kernel/compat_wrapper.S6
-rw-r--r--arch/s390/kernel/debug.c13
-rw-r--r--arch/s390/mm/cmm.c11
-rw-r--r--arch/sh/boards/mach-hp6xx/setup.c55
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c3
-rw-r--r--arch/sh/include/mach-common/mach/hp6xx.h4
-rw-r--r--arch/sh/kernel/traps_64.c13
-rw-r--r--arch/sparc/Kconfig7
-rw-r--r--arch/sparc/Makefile2
-rw-r--r--arch/sparc/include/asm/btext.h6
-rw-r--r--arch/sparc/include/asm/leon.h45
-rw-r--r--arch/sparc/include/asm/prom.h55
-rw-r--r--arch/sparc/include/asm/rwsem.h4
-rw-r--r--arch/sparc/include/asm/smp_32.h9
-rw-r--r--arch/sparc/kernel/Makefile3
-rw-r--r--arch/sparc/kernel/apc.c37
-rw-r--r--arch/sparc/kernel/auxio_32.c1
-rw-r--r--arch/sparc/kernel/btext.c673
-rw-r--r--arch/sparc/kernel/cpu.c11
-rw-r--r--arch/sparc/kernel/entry.S33
-rw-r--r--arch/sparc/kernel/head_32.S22
-rw-r--r--arch/sparc/kernel/ioport.c5
-rw-r--r--arch/sparc/kernel/irq_64.c8
-rw-r--r--arch/sparc/kernel/leon_kernel.c84
-rw-r--r--arch/sparc/kernel/leon_smp.c468
-rw-r--r--arch/sparc/kernel/pci_msi.c2
-rw-r--r--arch/sparc/kernel/setup_64.c6
-rw-r--r--arch/sparc/kernel/smp_32.c10
-rw-r--r--arch/sparc/kernel/sys_sparc32.c62
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/sparc/kernel/time_32.c3
-rw-r--r--arch/sparc/kernel/trampoline_32.S69
-rw-r--r--arch/sparc/mm/srmmu.c9
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/Kconfig.cpu2
-rw-r--r--arch/x86/Kconfig.debug23
-rw-r--r--arch/x86/Makefile3
-rw-r--r--arch/x86/Makefile_32.cpu2
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/ia32/sys_ia32.c56
-rw-r--r--arch/x86/include/asm/Kbuild1
-rw-r--r--arch/x86/include/asm/a.out-core.h10
-rw-r--r--arch/x86/include/asm/alternative-asm.h10
-rw-r--r--arch/x86/include/asm/alternative.h1
-rw-r--r--arch/x86/include/asm/apic.h21
-rw-r--r--arch/x86/include/asm/apicdef.h6
-rw-r--r--arch/x86/include/asm/apicnum.h12
-rw-r--r--arch/x86/include/asm/cmpxchg_32.h218
-rw-r--r--arch/x86/include/asm/cmpxchg_64.h234
-rw-r--r--arch/x86/include/asm/debugreg.h33
-rw-r--r--arch/x86/include/asm/hardirq.h6
-rw-r--r--arch/x86/include/asm/hw_breakpoint.h73
-rw-r--r--arch/x86/include/asm/hw_irq.h30
-rw-r--r--arch/x86/include/asm/inat.h220
-rw-r--r--arch/x86/include/asm/inat_types.h29
-rw-r--r--arch/x86/include/asm/insn.h184
-rw-r--r--arch/x86/include/asm/irq.h1
-rw-r--r--arch/x86/include/asm/mce.h14
-rw-r--r--arch/x86/include/asm/mpspec.h16
-rw-r--r--arch/x86/include/asm/msr.h8
-rw-r--r--arch/x86/include/asm/perf_event.h13
-rw-r--r--arch/x86/include/asm/processor.h14
-rw-r--r--arch/x86/include/asm/ptrace.h62
-rw-r--r--arch/x86/include/asm/string_32.h9
-rw-r--r--arch/x86/include/asm/sys_ia32.h5
-rw-r--r--arch/x86/include/asm/system.h31
-rw-r--r--arch/x86/include/asm/uaccess.h1
-rw-r--r--arch/x86/include/asm/uaccess_32.h27
-rw-r--r--arch/x86/include/asm/uaccess_64.h36
-rw-r--r--arch/x86/include/asm/uv/uv_irq.h14
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/apic/Makefile2
-rw-r--r--arch/x86/kernel/apic/apic.c34
-rw-r--r--arch/x86/kernel/apic/apic_noop.c200
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c13
-rw-r--r--arch/x86/kernel/apic/es7000_32.c16
-rw-r--r--arch/x86/kernel/apic/io_apic.c364
-rw-r--r--arch/x86/kernel/apic/nmi.c11
-rw-r--r--arch/x86/kernel/apic/numaq_32.c13
-rw-r--r--arch/x86/kernel/apic/probe_32.c2
-rw-r--r--arch/x86/kernel/apic/summit_32.c10
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c8
-rw-r--r--arch/x86/kernel/apm_32.c14
-rw-r--r--arch/x86/kernel/cpu/Makefile1
-rw-r--r--arch/x86/kernel/cpu/amd.c2
-rw-r--r--arch/x86/kernel/cpu/centaur.c2
-rw-r--r--arch/x86/kernel/cpu/common.c34
-rw-r--r--arch/x86/kernel/cpu/cpu.h2
-rw-r--r--arch/x86/kernel/cpu/cyrix.c2
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c16
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c103
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c29
-rw-r--r--arch/x86/kernel/cpu/perf_event.c205
-rw-r--r--arch/x86/kernel/cpu/perfctr-watchdog.c2
-rw-r--r--arch/x86/kernel/cpu/transmeta.c2
-rw-r--r--arch/x86/kernel/cpuid.c17
-rw-r--r--arch/x86/kernel/dumpstack.c7
-rw-r--r--arch/x86/kernel/dumpstack_32.c9
-rw-r--r--arch/x86/kernel/dumpstack_64.c46
-rw-r--r--arch/x86/kernel/entry_32.S24
-rw-r--r--arch/x86/kernel/entry_64.S19
-rw-r--r--arch/x86/kernel/head_64.S4
-rw-r--r--arch/x86/kernel/hw_breakpoint.c555
-rw-r--r--arch/x86/kernel/irq.c102
-rw-r--r--arch/x86/kernel/irq_32.c45
-rw-r--r--arch/x86/kernel/irq_64.c58
-rw-r--r--arch/x86/kernel/kgdb.c9
-rw-r--r--arch/x86/kernel/kprobes.c257
-rw-r--r--arch/x86/kernel/machine_kexec_32.c2
-rw-r--r--arch/x86/kernel/machine_kexec_64.c2
-rw-r--r--arch/x86/kernel/microcode_core.c2
-rw-r--r--arch/x86/kernel/msr.c16
-rw-r--r--arch/x86/kernel/process.c21
-rw-r--r--arch/x86/kernel/process_32.c10
-rw-r--r--arch/x86/kernel/process_64.c10
-rw-r--r--arch/x86/kernel/ptrace.c415
-rw-r--r--arch/x86/kernel/setup.c7
-rw-r--r--arch/x86/kernel/signal.c9
-rw-r--r--arch/x86/kernel/smpboot.c9
-rw-r--r--arch/x86/kernel/traps.c73
-rw-r--r--arch/x86/kernel/tsc_sync.c13
-rw-r--r--arch/x86/kernel/uv_irq.c239
-rw-r--r--arch/x86/kernel/visws_quirks.c8
-rw-r--r--arch/x86/kernel/vsyscall_64.c2
-rw-r--r--arch/x86/kernel/x8664_ksyms_64.c5
-rw-r--r--arch/x86/kvm/x86.c18
-rw-r--r--arch/x86/lib/.gitignore1
-rw-r--r--arch/x86/lib/Makefile13
-rw-r--r--arch/x86/lib/copy_user_64.S14
-rw-r--r--arch/x86/lib/inat.c90
-rw-r--r--arch/x86/lib/insn.c516
-rw-r--r--arch/x86/lib/msr.c46
-rw-r--r--arch/x86/lib/usercopy_32.c10
-rw-r--r--arch/x86/lib/x86-opcode-map.txt893
-rw-r--r--arch/x86/mm/extable.c31
-rw-r--r--arch/x86/mm/fault.c13
-rw-r--r--arch/x86/mm/kmmio.c8
-rw-r--r--arch/x86/mm/srat_64.c4
-rw-r--r--arch/x86/power/cpu.c26
-rw-r--r--arch/x86/tools/Makefile31
-rw-r--r--arch/x86/tools/chkobjdump.awk23
-rw-r--r--arch/x86/tools/distill.awk47
-rw-r--r--arch/x86/tools/gen-insn-attr-x86.awk380
-rw-r--r--arch/x86/tools/test_get_len.c173
-rw-r--r--arch/x86/vdso/vdso32-setup.c1
-rw-r--r--crypto/proc.c12
-rw-r--r--drivers/cdrom/cdrom.c20
-rw-r--r--drivers/char/hpet.c11
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c11
-rw-r--r--drivers/char/pty.c14
-rw-r--r--drivers/char/random.c54
-rw-r--r--drivers/char/rtc.c11
-rw-r--r--drivers/edac/edac_mce_amd.c21
-rw-r--r--drivers/macintosh/mac_hid.c17
-rw-r--r--drivers/md/md.c14
-rw-r--r--drivers/media/radio/Kconfig18
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/radio-miropcm20.c270
-rw-r--r--drivers/mfd/Kconfig6
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/twl4030-codec.c276
-rw-r--r--drivers/mfd/twl4030-core.c16
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c14
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c5
-rw-r--r--drivers/of/base.c26
-rw-r--r--drivers/parport/procfs.c39
-rw-r--r--drivers/s390/char/sclp_async.c5
-rw-r--r--drivers/scsi/scsi_sysctl.c11
-rw-r--r--drivers/serial/Kconfig13
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/apbuart.c710
-rw-r--r--drivers/serial/apbuart.h64
-rw-r--r--drivers/staging/arlan/arlan-proc.c245
-rw-r--r--drivers/watchdog/riowd.c6
-rw-r--r--fs/coda/sysctl.c10
-rw-r--r--fs/eventpoll.c4
-rw-r--r--fs/lockd/svc.c26
-rw-r--r--fs/nfs/sysctl.c22
-rw-r--r--fs/notify/inotify/inotify_user.c14
-rw-r--r--fs/ntfs/sysctl.c4
-rw-r--r--fs/ocfs2/stackglue.c15
-rw-r--r--fs/proc/array.c23
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/proc/stat.c19
-rw-r--r--fs/quota/dquot.c35
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c62
-rw-r--r--include/linux/compiler-gcc4.h8
-rw-r--r--include/linux/compiler.h11
-rw-r--r--include/linux/ftrace_event.h38
-rw-r--r--include/linux/hw_breakpoint.h131
-rw-r--r--include/linux/i2c/twl4030.h19
-rw-r--r--include/linux/jiffies.h1
-rw-r--r--include/linux/kernel_stat.h1
-rw-r--r--include/linux/kprobes.h2
-rw-r--r--include/linux/mfd/twl4030-codec.h272
-rw-r--r--include/linux/of.h103
-rw-r--r--include/linux/of_fdt.h86
-rw-r--r--include/linux/perf_counter.h3
-rw-r--r--include/linux/perf_event.h59
-rw-r--r--include/linux/preempt.h5
-rw-r--r--include/linux/sched.h22
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/syscalls.h77
-rw-r--r--include/linux/sysctl.h44
-rw-r--r--include/linux/tracepoint.h6
-rw-r--r--include/net/dn_dev.h1
-rw-r--r--include/net/neighbour.h3
-rw-r--r--include/sound/Kbuild1
-rw-r--r--include/sound/aci.h (renamed from sound/isa/opti9xx/miro.h)23
-rw-r--r--include/sound/ak4113.h321
-rw-r--r--include/sound/ak4114.h12
-rw-r--r--include/sound/ak4xxx-adda.h5
-rw-r--r--include/sound/control.h5
-rw-r--r--include/sound/cs4231-regs.h1
-rw-r--r--include/sound/pcm.h3
-rw-r--r--include/sound/rawmidi.h2
-rw-r--r--include/sound/sh_dac_audio.h21
-rw-r--r--include/sound/soc-dai.h14
-rw-r--r--include/sound/soc-dapm.h17
-rw-r--r--include/sound/soc.h15
-rw-r--r--include/sound/sscape_ioctl.h21
-rw-r--r--include/sound/tlv320dac33-plat.h20
-rw-r--r--include/sound/tpa6130a2-plat.h30
-rw-r--r--include/sound/wss.h1
-rw-r--r--include/trace/define_trace.h11
-rw-r--r--include/trace/events/bkl.h18
-rw-r--r--include/trace/events/block.h202
-rw-r--r--include/trace/events/ext4.h129
-rw-r--r--include/trace/events/irq.h52
-rw-r--r--include/trace/events/jbd2.h63
-rw-r--r--include/trace/events/kmem.h130
-rw-r--r--include/trace/events/lock.h (renamed from include/trace/events/lockdep.h)8
-rw-r--r--include/trace/events/mce.h69
-rw-r--r--include/trace/events/module.h22
-rw-r--r--include/trace/events/power.h38
-rw-r--r--include/trace/events/sched.h217
-rw-r--r--include/trace/events/signal.h173
-rw-r--r--include/trace/events/timer.h79
-rw-r--r--include/trace/events/workqueue.h22
-rw-r--r--include/trace/ftrace.h338
-rw-r--r--include/trace/syscall.h31
-rw-r--r--init/Kconfig1
-rw-r--r--ipc/ipc_sysctl.c77
-rw-r--r--ipc/mq_sysctl.c7
-rw-r--r--kernel/Makefile4
-rw-r--r--kernel/cpuset.c27
-rw-r--r--kernel/exit.c27
-rw-r--r--kernel/fork.c5
-rw-r--r--kernel/hw_breakpoint.c423
-rw-r--r--kernel/kallsyms.c1
-rw-r--r--kernel/kgdb.c2
-rw-r--r--kernel/kprobes.c68
-rw-r--r--kernel/lockdep.c2
-rw-r--r--kernel/notifier.c2
-rw-r--r--kernel/perf_event.c627
-rw-r--r--kernel/sched.c275
-rw-r--r--kernel/sched_debug.c4
-rw-r--r--kernel/sched_fair.c65
-rw-r--r--kernel/sched_rt.c61
-rw-r--r--kernel/signal.c27
-rw-r--r--kernel/slow-work.c7
-rw-r--r--kernel/sys.c21
-rw-r--r--kernel/sys_ni.c1
-rw-r--r--kernel/sysctl.c893
-rw-r--r--kernel/sysctl_binary.c1507
-rw-r--r--kernel/sysctl_check.c1377
-rw-r--r--kernel/time.c30
-rw-r--r--kernel/trace/Kconfig38
-rw-r--r--kernel/trace/Makefile2
-rw-r--r--kernel/trace/ring_buffer.c15
-rw-r--r--kernel/trace/trace.h38
-rw-r--r--kernel/trace/trace_entries.h16
-rw-r--r--kernel/trace/trace_event_profile.c43
-rw-r--r--kernel/trace/trace_events.c168
-rw-r--r--kernel/trace/trace_events_filter.c310
-rw-r--r--kernel/trace/trace_export.c39
-rw-r--r--kernel/trace/trace_kprobe.c1523
-rw-r--r--kernel/trace/trace_ksym.c550
-rw-r--r--kernel/trace/trace_selftest.c55
-rw-r--r--kernel/trace/trace_syscalls.c195
-rw-r--r--kernel/utsname_sysctl.c31
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--net/802/tr.c7
-rw-r--r--net/appletalk/sysctl_net_atalk.c13
-rw-r--r--net/ax25/sysctl_net_ax25.c38
-rw-r--r--net/bridge/br_netfilter.c6
-rw-r--r--net/core/neighbour.c47
-rw-r--r--net/core/sysctl_net_core.c21
-rw-r--r--net/dccp/sysctl.c8
-rw-r--r--net/decnet/dn_dev.c64
-rw-r--r--net/decnet/sysctl_net_decnet.c123
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c111
-rw-r--r--net/ipv4/ip_fragment.c6
-rw-r--r--net/ipv4/netfilter.c6
-rw-r--r--net/ipv4/netfilter/ip_queue.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c10
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c8
-rw-r--r--net/ipv4/route.c73
-rw-r--r--net/ipv4/sysctl_net_ipv4.c165
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/addrconf.c91
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ndisc.c39
-rw-r--r--net/ipv6/netfilter/ip6_queue.c4
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c4
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c4
-rw-r--r--net/ipv6/reassembly.c6
-rw-r--r--net/ipv6/route.c18
-rw-r--r--net/ipv6/sysctl_net_ipv6.c12
-rw-r--r--net/ipv6/xfrm6_policy.c1
-rw-r--r--net/ipx/sysctl_net_ipx.c7
-rw-r--r--net/irda/irsysctl.c31
-rw-r--r--net/llc/sysctl_net_llc.c25
-rw-r--r--net/netfilter/core.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c2
-rw-r--r--net/netfilter/nf_conntrack_acct.c1
-rw-r--r--net/netfilter/nf_conntrack_ecache.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c12
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c14
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c6
-rw-r--r--net/netfilter/nf_conntrack_standalone.c14
-rw-r--r--net/netfilter/nf_log.c7
-rw-r--r--net/netrom/sysctl_net_netrom.c30
-rw-r--r--net/phonet/sysctl.c8
-rw-r--r--net/rds/ib_sysctl.c26
-rw-r--r--net/rds/iw_sysctl.c26
-rw-r--r--net/rds/sysctl.c21
-rw-r--r--net/rose/sysctl_net_rose.c26
-rw-r--r--net/sctp/sysctl.c52
-rw-r--r--net/sunrpc/sysctl.c15
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma.c40
-rw-r--r--net/sunrpc/xprtrdma/transport.c32
-rw-r--r--net/sunrpc/xprtsock.c28
-rw-r--r--net/unix/sysctl_net_unix.c7
-rw-r--r--net/x25/sysctl_net_x25.c15
-rw-r--r--net/xfrm/xfrm_sysctl.c4
-rw-r--r--samples/Kconfig6
-rw-r--r--samples/Makefile3
-rw-r--r--samples/hw_breakpoint/Makefile1
-rw-r--r--samples/hw_breakpoint/data_breakpoint.c87
-rwxr-xr-xscripts/kernel-doc15
-rw-r--r--security/keys/sysctl.c17
-rw-r--r--security/tomoyo/file.c21
-rw-r--r--security/tomoyo/realpath.c9
-rw-r--r--security/tomoyo/tomoyo.c80
-rw-r--r--security/tomoyo/tomoyo.h2
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/arm/Makefile2
-rw-r--r--sound/arm/aaci.c35
-rw-r--r--sound/arm/devdma.c80
-rw-r--r--sound/arm/devdma.h3
-rw-r--r--sound/core/control.c9
-rw-r--r--sound/core/isadma.c10
-rw-r--r--sound/core/oss/mixer_oss.c4
-rw-r--r--sound/core/pcm.c6
-rw-r--r--sound/core/pcm_native.c83
-rw-r--r--sound/core/rawmidi.c17
-rw-r--r--sound/drivers/pcsp/pcsp.c32
-rw-r--r--sound/drivers/pcsp/pcsp.h2
-rw-r--r--sound/drivers/pcsp/pcsp_mixer.c35
-rw-r--r--sound/i2c/cs8427.c15
-rw-r--r--sound/i2c/other/Makefile3
-rw-r--r--sound/i2c/other/ak4113.c639
-rw-r--r--sound/i2c/other/ak4xxx-adda.c136
-rw-r--r--sound/i2c/other/tea575x-tuner.c2
-rw-r--r--sound/isa/Kconfig12
-rw-r--r--sound/isa/cmi8330.c4
-rw-r--r--sound/isa/cs423x/cs4236.c13
-rw-r--r--sound/isa/cs423x/cs4236_lib.c241
-rw-r--r--sound/isa/es1688/es1688_lib.c2
-rw-r--r--sound/isa/es18xx.c221
-rw-r--r--sound/isa/opti9xx/miro.c783
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c110
-rw-r--r--sound/isa/sb/sb_mixer.c4
-rw-r--r--sound/isa/sscape.c727
-rw-r--r--sound/isa/wss/wss_lib.c105
-rw-r--r--sound/oss/Kconfig12
-rw-r--r--sound/oss/Makefile1
-rw-r--r--sound/oss/audio.c2
-rw-r--r--sound/oss/midi_synth.c2
-rw-r--r--sound/oss/mpu401.c2
-rw-r--r--sound/oss/sh_dac_audio.c3
-rw-r--r--sound/oss/sscape.c1480
-rw-r--r--sound/pci/Kconfig1
-rw-r--r--sound/pci/ac97/ac97_codec.c6
-rw-r--r--sound/pci/ac97/ac97_patch.c12
-rw-r--r--sound/pci/azt3328.c4
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c4
-rw-r--r--sound/pci/ca0106/ca0106_proc.c4
-rw-r--r--sound/pci/cmipci.c4
-rw-r--r--sound/pci/ctxfi/ctatc.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c3
-rw-r--r--sound/pci/emu10k1/emumixer.c4
-rw-r--r--sound/pci/emu10k1/emuproc.c4
-rw-r--r--sound/pci/emu10k1/io.c2
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/fm801.c40
-rw-r--r--sound/pci/hda/Kconfig13
-rw-r--r--sound/pci/hda/hda_beep.c114
-rw-r--r--sound/pci/hda/hda_beep.h10
-rw-r--r--sound/pci/hda/hda_codec.c607
-rw-r--r--sound/pci/hda/hda_codec.h11
-rw-r--r--sound/pci/hda/hda_eld.c20
-rw-r--r--sound/pci/hda/hda_generic.c17
-rw-r--r--sound/pci/hda/hda_hwdep.c38
-rw-r--r--sound/pci/hda/hda_intel.c50
-rw-r--r--sound/pci/hda/hda_local.h69
-rw-r--r--sound/pci/hda/hda_proc.c70
-rw-r--r--sound/pci/hda/patch_analog.c61
-rw-r--r--sound/pci/hda/patch_ca0110.c4
-rw-r--r--sound/pci/hda/patch_cirrus.c31
-rw-r--r--sound/pci/hda/patch_cmedia.c4
-rw-r--r--sound/pci/hda/patch_conexant.c189
-rw-r--r--sound/pci/hda/patch_intelhdmi.c488
-rw-r--r--sound/pci/hda/patch_realtek.c440
-rw-r--r--sound/pci/hda/patch_sigmatel.c149
-rw-r--r--sound/pci/hda/patch_via.c3509
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/ice1712.c12
-rw-r--r--sound/pci/ice1712/ice1712.h14
-rw-r--r--sound/pci/ice1712/ice1724.c103
-rw-r--r--sound/pci/ice1712/juli.c56
-rw-r--r--sound/pci/ice1712/quartet.c1130
-rw-r--r--sound/pci/ice1712/quartet.h10
-rw-r--r--sound/pci/intel8x0.c6
-rw-r--r--sound/pci/oxygen/Makefile3
-rw-r--r--sound/pci/oxygen/cs2000.h83
-rw-r--r--sound/pci/oxygen/hifier.c61
-rw-r--r--sound/pci/oxygen/oxygen.c248
-rw-r--r--sound/pci/oxygen/oxygen.h5
-rw-r--r--sound/pci/oxygen/oxygen_lib.c29
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c52
-rw-r--r--sound/pci/oxygen/oxygen_pcm.c19
-rw-r--r--sound/pci/oxygen/virtuoso.c1105
-rw-r--r--sound/pci/oxygen/xonar.h50
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c434
-rw-r--r--sound/pci/oxygen/xonar_hdmi.c128
-rw-r--r--sound/pci/oxygen/xonar_lib.c132
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c1115
-rw-r--r--sound/ppc/awacs.c12
-rw-r--r--sound/ppc/burgundy.c8
-rw-r--r--sound/ppc/tumbler.c2
-rw-r--r--sound/sh/Kconfig8
-rw-r--r--sound/sh/Makefile2
-rw-r--r--sound/sh/sh_dac_audio.c453
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/au1x/dbdma2.c115
-rw-r--r--sound/soc/au1x/psc-ac97.c243
-rw-r--r--sound/soc/au1x/psc-i2s.c189
-rw-r--r--sound/soc/au1x/psc.h7
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c7
-rw-r--r--sound/soc/blackfin/bf5xx-ad1938.c9
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c15
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c9
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c45
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h11
-rw-r--r--sound/soc/codecs/Kconfig25
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1836.c12
-rw-r--r--sound/soc/codecs/ad1938.c12
-rw-r--r--sound/soc/codecs/ad1980.c5
-rw-r--r--sound/soc/codecs/ad73311.c8
-rw-r--r--sound/soc/codecs/ads117x.c123
-rw-r--r--sound/soc/codecs/ads117x.h13
-rw-r--r--sound/soc/codecs/ak4104.c8
-rw-r--r--sound/soc/codecs/ak4535.c9
-rw-r--r--sound/soc/codecs/ak4642.c9
-rw-r--r--sound/soc/codecs/ak4671.c815
-rw-r--r--sound/soc/codecs/ak4671.h156
-rw-r--r--sound/soc/codecs/cs4270.c28
-rw-r--r--sound/soc/codecs/cx20442.c12
-rw-r--r--sound/soc/codecs/pcm3008.c9
-rw-r--r--sound/soc/codecs/ssm2602.c9
-rw-r--r--sound/soc/codecs/stac9766.c3
-rw-r--r--sound/soc/codecs/tlv320aic23.c11
-rw-r--r--sound/soc/codecs/tlv320aic26.c11
-rw-r--r--sound/soc/codecs/tlv320aic3x.c11
-rw-r--r--sound/soc/codecs/tlv320dac33.c1229
-rw-r--r--sound/soc/codecs/tlv320dac33.h267
-rw-r--r--sound/soc/codecs/tpa6130a2.c463
-rw-r--r--sound/soc/codecs/tpa6130a2.h61
-rw-r--r--sound/soc/codecs/twl4030.c452
-rw-r--r--sound/soc/codecs/twl4030.h242
-rw-r--r--sound/soc/codecs/uda134x.c9
-rw-r--r--sound/soc/codecs/uda1380.c9
-rw-r--r--sound/soc/codecs/wm8350.c32
-rw-r--r--sound/soc/codecs/wm8400.c32
-rw-r--r--sound/soc/codecs/wm8510.c14
-rw-r--r--sound/soc/codecs/wm8523.c26
-rw-r--r--sound/soc/codecs/wm8580.c30
-rw-r--r--sound/soc/codecs/wm8711.c633
-rw-r--r--sound/soc/codecs/wm8711.h42
-rw-r--r--sound/soc/codecs/wm8727.c135
-rw-r--r--sound/soc/codecs/wm8727.h21
-rw-r--r--sound/soc/codecs/wm8728.c10
-rw-r--r--sound/soc/codecs/wm8731.c94
-rw-r--r--sound/soc/codecs/wm8750.c9
-rw-r--r--sound/soc/codecs/wm8753.c49
-rw-r--r--sound/soc/codecs/wm8776.c43
-rw-r--r--sound/soc/codecs/wm8900.c34
-rw-r--r--sound/soc/codecs/wm8903.c28
-rw-r--r--sound/soc/codecs/wm8940.c28
-rw-r--r--sound/soc/codecs/wm8960.c30
-rw-r--r--sound/soc/codecs/wm8961.c27
-rw-r--r--sound/soc/codecs/wm8971.c11
-rw-r--r--sound/soc/codecs/wm8974.c36
-rw-r--r--sound/soc/codecs/wm8988.c44
-rw-r--r--sound/soc/codecs/wm8990.c14
-rw-r--r--sound/soc/codecs/wm8993.c49
-rw-r--r--sound/soc/codecs/wm9081.c27
-rw-r--r--sound/soc/codecs/wm9705.c7
-rw-r--r--sound/soc/codecs/wm9712.c7
-rw-r--r--sound/soc/codecs/wm9713.c32
-rw-r--r--sound/soc/codecs/wm_hubs.c51
-rw-r--r--sound/soc/codecs/wm_hubs.h5
-rw-r--r--sound/soc/davinci/Kconfig4
-rw-r--r--sound/soc/davinci/davinci-evm.c7
-rw-r--r--sound/soc/davinci/davinci-i2s.c85
-rw-r--r--sound/soc/davinci/davinci-mcasp.c18
-rw-r--r--sound/soc/davinci/davinci-mcasp.h5
-rw-r--r--sound/soc/davinci/davinci-pcm.c571
-rw-r--r--sound/soc/davinci/davinci-pcm.h2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c123
-rw-r--r--sound/soc/fsl/mpc5200_dma.h24
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c39
-rw-r--r--sound/soc/imx/mx27vis_wm8974.c2
-rw-r--r--sound/soc/omap/Kconfig23
-rw-r--r--sound/soc/omap/Makefile4
-rw-r--r--sound/soc/omap/am3517evm.c202
-rw-r--r--sound/soc/omap/ams-delta.c4
-rw-r--r--sound/soc/omap/igep0020.c148
-rw-r--r--sound/soc/omap/omap-mcbsp.c63
-rw-r--r--sound/soc/omap/omap3evm.c7
-rw-r--r--sound/soc/omap/omap3pandora.c24
-rw-r--r--sound/soc/omap/overo.c4
-rw-r--r--sound/soc/pxa/Kconfig12
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/pxa-ssp.c20
-rw-r--r--sound/soc/pxa/raumfeld.c335
-rw-r--r--sound/soc/pxa/zylonite.c5
-rw-r--r--sound/soc/s3c24xx/Kconfig12
-rw-r--r--sound/soc/s3c24xx/Makefile6
-rw-r--r--sound/soc/s3c24xx/jive_wm8750.c2
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c2
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c10
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c11
-rw-r--r--sound/soc/s3c24xx/s3c-dma.c (renamed from sound/soc/s3c24xx/s3c24xx-pcm.c)88
-rw-r--r--sound/soc/s3c24xx/s3c-dma.h (renamed from sound/soc/s3c24xx/s3c24xx-pcm.h)8
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c35
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h4
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.c552
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.h123
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c7
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c13
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c14
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_hermes.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c2
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c26
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h1
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c2
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c268
-rw-r--r--sound/soc/s6000/s6000-pcm.c4
-rw-r--r--sound/soc/sh/Kconfig1
-rw-r--r--sound/soc/sh/fsi.c271
-rw-r--r--sound/soc/soc-cache.c46
-rw-r--r--sound/soc/soc-core.c566
-rw-r--r--sound/soc/soc-dapm.c135
-rw-r--r--sound/soc/soc-jack.c6
-rw-r--r--sound/soc/soc-utils.c74
-rw-r--r--sound/usb/usbaudio.c38
-rw-r--r--sound/usb/usbaudio.h7
-rw-r--r--sound/usb/usbmidi.c208
-rw-r--r--sound/usb/usbmixer_maps.c23
-rw-r--r--sound/usb/usbquirks.h23
-rw-r--r--sound/usb/usx2y/us122l.c135
-rw-r--r--sound/usb/usx2y/us122l.h4
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c8
-rw-r--r--sound/usb/usx2y/usbusx2y.c28
-rw-r--r--sound/usb/usx2y/usbusx2y.h6
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c34
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c8
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-bench.txt120
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt34
-rw-r--r--tools/perf/Documentation/perf-kmem.txt44
-rw-r--r--tools/perf/Documentation/perf-probe.txt49
-rw-r--r--tools/perf/Documentation/perf-record.txt16
-rw-r--r--tools/perf/Documentation/perf-report.txt8
-rw-r--r--tools/perf/Documentation/perf-timechart.txt5
-rw-r--r--tools/perf/Documentation/perf-trace-perl.txt219
-rw-r--r--tools/perf/Documentation/perf-trace.txt11
-rw-r--r--tools/perf/Makefile151
-rw-r--r--tools/perf/bench/bench.h17
-rw-r--r--tools/perf/bench/mem-memcpy.c193
-rw-r--r--tools/perf/bench/sched-messaging.c336
-rw-r--r--tools/perf/bench/sched-pipe.c124
-rw-r--r--tools/perf/builtin-annotate.c885
-rw-r--r--tools/perf/builtin-bench.c196
-rw-r--r--tools/perf/builtin-buildid-list.c116
-rw-r--r--tools/perf/builtin-help.c16
-rw-r--r--tools/perf/builtin-kmem.c807
-rw-r--r--tools/perf/builtin-probe.c242
-rw-r--r--tools/perf/builtin-record.c345
-rw-r--r--tools/perf/builtin-report.c1147
-rw-r--r--tools/perf/builtin-sched.c351
-rw-r--r--tools/perf/builtin-stat.c34
-rw-r--r--tools/perf/builtin-timechart.c267
-rw-r--r--tools/perf/builtin-top.c503
-rw-r--r--tools/perf/builtin-trace.c418
-rw-r--r--tools/perf/builtin.h4
-rw-r--r--tools/perf/command-list.txt4
-rw-r--r--tools/perf/design.txt2
-rw-r--r--tools/perf/perf.c86
-rw-r--r--tools/perf/perf.h12
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c134
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.xs41
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL17
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/README59
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm55
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm192
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm88
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/typemap1
-rw-r--r--tools/perf/scripts/perl/bin/check-perf-trace-record7
-rw-r--r--tools/perf/scripts/perl/bin/check-perf-trace-report5
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report5
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report5
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-record6
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report5
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-record2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-report6
-rw-r--r--tools/perf/scripts/perl/check-perf-trace.pl106
-rw-r--r--tools/perf/scripts/perl/rw-by-file.pl105
-rw-r--r--tools/perf/scripts/perl/rw-by-pid.pl170
-rw-r--r--tools/perf/scripts/perl/wakeup-latency.pl103
-rw-r--r--tools/perf/scripts/perl/workqueue-stats.pl129
-rw-r--r--tools/perf/util/cache.h11
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/color.h6
-rw-r--r--tools/perf/util/ctype.c8
-rw-r--r--tools/perf/util/data_map.c291
-rw-r--r--tools/perf/util/data_map.h32
-rw-r--r--tools/perf/util/debug.c4
-rw-r--r--tools/perf/util/debug.h9
-rw-r--r--tools/perf/util/debugfs.c241
-rw-r--r--tools/perf/util/debugfs.h25
-rw-r--r--tools/perf/util/event.c312
-rw-r--r--tools/perf/util/event.h75
-rw-r--r--tools/perf/util/exec_cmd.h6
-rw-r--r--tools/perf/util/header.c403
-rw-r--r--tools/perf/util/header.h76
-rw-r--r--tools/perf/util/help.h6
-rw-r--r--tools/perf/util/hist.c202
-rw-r--r--tools/perf/util/hist.h50
-rw-r--r--tools/perf/util/include/asm/asm-offsets.h1
-rw-r--r--tools/perf/util/include/asm/bitops.h18
-rw-r--r--tools/perf/util/include/asm/bug.h22
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/asm/swab.h1
-rw-r--r--tools/perf/util/include/asm/uaccess.h14
-rw-r--r--tools/perf/util/include/linux/bitmap.h3
-rw-r--r--tools/perf/util/include/linux/bitops.h29
-rw-r--r--tools/perf/util/include/linux/compiler.h10
-rw-r--r--tools/perf/util/include/linux/ctype.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h76
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/include/linux/types.h9
-rw-r--r--tools/perf/util/levenshtein.h6
-rw-r--r--tools/perf/util/map.c99
-rw-r--r--tools/perf/util/module.c545
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/parse-events.c155
-rw-r--r--tools/perf/util/parse-events.h8
-rw-r--r--tools/perf/util/parse-options.h6
-rw-r--r--tools/perf/util/probe-event.c484
-rw-r--r--tools/perf/util/probe-event.h18
-rw-r--r--tools/perf/util/probe-finder.c732
-rw-r--r--tools/perf/util/probe-finder.h57
-rw-r--r--tools/perf/util/quote.h6
-rw-r--r--tools/perf/util/run-command.h6
-rw-r--r--tools/perf/util/sigchain.h6
-rw-r--r--tools/perf/util/sort.c290
-rw-r--r--tools/perf/util/sort.h99
-rw-r--r--tools/perf/util/strbuf.h6
-rw-r--r--tools/perf/util/string.c194
-rw-r--r--tools/perf/util/string.h10
-rw-r--r--tools/perf/util/strlist.h6
-rw-r--r--tools/perf/util/svghelper.h6
-rw-r--r--tools/perf/util/symbol.c1193
-rw-r--r--tools/perf/util/symbol.h92
-rw-r--r--tools/perf/util/thread.c250
-rw-r--r--tools/perf/util/thread.h50
-rw-r--r--tools/perf/util/trace-event-info.c26
-rw-r--r--tools/perf/util/trace-event-parse.c573
-rw-r--r--tools/perf/util/trace-event-perl.c598
-rw-r--r--tools/perf/util/trace-event-perl.h51
-rw-r--r--tools/perf/util/trace-event-read.c11
-rw-r--r--tools/perf/util/trace-event.h64
-rw-r--r--tools/perf/util/types.h6
-rw-r--r--tools/perf/util/util.h31
-rw-r--r--tools/perf/util/values.h6
-rw-r--r--tools/perf/util/wrapper.c61
785 files changed, 48514 insertions, 19962 deletions
diff --git a/Documentation/DocBook/tracepoint.tmpl b/Documentation/DocBook/tracepoint.tmpl
index b0756d0fd579..8bca1d5cec09 100644
--- a/Documentation/DocBook/tracepoint.tmpl
+++ b/Documentation/DocBook/tracepoint.tmpl
@@ -86,4 +86,9 @@
86!Iinclude/trace/events/irq.h 86!Iinclude/trace/events/irq.h
87 </chapter> 87 </chapter>
88 88
89 <chapter id="signal">
90 <title>SIGNAL</title>
91!Iinclude/trace/events/signal.h
92 </chapter>
93
89</book> 94</book>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 72ae06f73acf..a004b04ffd3a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,6 +6,21 @@ be removed from this file.
6 6
7--------------------------- 7---------------------------
8 8
9What: USER_SCHED
10When: 2.6.34
11
12Why: USER_SCHED was implemented as a proof of concept for group scheduling.
13 The effect of USER_SCHED can already be achieved from userspace with
14 the help of libcgroup. The removal of USER_SCHED will also simplify
15 the scheduler code with the removal of one major ifdef. There are also
16 issues USER_SCHED has with USER_NS. A decision was taken not to fix
17 those and instead remove USER_SCHED. Also new group scheduling
18 features will not be implemented for USER_SCHED.
19
20Who: Dhaval Giani <dhaval@linux.vnet.ibm.com>
21
22---------------------------
23
9What: PRISM54 24What: PRISM54
10When: 2.6.34 25When: 2.6.34
11 26
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 2c48f945546b..4af0018533f2 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1072,7 +1072,8 @@ second). The meanings of the columns are as follows, from left to right:
1072- irq: servicing interrupts 1072- irq: servicing interrupts
1073- softirq: servicing softirqs 1073- softirq: servicing softirqs
1074- steal: involuntary wait 1074- steal: involuntary wait
1075- guest: running a guest 1075- guest: running a normal guest
1076- guest_nice: running a niced guest
1076 1077
1077The "intr" line gives counts of interrupts serviced since boot time, for each 1078The "intr" line gives counts of interrupts serviced since boot time, for each
1078of the possible system interrupts. The first column is the total of all 1079of the possible system interrupts. The first column is the total of all
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d8ce217d1f72..495a39a77341 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -344,6 +344,15 @@ and is between 256 and 4096 characters. It is defined in the file
344 Change the amount of debugging information output 344 Change the amount of debugging information output
345 when initialising the APIC and IO-APIC components. 345 when initialising the APIC and IO-APIC components.
346 346
347 show_lapic= [APIC,X86] Advanced Programmable Interrupt Controller
348 Limit apic dumping. The parameter defines the maximal
349 number of local apics being dumped. Also it is possible
350 to set it to "all" by meaning -- no limit here.
351 Format: { 1 (default) | 2 | ... | all }.
352 The parameter valid if only apic=debug or
353 apic=verbose is specified.
354 Example: apic=debug show_lapic=all
355
347 apm= [APM] Advanced Power Management 356 apm= [APM] Advanced Power Management
348 See header of arch/x86/kernel/apm_32.c. 357 See header of arch/x86/kernel/apm_32.c.
349 358
@@ -2186,6 +2195,8 @@ and is between 256 and 4096 characters. It is defined in the file
2186 2195
2187 sbni= [NET] Granch SBNI12 leased line adapter 2196 sbni= [NET] Granch SBNI12 leased line adapter
2188 2197
2198 sched_debug [KNL] Enables verbose scheduler debug messages.
2199
2189 sc1200wdt= [HW,WDT] SC1200 WDT (watchdog) driver 2200 sc1200wdt= [HW,WDT] SC1200 WDT (watchdog) driver
2190 Format: <io>[,<timeout>[,<isapnp>]] 2201 Format: <io>[,<timeout>[,<isapnp>]]
2191 2202
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index fd9a2f67edf2..8923597bd2bd 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -798,6 +798,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
798 setup before initializing the codecs. This option is 798 setup before initializing the codecs. This option is
799 available only when CONFIG_SND_HDA_PATCH_LOADER=y is set. 799 available only when CONFIG_SND_HDA_PATCH_LOADER=y is set.
800 See HD-Audio.txt for details. 800 See HD-Audio.txt for details.
801 beep_mode - Selects the beep registration mode (0=off, 1=on, 2=
802 dynamic registration via mute switch on/off); the default
803 value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig.
801 804
802 [Single (global) options] 805 [Single (global) options]
803 single_cmd - Use single immediate commands to communicate with 806 single_cmd - Use single immediate commands to communicate with
@@ -1454,6 +1457,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1454 1457
1455 Module for internal PC-Speaker. 1458 Module for internal PC-Speaker.
1456 1459
1460 nopcm - Disable PC-Speaker PCM sound. Only beeps remain.
1457 nforce_wa - enable NForce chipset workaround. Expect bad sound. 1461 nforce_wa - enable NForce chipset workaround. Expect bad sound.
1458 1462
1459 This module supports system beeps, some kind of PCM playback and 1463 This module supports system beeps, some kind of PCM playback and
@@ -1631,7 +1635,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1631 Module snd-sscape 1635 Module snd-sscape
1632 ----------------- 1636 -----------------
1633 1637
1634 Module for ENSONIQ SoundScape PnP cards. 1638 Module for ENSONIQ SoundScape cards.
1635 1639
1636 port - Port # (PnP setup) 1640 port - Port # (PnP setup)
1637 wss_port - WSS Port # (PnP setup) 1641 wss_port - WSS Port # (PnP setup)
@@ -1639,10 +1643,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1639 mpu_irq - MPU-401 IRQ # (PnP setup) 1643 mpu_irq - MPU-401 IRQ # (PnP setup)
1640 dma - DMA # (PnP setup) 1644 dma - DMA # (PnP setup)
1641 dma2 - 2nd DMA # (PnP setup, -1 to disable) 1645 dma2 - 2nd DMA # (PnP setup, -1 to disable)
1646 joystick - Enable gameport - 0 = disable (default), 1 = enable
1647
1648 This module supports multiple cards.
1642 1649
1643 This module supports multiple cards. ISA PnP must be enabled. 1650 The driver requires the firmware loader support on kernel.
1644 You need sscape_ctl tool in alsa-tools package for loading
1645 the microcode.
1646 1651
1647 Module snd-sun-amd7930 (on sparc only) 1652 Module snd-sun-amd7930 (on sparc only)
1648 -------------------------------------- 1653 --------------------------------------
diff --git a/Documentation/sound/alsa/ControlNames.txt b/Documentation/sound/alsa/ControlNames.txt
index 5b18298e9495..fea65bb6269e 100644
--- a/Documentation/sound/alsa/ControlNames.txt
+++ b/Documentation/sound/alsa/ControlNames.txt
@@ -18,8 +18,9 @@ SOURCE:
18 Master 18 Master
19 Master Mono 19 Master Mono
20 Hardware Master 20 Hardware Master
21 Speaker (internal speaker)
21 Headphone 22 Headphone
22 PC Speaker 23 Beep (beep generator)
23 Phone 24 Phone
24 Phone Input 25 Phone Input
25 Phone Output 26 Phone Output
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 4c7f9aee5c4e..9000cd84d076 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -391,6 +391,7 @@ STAC92HD83*
391 ref Reference board 391 ref Reference board
392 mic-ref Reference board with power management for ports 392 mic-ref Reference board with power management for ports
393 dell-s14 Dell laptop 393 dell-s14 Dell laptop
394 hp HP laptops with (inverted) mute-LED
394 auto BIOS setup (default) 395 auto BIOS setup (default)
395 396
396STAC9872 397STAC9872
diff --git a/Documentation/sysctl/ctl_unnumbered.txt b/Documentation/sysctl/ctl_unnumbered.txt
deleted file mode 100644
index 23003a8ea3e7..000000000000
--- a/Documentation/sysctl/ctl_unnumbered.txt
+++ /dev/null
@@ -1,22 +0,0 @@
1
2Except for a few extremely rare exceptions user space applications do not use
3the binary sysctl interface. Instead everyone uses /proc/sys/... with
4readable ascii names.
5
6Recently the kernel has started supporting setting the binary sysctl value to
7CTL_UNNUMBERED so we no longer need to assign a binary sysctl path to allow
8sysctls to show up in /proc/sys.
9
10Assigning binary sysctl numbers is an endless source of conflicts in sysctl.h,
11breaking of the user space ABI (because of those conflicts), and maintenance
12problems. A complete pass through all of the sysctl users revealed multiple
13instances where the sysctl binary interface was broken and had gone undetected
14for years.
15
16So please do not add new binary sysctl numbers. They are unneeded and
17problematic.
18
19If you really need a new binary sysctl number please first merge your sysctl
20into the kernel and then as a separate patch allocate a binary sysctl number.
21
22(ebiederm@xmission.com, June 2007)
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
new file mode 100644
index 000000000000..47aabeebbdf6
--- /dev/null
+++ b/Documentation/trace/kprobetrace.txt
@@ -0,0 +1,149 @@
1 Kprobe-based Event Tracing
2 ==========================
3
4 Documentation is written by Masami Hiramatsu
5
6
7Overview
8--------
9These events are similar to tracepoint based events. Instead of Tracepoint,
10this is based on kprobes (kprobe and kretprobe). So it can probe wherever
11kprobes can probe (this means, all functions body except for __kprobes
12functions). Unlike the Tracepoint based event, this can be added and removed
13dynamically, on the fly.
14
15To enable this feature, build your kernel with CONFIG_KPROBE_TRACING=y.
16
17Similar to the events tracer, this doesn't need to be activated via
18current_tracer. Instead of that, add probe points via
19/sys/kernel/debug/tracing/kprobe_events, and enable it via
20/sys/kernel/debug/tracing/events/kprobes/<EVENT>/enabled.
21
22
23Synopsis of kprobe_events
24-------------------------
25 p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS] : Set a probe
26 r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe
27
28 GRP : Group name. If omitted, use "kprobes" for it.
29 EVENT : Event name. If omitted, the event name is generated
30 based on SYMBOL+offs or MEMADDR.
31 SYMBOL[+offs] : Symbol+offset where the probe is inserted.
32 MEMADDR : Address where the probe is inserted.
33
34 FETCHARGS : Arguments. Each probe can have up to 128 args.
35 %REG : Fetch register REG
36 @ADDR : Fetch memory at ADDR (ADDR should be in kernel)
37 @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol)
38 $stackN : Fetch Nth entry of stack (N >= 0)
39 $stack : Fetch stack address.
40 $argN : Fetch function argument. (N >= 0)(*)
41 $retval : Fetch return value.(**)
42 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(***)
43 NAME=FETCHARG: Set NAME as the argument name of FETCHARG.
44
45 (*) aN may not correct on asmlinkaged functions and at the middle of
46 function body.
47 (**) only for return probe.
48 (***) this is useful for fetching a field of data structures.
49
50
51Per-Probe Event Filtering
52-------------------------
53 Per-probe event filtering feature allows you to set different filter on each
54probe and gives you what arguments will be shown in trace buffer. If an event
55name is specified right after 'p:' or 'r:' in kprobe_events, it adds an event
56under tracing/events/kprobes/<EVENT>, at the directory you can see 'id',
57'enabled', 'format' and 'filter'.
58
59enabled:
60 You can enable/disable the probe by writing 1 or 0 on it.
61
62format:
63 This shows the format of this probe event.
64
65filter:
66 You can write filtering rules of this event.
67
68id:
69 This shows the id of this probe event.
70
71
72Event Profiling
73---------------
74 You can check the total number of probe hits and probe miss-hits via
75/sys/kernel/debug/tracing/kprobe_profile.
76 The first column is event name, the second is the number of probe hits,
77the third is the number of probe miss-hits.
78
79
80Usage examples
81--------------
82To add a probe as a new event, write a new definition to kprobe_events
83as below.
84
85 echo p:myprobe do_sys_open dfd=$arg0 filename=$arg1 flags=$arg2 mode=$arg3 > /sys/kernel/debug/tracing/kprobe_events
86
87 This sets a kprobe on the top of do_sys_open() function with recording
881st to 4th arguments as "myprobe" event. As this example shows, users can
89choose more familiar names for each arguments.
90
91 echo r:myretprobe do_sys_open $retval >> /sys/kernel/debug/tracing/kprobe_events
92
93 This sets a kretprobe on the return point of do_sys_open() function with
94recording return value as "myretprobe" event.
95 You can see the format of these events via
96/sys/kernel/debug/tracing/events/kprobes/<EVENT>/format.
97
98 cat /sys/kernel/debug/tracing/events/kprobes/myprobe/format
99name: myprobe
100ID: 75
101format:
102 field:unsigned short common_type; offset:0; size:2;
103 field:unsigned char common_flags; offset:2; size:1;
104 field:unsigned char common_preempt_count; offset:3; size:1;
105 field:int common_pid; offset:4; size:4;
106 field:int common_tgid; offset:8; size:4;
107
108 field: unsigned long ip; offset:16;tsize:8;
109 field: int nargs; offset:24;tsize:4;
110 field: unsigned long dfd; offset:32;tsize:8;
111 field: unsigned long filename; offset:40;tsize:8;
112 field: unsigned long flags; offset:48;tsize:8;
113 field: unsigned long mode; offset:56;tsize:8;
114
115print fmt: "(%lx) dfd=%lx filename=%lx flags=%lx mode=%lx", REC->ip, REC->dfd, REC->filename, REC->flags, REC->mode
116
117
118 You can see that the event has 4 arguments as in the expressions you specified.
119
120 echo > /sys/kernel/debug/tracing/kprobe_events
121
122 This clears all probe points.
123
124 Right after definition, each event is disabled by default. For tracing these
125events, you need to enable it.
126
127 echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
128 echo 1 > /sys/kernel/debug/tracing/events/kprobes/myretprobe/enable
129
130 And you can see the traced information via /sys/kernel/debug/tracing/trace.
131
132 cat /sys/kernel/debug/tracing/trace
133# tracer: nop
134#
135# TASK-PID CPU# TIMESTAMP FUNCTION
136# | | | | |
137 <...>-1447 [001] 1038282.286875: myprobe: (do_sys_open+0x0/0xd6) dfd=3 filename=7fffd1ec4440 flags=8000 mode=0
138 <...>-1447 [001] 1038282.286878: myretprobe: (sys_openat+0xc/0xe <- do_sys_open) $retval=fffffffffffffffe
139 <...>-1447 [001] 1038282.286885: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=40413c flags=8000 mode=1b6
140 <...>-1447 [001] 1038282.286915: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $retval=3
141 <...>-1447 [001] 1038282.286969: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=4041c6 flags=98800 mode=10
142 <...>-1447 [001] 1038282.286976: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $retval=3
143
144
145 Each line shows when the kernel hits an event, and <- SYMBOL means kernel
146returns from SYMBOL(e.g. "sys_open+0x1b/0x1d <- do_sys_open" means kernel
147returns from do_sys_open to sys_open+0x1b).
148
149
diff --git a/arch/Kconfig b/arch/Kconfig
index 7f418bbc261a..eef3bbb97075 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -126,4 +126,11 @@ config HAVE_DMA_API_DEBUG
126config HAVE_DEFAULT_NO_SPIN_MUTEXES 126config HAVE_DEFAULT_NO_SPIN_MUTEXES
127 bool 127 bool
128 128
129config HAVE_HW_BREAKPOINT
130 bool
131 depends on HAVE_PERF_EVENTS
132 select ANON_INODES
133 select PERF_EVENTS
134
135
129source "kernel/gcov/Kconfig" 136source "kernel/gcov/Kconfig"
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 8ac9b8424007..346485910732 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -22,47 +22,42 @@ static unsigned int isa_membase, isa_portbase, isa_portshift;
22 22
23static ctl_table ctl_isa_vars[4] = { 23static ctl_table ctl_isa_vars[4] = {
24 { 24 {
25 .ctl_name = BUS_ISA_MEM_BASE,
26 .procname = "membase", 25 .procname = "membase",
27 .data = &isa_membase, 26 .data = &isa_membase,
28 .maxlen = sizeof(isa_membase), 27 .maxlen = sizeof(isa_membase),
29 .mode = 0444, 28 .mode = 0444,
30 .proc_handler = &proc_dointvec, 29 .proc_handler = proc_dointvec,
31 }, { 30 }, {
32 .ctl_name = BUS_ISA_PORT_BASE,
33 .procname = "portbase", 31 .procname = "portbase",
34 .data = &isa_portbase, 32 .data = &isa_portbase,
35 .maxlen = sizeof(isa_portbase), 33 .maxlen = sizeof(isa_portbase),
36 .mode = 0444, 34 .mode = 0444,
37 .proc_handler = &proc_dointvec, 35 .proc_handler = proc_dointvec,
38 }, { 36 }, {
39 .ctl_name = BUS_ISA_PORT_SHIFT,
40 .procname = "portshift", 37 .procname = "portshift",
41 .data = &isa_portshift, 38 .data = &isa_portshift,
42 .maxlen = sizeof(isa_portshift), 39 .maxlen = sizeof(isa_portshift),
43 .mode = 0444, 40 .mode = 0444,
44 .proc_handler = &proc_dointvec, 41 .proc_handler = proc_dointvec,
45 }, {0} 42 }, {}
46}; 43};
47 44
48static struct ctl_table_header *isa_sysctl_header; 45static struct ctl_table_header *isa_sysctl_header;
49 46
50static ctl_table ctl_isa[2] = { 47static ctl_table ctl_isa[2] = {
51 { 48 {
52 .ctl_name = CTL_BUS_ISA,
53 .procname = "isa", 49 .procname = "isa",
54 .mode = 0555, 50 .mode = 0555,
55 .child = ctl_isa_vars, 51 .child = ctl_isa_vars,
56 }, {0} 52 }, {}
57}; 53};
58 54
59static ctl_table ctl_bus[2] = { 55static ctl_table ctl_bus[2] = {
60 { 56 {
61 .ctl_name = CTL_BUS,
62 .procname = "bus", 57 .procname = "bus",
63 .mode = 0555, 58 .mode = 0555,
64 .child = ctl_isa, 59 .child = ctl_isa,
65 }, {0} 60 }, {}
66}; 61};
67 62
68void __init 63void __init
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 0da693b0f7e1..fbe6fa02c882 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -47,10 +47,6 @@ HW_DECLARE_SPINLOCK(gpio)
47 EXPORT_SYMBOL(bcmring_gpio_reg_lock); 47 EXPORT_SYMBOL(bcmring_gpio_reg_lock);
48#endif 48#endif
49 49
50/* FIXME: temporary solution */
51#define BCM_SYSCTL_REBOOT_WARM 1
52#define CTL_BCM_REBOOT 112
53
54/* sysctl */ 50/* sysctl */
55int bcmring_arch_warm_reboot; /* do a warm reboot on hard reset */ 51int bcmring_arch_warm_reboot; /* do a warm reboot on hard reset */
56 52
@@ -58,18 +54,16 @@ static struct ctl_table_header *bcmring_sysctl_header;
58 54
59static struct ctl_table bcmring_sysctl_warm_reboot[] = { 55static struct ctl_table bcmring_sysctl_warm_reboot[] = {
60 { 56 {
61 .ctl_name = BCM_SYSCTL_REBOOT_WARM,
62 .procname = "warm", 57 .procname = "warm",
63 .data = &bcmring_arch_warm_reboot, 58 .data = &bcmring_arch_warm_reboot,
64 .maxlen = sizeof(int), 59 .maxlen = sizeof(int),
65 .mode = 0644, 60 .mode = 0644,
66 .proc_handler = &proc_dointvec}, 61 .proc_handler = proc_dointvec},
67 {} 62 {}
68}; 63};
69 64
70static struct ctl_table bcmring_sysctl_reboot[] = { 65static struct ctl_table bcmring_sysctl_reboot[] = {
71 { 66 {
72 .ctl_name = CTL_BCM_REBOOT,
73 .procname = "reboot", 67 .procname = "reboot",
74 .mode = 0555, 68 .mode = 0555,
75 .child = bcmring_sysctl_warm_reboot}, 69 .child = bcmring_sysctl_warm_reboot},
diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h
index 18e4ce34ece6..e07f70ed7c53 100644
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ b/arch/arm/mach-davinci/include/mach/asp.h
@@ -51,6 +51,14 @@ struct snd_platform_data {
51 u32 rx_dma_offset; 51 u32 rx_dma_offset;
52 enum dma_event_q eventq_no; /* event queue number */ 52 enum dma_event_q eventq_no; /* event queue number */
53 unsigned int codec_fmt; 53 unsigned int codec_fmt;
54 /*
55 * Allowing this is more efficient and eliminates left and right swaps
56 * caused by underruns, but will swap the left and right channels
57 * when compared to previous behavior.
58 */
59 unsigned enable_channel_combine:1;
60 unsigned sram_size_playback;
61 unsigned sram_size_capture;
54 62
55 /* McASP specific fields */ 63 /* McASP specific fields */
56 int tdm_slots; 64 int tdm_slots;
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 0acb5560229c..08e535d92c06 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -410,6 +410,15 @@ static struct regulator_init_data sdp3430_vpll2 = {
410 .consumer_supplies = &sdp3430_vdvi_supply, 410 .consumer_supplies = &sdp3430_vdvi_supply,
411}; 411};
412 412
413static struct twl4030_codec_audio_data sdp3430_audio = {
414 .audio_mclk = 26000000,
415};
416
417static struct twl4030_codec_data sdp3430_codec = {
418 .audio_mclk = 26000000,
419 .audio = &sdp3430_audio,
420};
421
413static struct twl4030_platform_data sdp3430_twldata = { 422static struct twl4030_platform_data sdp3430_twldata = {
414 .irq_base = TWL4030_IRQ_BASE, 423 .irq_base = TWL4030_IRQ_BASE,
415 .irq_end = TWL4030_IRQ_END, 424 .irq_end = TWL4030_IRQ_END,
@@ -420,6 +429,7 @@ static struct twl4030_platform_data sdp3430_twldata = {
420 .madc = &sdp3430_madc_data, 429 .madc = &sdp3430_madc_data,
421 .keypad = &sdp3430_kp_data, 430 .keypad = &sdp3430_kp_data,
422 .usb = &sdp3430_usb_data, 431 .usb = &sdp3430_usb_data,
432 .codec = &sdp3430_codec,
423 433
424 .vaux1 = &sdp3430_vaux1, 434 .vaux1 = &sdp3430_vaux1,
425 .vaux2 = &sdp3430_vaux2, 435 .vaux2 = &sdp3430_vaux2,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 08b0816afa61..af411e11dddf 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -254,6 +254,15 @@ static struct twl4030_usb_data beagle_usb_data = {
254 .usb_mode = T2_USB_MODE_ULPI, 254 .usb_mode = T2_USB_MODE_ULPI,
255}; 255};
256 256
257static struct twl4030_codec_audio_data beagle_audio_data = {
258 .audio_mclk = 26000000,
259};
260
261static struct twl4030_codec_data beagle_codec_data = {
262 .audio_mclk = 26000000,
263 .audio = &beagle_audio_data,
264};
265
257static struct twl4030_platform_data beagle_twldata = { 266static struct twl4030_platform_data beagle_twldata = {
258 .irq_base = TWL4030_IRQ_BASE, 267 .irq_base = TWL4030_IRQ_BASE,
259 .irq_end = TWL4030_IRQ_END, 268 .irq_end = TWL4030_IRQ_END,
@@ -261,6 +270,7 @@ static struct twl4030_platform_data beagle_twldata = {
261 /* platform_data for children goes here */ 270 /* platform_data for children goes here */
262 .usb = &beagle_usb_data, 271 .usb = &beagle_usb_data,
263 .gpio = &beagle_gpio_data, 272 .gpio = &beagle_gpio_data,
273 .codec = &beagle_codec_data,
264 .vmmc1 = &beagle_vmmc1, 274 .vmmc1 = &beagle_vmmc1,
265 .vsim = &beagle_vsim, 275 .vsim = &beagle_vsim,
266 .vdac = &beagle_vdac, 276 .vdac = &beagle_vdac,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 4c4d7f8dbd72..25ca5f6a0d3d 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -194,6 +194,15 @@ static struct twl4030_madc_platform_data omap3evm_madc_data = {
194 .irq_line = 1, 194 .irq_line = 1,
195}; 195};
196 196
197static struct twl4030_codec_audio_data omap3evm_audio_data = {
198 .audio_mclk = 26000000,
199};
200
201static struct twl4030_codec_data omap3evm_codec_data = {
202 .audio_mclk = 26000000,
203 .audio = &omap3evm_audio_data,
204};
205
197static struct twl4030_platform_data omap3evm_twldata = { 206static struct twl4030_platform_data omap3evm_twldata = {
198 .irq_base = TWL4030_IRQ_BASE, 207 .irq_base = TWL4030_IRQ_BASE,
199 .irq_end = TWL4030_IRQ_END, 208 .irq_end = TWL4030_IRQ_END,
@@ -203,6 +212,7 @@ static struct twl4030_platform_data omap3evm_twldata = {
203 .madc = &omap3evm_madc_data, 212 .madc = &omap3evm_madc_data,
204 .usb = &omap3evm_usb_data, 213 .usb = &omap3evm_usb_data,
205 .gpio = &omap3evm_gpio_data, 214 .gpio = &omap3evm_gpio_data,
215 .codec = &omap3evm_codec_data,
206}; 216};
207 217
208static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { 218static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 7519edb69155..c4be626c8422 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -281,11 +281,21 @@ static struct twl4030_usb_data omap3pandora_usb_data = {
281 .usb_mode = T2_USB_MODE_ULPI, 281 .usb_mode = T2_USB_MODE_ULPI,
282}; 282};
283 283
284static struct twl4030_codec_audio_data omap3pandora_audio_data = {
285 .audio_mclk = 26000000,
286};
287
288static struct twl4030_codec_data omap3pandora_codec_data = {
289 .audio_mclk = 26000000,
290 .audio = &omap3pandora_audio_data,
291};
292
284static struct twl4030_platform_data omap3pandora_twldata = { 293static struct twl4030_platform_data omap3pandora_twldata = {
285 .irq_base = TWL4030_IRQ_BASE, 294 .irq_base = TWL4030_IRQ_BASE,
286 .irq_end = TWL4030_IRQ_END, 295 .irq_end = TWL4030_IRQ_END,
287 .gpio = &omap3pandora_gpio_data, 296 .gpio = &omap3pandora_gpio_data,
288 .usb = &omap3pandora_usb_data, 297 .usb = &omap3pandora_usb_data,
298 .codec = &omap3pandora_codec_data,
289 .vmmc1 = &pandora_vmmc1, 299 .vmmc1 = &pandora_vmmc1,
290 .vmmc2 = &pandora_vmmc2, 300 .vmmc2 = &pandora_vmmc2,
291 .keypad = &pandora_kp_data, 301 .keypad = &pandora_kp_data,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 9917d2fddc2f..e1fb50451e19 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -329,6 +329,15 @@ static struct regulator_init_data overo_vmmc1 = {
329 .consumer_supplies = &overo_vmmc1_supply, 329 .consumer_supplies = &overo_vmmc1_supply,
330}; 330};
331 331
332static struct twl4030_codec_audio_data overo_audio_data = {
333 .audio_mclk = 26000000,
334};
335
336static struct twl4030_codec_data overo_codec_data = {
337 .audio_mclk = 26000000,
338 .audio = &overo_audio_data,
339};
340
332/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ 341/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
333 342
334static struct twl4030_platform_data overo_twldata = { 343static struct twl4030_platform_data overo_twldata = {
@@ -336,6 +345,7 @@ static struct twl4030_platform_data overo_twldata = {
336 .irq_end = TWL4030_IRQ_END, 345 .irq_end = TWL4030_IRQ_END,
337 .gpio = &overo_gpio_data, 346 .gpio = &overo_gpio_data,
338 .usb = &overo_usb_data, 347 .usb = &overo_usb_data,
348 .codec = &overo_codec_data,
339 .vmmc1 = &overo_vmmc1, 349 .vmmc1 = &overo_vmmc1,
340}; 350};
341 351
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 51e0b3ba5f3a..51df584728f6 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -230,6 +230,15 @@ static struct twl4030_madc_platform_data zoom2_madc_data = {
230 .irq_line = 1, 230 .irq_line = 1,
231}; 231};
232 232
233static struct twl4030_codec_audio_data zoom2_audio_data = {
234 .audio_mclk = 26000000,
235};
236
237static struct twl4030_codec_data zoom2_codec_data = {
238 .audio_mclk = 26000000,
239 .audio = &zoom2_audio_data,
240};
241
233static struct twl4030_platform_data zoom2_twldata = { 242static struct twl4030_platform_data zoom2_twldata = {
234 .irq_base = TWL4030_IRQ_BASE, 243 .irq_base = TWL4030_IRQ_BASE,
235 .irq_end = TWL4030_IRQ_END, 244 .irq_end = TWL4030_IRQ_END,
@@ -240,6 +249,7 @@ static struct twl4030_platform_data zoom2_twldata = {
240 .usb = &zoom2_usb_data, 249 .usb = &zoom2_usb_data,
241 .gpio = &zoom2_gpio_data, 250 .gpio = &zoom2_gpio_data,
242 .keypad = &zoom2_kp_twl4030_data, 251 .keypad = &zoom2_kp_twl4030_data,
252 .codec = &zoom2_codec_data,
243 .vmmc1 = &zoom2_vmmc1, 253 .vmmc1 = &zoom2_vmmc1,
244 .vmmc2 = &zoom2_vmmc2, 254 .vmmc2 = &zoom2_vmmc2,
245 .vsim = &zoom2_vsim, 255 .vsim = &zoom2_vsim,
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
index fc8b223bad4f..866be31872a5 100644
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ b/arch/arm/mach-s3c6400/include/mach/map.h
@@ -48,6 +48,8 @@
48#define S3C64XX_PA_IIS1 (0x7F003000) 48#define S3C64XX_PA_IIS1 (0x7F003000)
49#define S3C64XX_PA_TIMER (0x7F006000) 49#define S3C64XX_PA_TIMER (0x7F006000)
50#define S3C64XX_PA_IIC0 (0x7F004000) 50#define S3C64XX_PA_IIC0 (0x7F004000)
51#define S3C64XX_PA_PCM0 (0x7F009000)
52#define S3C64XX_PA_PCM1 (0x7F00A000)
51#define S3C64XX_PA_IISV4 (0x7F00D000) 53#define S3C64XX_PA_IISV4 (0x7F00D000)
52#define S3C64XX_PA_IIC1 (0x7F00F000) 54#define S3C64XX_PA_IIC1 (0x7F00F000)
53 55
diff --git a/arch/arm/plat-s3c/include/plat/audio.h b/arch/arm/plat-s3c/include/plat/audio.h
index de0e8da48bc3..f22d23bb6271 100644
--- a/arch/arm/plat-s3c/include/plat/audio.h
+++ b/arch/arm/plat-s3c/include/plat/audio.h
@@ -1,45 +1,17 @@
1/* arch/arm/mach-s3c2410/include/mach/audio.h 1/* arch/arm/plat-s3c/include/plat/audio.h
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2009 Samsung Electronics Co. Ltd
4 * http://www.simtec.co.uk/products/SWLINUX/ 4 * Author: Jaswinder Singh <jassi.brar@samsung.com>
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C24XX - Audio platfrom_device info
8 * 5 *
9 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
12*/ 9 */
13
14#ifndef __ASM_ARCH_AUDIO_H
15#define __ASM_ARCH_AUDIO_H __FILE__
16
17/* struct s3c24xx_iis_ops
18 *
19 * called from the s3c24xx audio core to deal with the architecture
20 * or the codec's setup and control.
21 *
22 * the pointer to itself is passed through in case the caller wants to
23 * embed this in an larger structure for easy reference to it's context.
24*/
25 10
26struct s3c24xx_iis_ops { 11/**
27 struct module *owner; 12 * struct s3c_audio_pdata - common platform data for audio device drivers
28 13 * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
29 int (*startup)(struct s3c24xx_iis_ops *me); 14 */
30 void (*shutdown)(struct s3c24xx_iis_ops *me); 15struct s3c_audio_pdata {
31 int (*suspend)(struct s3c24xx_iis_ops *me); 16 int (*cfg_gpio)(struct platform_device *);
32 int (*resume)(struct s3c24xx_iis_ops *me);
33
34 int (*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
35 int (*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
36 int (*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
37}; 17};
38
39struct s3c24xx_platdata_iis {
40 const char *codec_clk;
41 struct s3c24xx_iis_ops *ops;
42 int (*match_dev)(struct device *dev);
43};
44
45#endif /* __ASM_ARCH_AUDIO_H */
diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h
index 0f540ea1e999..932cbbbb4273 100644
--- a/arch/arm/plat-s3c/include/plat/devs.h
+++ b/arch/arm/plat-s3c/include/plat/devs.h
@@ -28,6 +28,9 @@ extern struct platform_device s3c64xx_device_iis0;
28extern struct platform_device s3c64xx_device_iis1; 28extern struct platform_device s3c64xx_device_iis1;
29extern struct platform_device s3c64xx_device_iisv4; 29extern struct platform_device s3c64xx_device_iisv4;
30 30
31extern struct platform_device s3c64xx_device_pcm0;
32extern struct platform_device s3c64xx_device_pcm1;
33
31extern struct platform_device s3c_device_fb; 34extern struct platform_device s3c_device_fb;
32extern struct platform_device s3c_device_usb; 35extern struct platform_device s3c_device_usb;
33extern struct platform_device s3c_device_lcd; 36extern struct platform_device s3c_device_lcd;
diff --git a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
index 07659dad1748..abf2fbc2eb2f 100644
--- a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
+++ b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
@@ -67,6 +67,8 @@
67#define S3C2412_IISMOD_BCLK_MASK (3 << 1) 67#define S3C2412_IISMOD_BCLK_MASK (3 << 1)
68#define S3C2412_IISMOD_8BIT (1 << 0) 68#define S3C2412_IISMOD_8BIT (1 << 0)
69 69
70#define S3C64XX_IISMOD_CDCLKCON (1 << 12)
71
70#define S3C2412_IISPSR_PSREN (1 << 15) 72#define S3C2412_IISPSR_PSREN (1 << 15)
71 73
72#define S3C2412_IISFIC_TXFLUSH (1 << 15) 74#define S3C2412_IISFIC_TXFLUSH (1 << 15)
diff --git a/arch/arm/plat-s3c64xx/dev-audio.c b/arch/arm/plat-s3c64xx/dev-audio.c
index 1322beb40dd7..a21a88fbb7e3 100644
--- a/arch/arm/plat-s3c64xx/dev-audio.c
+++ b/arch/arm/plat-s3c64xx/dev-audio.c
@@ -15,9 +15,14 @@
15 15
16#include <mach/irqs.h> 16#include <mach/irqs.h>
17#include <mach/map.h> 17#include <mach/map.h>
18#include <mach/dma.h>
19#include <mach/gpio.h>
18 20
19#include <plat/devs.h> 21#include <plat/devs.h>
20 22#include <plat/audio.h>
23#include <plat/gpio-bank-d.h>
24#include <plat/gpio-bank-e.h>
25#include <plat/gpio-cfg.h>
21 26
22static struct resource s3c64xx_iis0_resource[] = { 27static struct resource s3c64xx_iis0_resource[] = {
23 [0] = { 28 [0] = {
@@ -66,3 +71,97 @@ struct platform_device s3c64xx_device_iisv4 = {
66 .resource = s3c64xx_iisv4_resource, 71 .resource = s3c64xx_iisv4_resource,
67}; 72};
68EXPORT_SYMBOL(s3c64xx_device_iisv4); 73EXPORT_SYMBOL(s3c64xx_device_iisv4);
74
75
76/* PCM Controller platform_devices */
77
78static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
79{
80 switch (pdev->id) {
81 case 0:
82 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK);
83 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK);
84 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC);
85 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN);
86 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT);
87 break;
88 case 1:
89 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK);
90 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK);
91 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC);
92 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN);
93 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
94 break;
95 default:
96 printk(KERN_DEBUG "Invalid PCM Controller number!");
97 return -EINVAL;
98 }
99
100 return 0;
101}
102
103static struct resource s3c64xx_pcm0_resource[] = {
104 [0] = {
105 .start = S3C64XX_PA_PCM0,
106 .end = S3C64XX_PA_PCM0 + 0x100 - 1,
107 .flags = IORESOURCE_MEM,
108 },
109 [1] = {
110 .start = DMACH_PCM0_TX,
111 .end = DMACH_PCM0_TX,
112 .flags = IORESOURCE_DMA,
113 },
114 [2] = {
115 .start = DMACH_PCM0_RX,
116 .end = DMACH_PCM0_RX,
117 .flags = IORESOURCE_DMA,
118 },
119};
120
121static struct s3c_audio_pdata s3c_pcm0_pdata = {
122 .cfg_gpio = s3c64xx_pcm_cfg_gpio,
123};
124
125struct platform_device s3c64xx_device_pcm0 = {
126 .name = "samsung-pcm",
127 .id = 0,
128 .num_resources = ARRAY_SIZE(s3c64xx_pcm0_resource),
129 .resource = s3c64xx_pcm0_resource,
130 .dev = {
131 .platform_data = &s3c_pcm0_pdata,
132 },
133};
134EXPORT_SYMBOL(s3c64xx_device_pcm0);
135
136static struct resource s3c64xx_pcm1_resource[] = {
137 [0] = {
138 .start = S3C64XX_PA_PCM1,
139 .end = S3C64XX_PA_PCM1 + 0x100 - 1,
140 .flags = IORESOURCE_MEM,
141 },
142 [1] = {
143 .start = DMACH_PCM1_TX,
144 .end = DMACH_PCM1_TX,
145 .flags = IORESOURCE_DMA,
146 },
147 [2] = {
148 .start = DMACH_PCM1_RX,
149 .end = DMACH_PCM1_RX,
150 .flags = IORESOURCE_DMA,
151 },
152};
153
154static struct s3c_audio_pdata s3c_pcm1_pdata = {
155 .cfg_gpio = s3c64xx_pcm_cfg_gpio,
156};
157
158struct platform_device s3c64xx_device_pcm1 = {
159 .name = "samsung-pcm",
160 .id = 1,
161 .num_resources = ARRAY_SIZE(s3c64xx_pcm1_resource),
162 .resource = s3c64xx_pcm1_resource,
163 .dev = {
164 .platform_data = &s3c_pcm1_pdata,
165 },
166};
167EXPORT_SYMBOL(s3c64xx_device_pcm1);
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 0d4d3e3a4cfc..5fa3889d858b 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -211,37 +211,6 @@ static int cmode_procctl(ctl_table *ctl, int write,
211 return try_set_cmode(new_cmode)?:*lenp; 211 return try_set_cmode(new_cmode)?:*lenp;
212} 212}
213 213
214static int cmode_sysctl(ctl_table *table,
215 void __user *oldval, size_t __user *oldlenp,
216 void __user *newval, size_t newlen)
217{
218 if (oldval && oldlenp) {
219 size_t oldlen;
220
221 if (get_user(oldlen, oldlenp))
222 return -EFAULT;
223
224 if (oldlen != sizeof(int))
225 return -EINVAL;
226
227 if (put_user(clock_cmode_current, (unsigned __user *)oldval) ||
228 put_user(sizeof(int), oldlenp))
229 return -EFAULT;
230 }
231 if (newval && newlen) {
232 int new_cmode;
233
234 if (newlen != sizeof(int))
235 return -EINVAL;
236
237 if (get_user(new_cmode, (int __user *)newval))
238 return -EFAULT;
239
240 return try_set_cmode(new_cmode)?:1;
241 }
242 return 1;
243}
244
245static int try_set_p0(int new_p0) 214static int try_set_p0(int new_p0)
246{ 215{
247 unsigned long flags, clkc; 216 unsigned long flags, clkc;
@@ -314,37 +283,6 @@ static int p0_procctl(ctl_table *ctl, int write,
314 return try_set_p0(new_p0)?:*lenp; 283 return try_set_p0(new_p0)?:*lenp;
315} 284}
316 285
317static int p0_sysctl(ctl_table *table,
318 void __user *oldval, size_t __user *oldlenp,
319 void __user *newval, size_t newlen)
320{
321 if (oldval && oldlenp) {
322 size_t oldlen;
323
324 if (get_user(oldlen, oldlenp))
325 return -EFAULT;
326
327 if (oldlen != sizeof(int))
328 return -EINVAL;
329
330 if (put_user(clock_p0_current, (unsigned __user *)oldval) ||
331 put_user(sizeof(int), oldlenp))
332 return -EFAULT;
333 }
334 if (newval && newlen) {
335 int new_p0;
336
337 if (newlen != sizeof(int))
338 return -EINVAL;
339
340 if (get_user(new_p0, (int __user *)newval))
341 return -EFAULT;
342
343 return try_set_p0(new_p0)?:1;
344 }
345 return 1;
346}
347
348static int cm_procctl(ctl_table *ctl, int write, 286static int cm_procctl(ctl_table *ctl, int write,
349 void __user *buffer, size_t *lenp, loff_t *fpos) 287 void __user *buffer, size_t *lenp, loff_t *fpos)
350{ 288{
@@ -358,87 +296,47 @@ static int cm_procctl(ctl_table *ctl, int write,
358 return try_set_cm(new_cm)?:*lenp; 296 return try_set_cm(new_cm)?:*lenp;
359} 297}
360 298
361static int cm_sysctl(ctl_table *table,
362 void __user *oldval, size_t __user *oldlenp,
363 void __user *newval, size_t newlen)
364{
365 if (oldval && oldlenp) {
366 size_t oldlen;
367
368 if (get_user(oldlen, oldlenp))
369 return -EFAULT;
370
371 if (oldlen != sizeof(int))
372 return -EINVAL;
373
374 if (put_user(clock_cm_current, (unsigned __user *)oldval) ||
375 put_user(sizeof(int), oldlenp))
376 return -EFAULT;
377 }
378 if (newval && newlen) {
379 int new_cm;
380
381 if (newlen != sizeof(int))
382 return -EINVAL;
383
384 if (get_user(new_cm, (int __user *)newval))
385 return -EFAULT;
386
387 return try_set_cm(new_cm)?:1;
388 }
389 return 1;
390}
391
392
393static struct ctl_table pm_table[] = 299static struct ctl_table pm_table[] =
394{ 300{
395 { 301 {
396 .ctl_name = CTL_PM_SUSPEND,
397 .procname = "suspend", 302 .procname = "suspend",
398 .data = NULL, 303 .data = NULL,
399 .maxlen = 0, 304 .maxlen = 0,
400 .mode = 0200, 305 .mode = 0200,
401 .proc_handler = &sysctl_pm_do_suspend, 306 .proc_handler = sysctl_pm_do_suspend,
402 }, 307 },
403 { 308 {
404 .ctl_name = CTL_PM_CMODE,
405 .procname = "cmode", 309 .procname = "cmode",
406 .data = &clock_cmode_current, 310 .data = &clock_cmode_current,
407 .maxlen = sizeof(int), 311 .maxlen = sizeof(int),
408 .mode = 0644, 312 .mode = 0644,
409 .proc_handler = &cmode_procctl, 313 .proc_handler = cmode_procctl,
410 .strategy = &cmode_sysctl,
411 }, 314 },
412 { 315 {
413 .ctl_name = CTL_PM_P0,
414 .procname = "p0", 316 .procname = "p0",
415 .data = &clock_p0_current, 317 .data = &clock_p0_current,
416 .maxlen = sizeof(int), 318 .maxlen = sizeof(int),
417 .mode = 0644, 319 .mode = 0644,
418 .proc_handler = &p0_procctl, 320 .proc_handler = p0_procctl,
419 .strategy = &p0_sysctl,
420 }, 321 },
421 { 322 {
422 .ctl_name = CTL_PM_CM,
423 .procname = "cm", 323 .procname = "cm",
424 .data = &clock_cm_current, 324 .data = &clock_cm_current,
425 .maxlen = sizeof(int), 325 .maxlen = sizeof(int),
426 .mode = 0644, 326 .mode = 0644,
427 .proc_handler = &cm_procctl, 327 .proc_handler = cm_procctl,
428 .strategy = &cm_sysctl,
429 }, 328 },
430 { .ctl_name = 0} 329 { }
431}; 330};
432 331
433static struct ctl_table pm_dir_table[] = 332static struct ctl_table pm_dir_table[] =
434{ 333{
435 { 334 {
436 .ctl_name = CTL_PM,
437 .procname = "pm", 335 .procname = "pm",
438 .mode = 0555, 336 .mode = 0555,
439 .child = pm_table, 337 .child = pm_table,
440 }, 338 },
441 { .ctl_name = 0} 339 { }
442}; 340};
443 341
444/* 342/*
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index 3e9d7e03fb95..035516cb7a97 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -176,21 +176,19 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
176static struct ctl_table frv_table[] = 176static struct ctl_table frv_table[] =
177{ 177{
178 { 178 {
179 .ctl_name = 1,
180 .procname = "cache-mode", 179 .procname = "cache-mode",
181 .data = NULL, 180 .data = NULL,
182 .maxlen = 0, 181 .maxlen = 0,
183 .mode = 0644, 182 .mode = 0644,
184 .proc_handler = &procctl_frv_cachemode, 183 .proc_handler = procctl_frv_cachemode,
185 }, 184 },
186#ifdef CONFIG_MMU 185#ifdef CONFIG_MMU
187 { 186 {
188 .ctl_name = 2,
189 .procname = "pin-cxnr", 187 .procname = "pin-cxnr",
190 .data = NULL, 188 .data = NULL,
191 .maxlen = 0, 189 .maxlen = 0,
192 .mode = 0644, 190 .mode = 0644,
193 .proc_handler = &procctl_frv_pin_cxnr 191 .proc_handler = procctl_frv_pin_cxnr
194 }, 192 },
195#endif 193#endif
196 {} 194 {}
@@ -203,7 +201,6 @@ static struct ctl_table frv_table[] =
203static struct ctl_table frv_dir_table[] = 201static struct ctl_table frv_dir_table[] =
204{ 202{
205 { 203 {
206 .ctl_name = CTL_FRV,
207 .procname = "frv", 204 .procname = "frv",
208 .mode = 0555, 205 .mode = 0555,
209 .child = frv_table 206 .child = frv_table
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index af9405cd70e5..10c37510f4b4 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -327,7 +327,7 @@ ia32_syscall_table:
327 data8 compat_sys_writev 327 data8 compat_sys_writev
328 data8 sys_getsid 328 data8 sys_getsid
329 data8 sys_fdatasync 329 data8 sys_fdatasync
330 data8 sys32_sysctl 330 data8 compat_sys_sysctl
331 data8 sys_mlock /* 150 */ 331 data8 sys_mlock /* 150 */
332 data8 sys_munlock 332 data8 sys_munlock
333 data8 sys_mlockall 333 data8 sys_mlockall
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 625ed8f76fce..429ec968c9ee 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1628,61 +1628,6 @@ sys32_msync (unsigned int start, unsigned int len, int flags)
1628 return sys_msync(addr, len + (start - addr), flags); 1628 return sys_msync(addr, len + (start - addr), flags);
1629} 1629}
1630 1630
1631struct sysctl32 {
1632 unsigned int name;
1633 int nlen;
1634 unsigned int oldval;
1635 unsigned int oldlenp;
1636 unsigned int newval;
1637 unsigned int newlen;
1638 unsigned int __unused[4];
1639};
1640
1641#ifdef CONFIG_SYSCTL_SYSCALL
1642asmlinkage long
1643sys32_sysctl (struct sysctl32 __user *args)
1644{
1645 struct sysctl32 a32;
1646 mm_segment_t old_fs = get_fs ();
1647 void __user *oldvalp, *newvalp;
1648 size_t oldlen;
1649 int __user *namep;
1650 long ret;
1651
1652 if (copy_from_user(&a32, args, sizeof(a32)))
1653 return -EFAULT;
1654
1655 /*
1656 * We need to pre-validate these because we have to disable address checking
1657 * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
1658 * user specifying bad addresses here. Well, since we're dealing with 32 bit
1659 * addresses, we KNOW that access_ok() will always succeed, so this is an
1660 * expensive NOP, but so what...
1661 */
1662 namep = (int __user *) compat_ptr(a32.name);
1663 oldvalp = compat_ptr(a32.oldval);
1664 newvalp = compat_ptr(a32.newval);
1665
1666 if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp)))
1667 || !access_ok(VERIFY_WRITE, namep, 0)
1668 || !access_ok(VERIFY_WRITE, oldvalp, 0)
1669 || !access_ok(VERIFY_WRITE, newvalp, 0))
1670 return -EFAULT;
1671
1672 set_fs(KERNEL_DS);
1673 lock_kernel();
1674 ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen,
1675 newvalp, (size_t) a32.newlen);
1676 unlock_kernel();
1677 set_fs(old_fs);
1678
1679 if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp)))
1680 return -EFAULT;
1681
1682 return ret;
1683}
1684#endif
1685
1686asmlinkage long 1631asmlinkage long
1687sys32_newuname (struct new_utsname __user *name) 1632sys32_newuname (struct new_utsname __user *name)
1688{ 1633{
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index 6631a9dfafdc..b942f4032d7a 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -239,32 +239,29 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
239#ifdef CONFIG_SYSCTL 239#ifdef CONFIG_SYSCTL
240static ctl_table kdump_ctl_table[] = { 240static ctl_table kdump_ctl_table[] = {
241 { 241 {
242 .ctl_name = CTL_UNNUMBERED,
243 .procname = "kdump_on_init", 242 .procname = "kdump_on_init",
244 .data = &kdump_on_init, 243 .data = &kdump_on_init,
245 .maxlen = sizeof(int), 244 .maxlen = sizeof(int),
246 .mode = 0644, 245 .mode = 0644,
247 .proc_handler = &proc_dointvec, 246 .proc_handler = proc_dointvec,
248 }, 247 },
249 { 248 {
250 .ctl_name = CTL_UNNUMBERED,
251 .procname = "kdump_on_fatal_mca", 249 .procname = "kdump_on_fatal_mca",
252 .data = &kdump_on_fatal_mca, 250 .data = &kdump_on_fatal_mca,
253 .maxlen = sizeof(int), 251 .maxlen = sizeof(int),
254 .mode = 0644, 252 .mode = 0644,
255 .proc_handler = &proc_dointvec, 253 .proc_handler = proc_dointvec,
256 }, 254 },
257 { .ctl_name = 0 } 255 { }
258}; 256};
259 257
260static ctl_table sys_table[] = { 258static ctl_table sys_table[] = {
261 { 259 {
262 .ctl_name = CTL_KERN,
263 .procname = "kernel", 260 .procname = "kernel",
264 .mode = 0555, 261 .mode = 0555,
265 .child = kdump_ctl_table, 262 .child = kdump_ctl_table,
266 }, 263 },
267 { .ctl_name = 0 } 264 { }
268}; 265};
269#endif 266#endif
270 267
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index f1782705b1f7..402698b6689f 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -522,42 +522,37 @@ EXPORT_SYMBOL(pfm_sysctl);
522 522
523static ctl_table pfm_ctl_table[]={ 523static ctl_table pfm_ctl_table[]={
524 { 524 {
525 .ctl_name = CTL_UNNUMBERED,
526 .procname = "debug", 525 .procname = "debug",
527 .data = &pfm_sysctl.debug, 526 .data = &pfm_sysctl.debug,
528 .maxlen = sizeof(int), 527 .maxlen = sizeof(int),
529 .mode = 0666, 528 .mode = 0666,
530 .proc_handler = &proc_dointvec, 529 .proc_handler = proc_dointvec,
531 }, 530 },
532 { 531 {
533 .ctl_name = CTL_UNNUMBERED,
534 .procname = "debug_ovfl", 532 .procname = "debug_ovfl",
535 .data = &pfm_sysctl.debug_ovfl, 533 .data = &pfm_sysctl.debug_ovfl,
536 .maxlen = sizeof(int), 534 .maxlen = sizeof(int),
537 .mode = 0666, 535 .mode = 0666,
538 .proc_handler = &proc_dointvec, 536 .proc_handler = proc_dointvec,
539 }, 537 },
540 { 538 {
541 .ctl_name = CTL_UNNUMBERED,
542 .procname = "fastctxsw", 539 .procname = "fastctxsw",
543 .data = &pfm_sysctl.fastctxsw, 540 .data = &pfm_sysctl.fastctxsw,
544 .maxlen = sizeof(int), 541 .maxlen = sizeof(int),
545 .mode = 0600, 542 .mode = 0600,
546 .proc_handler = &proc_dointvec, 543 .proc_handler = proc_dointvec,
547 }, 544 },
548 { 545 {
549 .ctl_name = CTL_UNNUMBERED,
550 .procname = "expert_mode", 546 .procname = "expert_mode",
551 .data = &pfm_sysctl.expert_mode, 547 .data = &pfm_sysctl.expert_mode,
552 .maxlen = sizeof(int), 548 .maxlen = sizeof(int),
553 .mode = 0600, 549 .mode = 0600,
554 .proc_handler = &proc_dointvec, 550 .proc_handler = proc_dointvec,
555 }, 551 },
556 {} 552 {}
557}; 553};
558static ctl_table pfm_sysctl_dir[] = { 554static ctl_table pfm_sysctl_dir[] = {
559 { 555 {
560 .ctl_name = CTL_UNNUMBERED,
561 .procname = "perfmon", 556 .procname = "perfmon",
562 .mode = 0555, 557 .mode = 0555,
563 .child = pfm_ctl_table, 558 .child = pfm_ctl_table,
@@ -566,7 +561,6 @@ static ctl_table pfm_sysctl_dir[] = {
566}; 561};
567static ctl_table pfm_sysctl_root[] = { 562static ctl_table pfm_sysctl_root[] = {
568 { 563 {
569 .ctl_name = CTL_KERN,
570 .procname = "kernel", 564 .procname = "kernel",
571 .mode = 0555, 565 .mode = 0555,
572 .child = pfm_sysctl_dir, 566 .child = pfm_sysctl_dir,
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 37e6f305a68e..ef3ec1d6ceb3 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -12,23 +12,15 @@
12 * 2 of the License, or (at your option) any later version. 12 * 2 of the License, or (at your option) any later version.
13 */ 13 */
14 14
15#include <linux/of.h> /* linux/of.h gets to determine #include ordering */
16
15#ifndef _ASM_MICROBLAZE_PROM_H 17#ifndef _ASM_MICROBLAZE_PROM_H
16#define _ASM_MICROBLAZE_PROM_H 18#define _ASM_MICROBLAZE_PROM_H
17#ifdef __KERNEL__ 19#ifdef __KERNEL__
18
19/* Definitions used by the flattened device tree */
20#define OF_DT_HEADER 0xd00dfeed /* marker */
21#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
22#define OF_DT_END_NODE 0x2 /* End node */
23#define OF_DT_PROP 0x3 /* Property: name off, size, content */
24#define OF_DT_NOP 0x4 /* nop */
25#define OF_DT_END 0x9
26
27#define OF_DT_VERSION 0x10
28
29#ifndef __ASSEMBLY__ 20#ifndef __ASSEMBLY__
30 21
31#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/of_fdt.h>
32#include <linux/proc_fs.h> 24#include <linux/proc_fs.h>
33#include <linux/platform_device.h> 25#include <linux/platform_device.h>
34#include <asm/irq.h> 26#include <asm/irq.h>
@@ -41,122 +33,19 @@
41#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) 33#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
42#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) 34#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
43 35
44/*
45 * This is what gets passed to the kernel by prom_init or kexec
46 *
47 * The dt struct contains the device tree structure, full pathes and
48 * property contents. The dt strings contain a separate block with just
49 * the strings for the property names, and is fully page aligned and
50 * self contained in a page, so that it can be kept around by the kernel,
51 * each property name appears only once in this page (cheap compression)
52 *
53 * the mem_rsvmap contains a map of reserved ranges of physical memory,
54 * passing it here instead of in the device-tree itself greatly simplifies
55 * the job of everybody. It's just a list of u64 pairs (base/size) that
56 * ends when size is 0
57 */
58struct boot_param_header {
59 u32 magic; /* magic word OF_DT_HEADER */
60 u32 totalsize; /* total size of DT block */
61 u32 off_dt_struct; /* offset to structure */
62 u32 off_dt_strings; /* offset to strings */
63 u32 off_mem_rsvmap; /* offset to memory reserve map */
64 u32 version; /* format version */
65 u32 last_comp_version; /* last compatible version */
66 /* version 2 fields below */
67 u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
68 /* version 3 fields below */
69 u32 dt_strings_size; /* size of the DT strings block */
70 /* version 17 fields below */
71 u32 dt_struct_size; /* size of the DT structure block */
72};
73
74typedef u32 phandle;
75typedef u32 ihandle;
76
77struct property {
78 char *name;
79 int length;
80 void *value;
81 struct property *next;
82};
83
84struct device_node {
85 const char *name;
86 const char *type;
87 phandle node;
88 phandle linux_phandle;
89 char *full_name;
90
91 struct property *properties;
92 struct property *deadprops; /* removed properties */
93 struct device_node *parent;
94 struct device_node *child;
95 struct device_node *sibling;
96 struct device_node *next; /* next device of same type */
97 struct device_node *allnext; /* next in list of all nodes */
98 struct proc_dir_entry *pde; /* this node's proc directory */
99 struct kref kref;
100 unsigned long _flags;
101 void *data;
102};
103
104extern struct device_node *of_chosen; 36extern struct device_node *of_chosen;
105 37
106static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
107{
108 return test_bit(flag, &n->_flags);
109}
110
111static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
112{
113 set_bit(flag, &n->_flags);
114}
115
116#define HAVE_ARCH_DEVTREE_FIXUPS 38#define HAVE_ARCH_DEVTREE_FIXUPS
117 39
118static inline void set_node_proc_entry(struct device_node *dn,
119 struct proc_dir_entry *de)
120{
121 dn->pde = de;
122}
123
124extern struct device_node *allnodes; /* temporary while merging */ 40extern struct device_node *allnodes; /* temporary while merging */
125extern rwlock_t devtree_lock; /* temporary while merging */ 41extern rwlock_t devtree_lock; /* temporary while merging */
126 42
127extern struct device_node *of_find_all_nodes(struct device_node *prev);
128extern struct device_node *of_node_get(struct device_node *node);
129extern void of_node_put(struct device_node *node);
130
131/* For scanning the flat device-tree at boot time */
132extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
133 const char *uname, int depth,
134 void *data),
135 void *data);
136extern void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
137 unsigned long *size);
138extern int __init
139 of_flat_dt_is_compatible(unsigned long node, const char *name);
140extern unsigned long __init of_get_flat_dt_root(void);
141
142/* For updating the device tree at runtime */ 43/* For updating the device tree at runtime */
143extern void of_attach_node(struct device_node *); 44extern void of_attach_node(struct device_node *);
144extern void of_detach_node(struct device_node *); 45extern void of_detach_node(struct device_node *);
145 46
146/* Other Prototypes */ 47/* Other Prototypes */
147extern void finish_device_tree(void);
148extern void unflatten_device_tree(void);
149extern int early_uartlite_console(void); 48extern int early_uartlite_console(void);
150extern void early_init_devtree(void *);
151extern int machine_is_compatible(const char *compat);
152extern void print_properties(struct device_node *node);
153extern int prom_n_intr_cells(struct device_node *np);
154extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
155extern int prom_add_property(struct device_node *np, struct property *prop);
156extern int prom_remove_property(struct device_node *np, struct property *prop);
157extern int prom_update_property(struct device_node *np,
158 struct property *newprop,
159 struct property *oldprop);
160 49
161extern struct resource *request_OF_resource(struct device_node *node, 50extern struct resource *request_OF_resource(struct device_node *node,
162 int index, const char *name_postfix); 51 int index, const char *name_postfix);
@@ -166,18 +55,6 @@ extern int release_OF_resource(struct device_node *node, int index);
166 * OF address retreival & translation 55 * OF address retreival & translation
167 */ 56 */
168 57
169/* Helper to read a big number; size is in cells (not bytes) */
170static inline u64 of_read_number(const u32 *cell, int size)
171{
172 u64 r = 0;
173 while (size--)
174 r = (r << 32) | *(cell++);
175 return r;
176}
177
178/* Like of_read_number, but we want an unsigned long result */
179#define of_read_ulong(cell, size) of_read_number(cell, size)
180
181/* Translate an OF address block into a CPU physical address 58/* Translate an OF address block into a CPU physical address
182 */ 59 */
183extern u64 of_translate_address(struct device_node *np, const u32 *addr); 60extern u64 of_translate_address(struct device_node *np, const u32 *addr);
@@ -305,12 +182,6 @@ extern int of_irq_to_resource(struct device_node *dev, int index,
305 */ 182 */
306extern void __iomem *of_iomap(struct device_node *device, int index); 183extern void __iomem *of_iomap(struct device_node *device, int index);
307 184
308/*
309 * NB: This is here while we transition from using asm/prom.h
310 * to linux/of.h
311 */
312#include <linux/of.h>
313
314#endif /* __ASSEMBLY__ */ 185#endif /* __ASSEMBLY__ */
315#endif /* __KERNEL__ */ 186#endif /* __KERNEL__ */
316#endif /* _ASM_MICROBLAZE_PROM_H */ 187#endif /* _ASM_MICROBLAZE_PROM_H */
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index 697ce3007f30..30916193fcc7 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -31,7 +31,7 @@
31#include <linux/linkage.h> 31#include <linux/linkage.h>
32#include <asm/thread_info.h> 32#include <asm/thread_info.h>
33#include <asm/page.h> 33#include <asm/page.h>
34#include <asm/prom.h> /* for OF_DT_HEADER */ 34#include <linux/of_fdt.h> /* for OF_DT_HEADER */
35 35
36#ifdef CONFIG_MMU 36#ifdef CONFIG_MMU
37#include <asm/setup.h> /* COMMAND_LINE_SIZE */ 37#include <asm/setup.h> /* COMMAND_LINE_SIZE */
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index c005cc6f1aaf..b817df172aa9 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -860,29 +860,6 @@ struct device_node *of_find_node_by_phandle(phandle handle)
860EXPORT_SYMBOL(of_find_node_by_phandle); 860EXPORT_SYMBOL(of_find_node_by_phandle);
861 861
862/** 862/**
863 * of_find_all_nodes - Get next node in global list
864 * @prev: Previous node or NULL to start iteration
865 * of_node_put() will be called on it
866 *
867 * Returns a node pointer with refcount incremented, use
868 * of_node_put() on it when done.
869 */
870struct device_node *of_find_all_nodes(struct device_node *prev)
871{
872 struct device_node *np;
873
874 read_lock(&devtree_lock);
875 np = prev ? prev->allnext : allnodes;
876 for (; np != NULL; np = np->allnext)
877 if (of_node_get(np))
878 break;
879 of_node_put(prev);
880 read_unlock(&devtree_lock);
881 return np;
882}
883EXPORT_SYMBOL(of_find_all_nodes);
884
885/**
886 * of_node_get - Increment refcount of a node 863 * of_node_get - Increment refcount of a node
887 * @node: Node to inc refcount, NULL is supported to 864 * @node: Node to inc refcount, NULL is supported to
888 * simplify writing of callers 865 * simplify writing of callers
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index b77fefaff9da..1a2793efdc4e 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -265,67 +265,6 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
265} 265}
266#endif 266#endif
267 267
268struct sysctl_args32
269{
270 compat_caddr_t name;
271 int nlen;
272 compat_caddr_t oldval;
273 compat_caddr_t oldlenp;
274 compat_caddr_t newval;
275 compat_size_t newlen;
276 unsigned int __unused[4];
277};
278
279#ifdef CONFIG_SYSCTL_SYSCALL
280
281SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
282{
283 struct sysctl_args32 tmp;
284 int error;
285 size_t oldlen;
286 size_t __user *oldlenp = NULL;
287 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
288
289 if (copy_from_user(&tmp, args, sizeof(tmp)))
290 return -EFAULT;
291
292 if (tmp.oldval && tmp.oldlenp) {
293 /* Duh, this is ugly and might not work if sysctl_args
294 is in read-only memory, but do_sysctl does indirectly
295 a lot of uaccess in both directions and we'd have to
296 basically copy the whole sysctl.c here, and
297 glibc's __sysctl uses rw memory for the structure
298 anyway. */
299 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
300 put_user(oldlen, (size_t __user *)addr))
301 return -EFAULT;
302 oldlenp = (size_t __user *)addr;
303 }
304
305 lock_kernel();
306 error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
307 oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
308 unlock_kernel();
309 if (oldlenp) {
310 if (!error) {
311 if (get_user(oldlen, (size_t __user *)addr) ||
312 put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
313 error = -EFAULT;
314 }
315 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
316 }
317 return error;
318}
319
320#else
321
322SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
323{
324 return -ENOSYS;
325}
326
327#endif /* CONFIG_SYSCTL_SYSCALL */
328
329SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name) 268SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
330{ 269{
331 int ret = 0; 270 int ret = 0;
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 5154e64f7cfe..66b5a48676dd 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -272,7 +272,7 @@ EXPORT(sysn32_call_table)
272 PTR sys_munlockall 272 PTR sys_munlockall
273 PTR sys_vhangup /* 6150 */ 273 PTR sys_vhangup /* 6150 */
274 PTR sys_pivot_root 274 PTR sys_pivot_root
275 PTR sys_32_sysctl 275 PTR compat_sys_sysctl
276 PTR sys_prctl 276 PTR sys_prctl
277 PTR compat_sys_adjtimex 277 PTR compat_sys_adjtimex
278 PTR compat_sys_setrlimit /* 6155 */ 278 PTR compat_sys_setrlimit /* 6155 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 23b842be83ea..515f9eab2b28 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -356,7 +356,7 @@ sys_call_table:
356 PTR sys_ni_syscall /* 4150 */ 356 PTR sys_ni_syscall /* 4150 */
357 PTR sys_getsid 357 PTR sys_getsid
358 PTR sys_fdatasync 358 PTR sys_fdatasync
359 PTR sys_32_sysctl 359 PTR compat_sys_sysctl
360 PTR sys_mlock 360 PTR sys_mlock
361 PTR sys_munlock /* 4155 */ 361 PTR sys_munlock /* 4155 */
362 PTR sys_mlockall 362 PTR sys_mlockall
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index b3deed8db619..14b9a28a4aec 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -37,23 +37,6 @@
37#include "ds1603.h" 37#include "ds1603.h"
38#endif 38#endif
39 39
40/* Strategy function to write EEPROM after changing string entry */
41int sysctl_lasatstring(ctl_table *table,
42 void *oldval, size_t *oldlenp,
43 void *newval, size_t newlen)
44{
45 int r;
46
47 r = sysctl_string(table, oldval, oldlenp, newval, newlen);
48 if (r < 0)
49 return r;
50
51 if (newval && newlen)
52 lasat_write_eeprom_info();
53
54 return 0;
55}
56
57 40
58/* And the same for proc */ 41/* And the same for proc */
59int proc_dolasatstring(ctl_table *table, int write, 42int proc_dolasatstring(ctl_table *table, int write,
@@ -113,46 +96,6 @@ int proc_dolasatrtc(ctl_table *table, int write,
113} 96}
114#endif 97#endif
115 98
116/* Sysctl for setting the IP addresses */
117int sysctl_lasat_intvec(ctl_table *table,
118 void *oldval, size_t *oldlenp,
119 void *newval, size_t newlen)
120{
121 int r;
122
123 r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
124 if (r < 0)
125 return r;
126
127 if (newval && newlen)
128 lasat_write_eeprom_info();
129
130 return 0;
131}
132
133#ifdef CONFIG_DS1603
134/* Same for RTC */
135int sysctl_lasat_rtc(ctl_table *table,
136 void *oldval, size_t *oldlenp,
137 void *newval, size_t newlen)
138{
139 struct timespec ts;
140 int r;
141
142 read_persistent_clock(&ts);
143 rtctmp = ts.tv_sec;
144 if (rtctmp < 0)
145 rtctmp = 0;
146 r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
147 if (r < 0)
148 return r;
149 if (newval && newlen)
150 rtc_mips_set_mmss(rtctmp);
151
152 return r;
153}
154#endif
155
156#ifdef CONFIG_INET 99#ifdef CONFIG_INET
157int proc_lasat_ip(ctl_table *table, int write, 100int proc_lasat_ip(ctl_table *table, int write,
158 void *buffer, size_t *lenp, loff_t *ppos) 101 void *buffer, size_t *lenp, loff_t *ppos)
@@ -214,23 +157,6 @@ int proc_lasat_ip(ctl_table *table, int write,
214} 157}
215#endif 158#endif
216 159
217static int sysctl_lasat_prid(ctl_table *table,
218 void *oldval, size_t *oldlenp,
219 void *newval, size_t newlen)
220{
221 int r;
222
223 r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
224 if (r < 0)
225 return r;
226 if (newval && newlen) {
227 lasat_board_info.li_eeprom_info.prid = *(int *)newval;
228 lasat_write_eeprom_info();
229 lasat_init_board_info();
230 }
231 return 0;
232}
233
234int proc_lasat_prid(ctl_table *table, int write, 160int proc_lasat_prid(ctl_table *table, int write,
235 void *buffer, size_t *lenp, loff_t *ppos) 161 void *buffer, size_t *lenp, loff_t *ppos)
236{ 162{
@@ -252,115 +178,92 @@ extern int lasat_boot_to_service;
252 178
253static ctl_table lasat_table[] = { 179static ctl_table lasat_table[] = {
254 { 180 {
255 .ctl_name = CTL_UNNUMBERED,
256 .procname = "cpu-hz", 181 .procname = "cpu-hz",
257 .data = &lasat_board_info.li_cpu_hz, 182 .data = &lasat_board_info.li_cpu_hz,
258 .maxlen = sizeof(int), 183 .maxlen = sizeof(int),
259 .mode = 0444, 184 .mode = 0444,
260 .proc_handler = &proc_dointvec, 185 .proc_handler = proc_dointvec,
261 .strategy = &sysctl_intvec
262 }, 186 },
263 { 187 {
264 .ctl_name = CTL_UNNUMBERED,
265 .procname = "bus-hz", 188 .procname = "bus-hz",
266 .data = &lasat_board_info.li_bus_hz, 189 .data = &lasat_board_info.li_bus_hz,
267 .maxlen = sizeof(int), 190 .maxlen = sizeof(int),
268 .mode = 0444, 191 .mode = 0444,
269 .proc_handler = &proc_dointvec, 192 .proc_handler = proc_dointvec,
270 .strategy = &sysctl_intvec
271 }, 193 },
272 { 194 {
273 .ctl_name = CTL_UNNUMBERED,
274 .procname = "bmid", 195 .procname = "bmid",
275 .data = &lasat_board_info.li_bmid, 196 .data = &lasat_board_info.li_bmid,
276 .maxlen = sizeof(int), 197 .maxlen = sizeof(int),
277 .mode = 0444, 198 .mode = 0444,
278 .proc_handler = &proc_dointvec, 199 .proc_handler = proc_dointvec,
279 .strategy = &sysctl_intvec
280 }, 200 },
281 { 201 {
282 .ctl_name = CTL_UNNUMBERED,
283 .procname = "prid", 202 .procname = "prid",
284 .data = &lasat_board_info.li_prid, 203 .data = &lasat_board_info.li_prid,
285 .maxlen = sizeof(int), 204 .maxlen = sizeof(int),
286 .mode = 0644, 205 .mode = 0644,
287 .proc_handler = &proc_lasat_prid, 206 .proc_handler = proc_lasat_prid,
288 .strategy = &sysctl_lasat_prid 207. },
289 },
290#ifdef CONFIG_INET 208#ifdef CONFIG_INET
291 { 209 {
292 .ctl_name = CTL_UNNUMBERED,
293 .procname = "ipaddr", 210 .procname = "ipaddr",
294 .data = &lasat_board_info.li_eeprom_info.ipaddr, 211 .data = &lasat_board_info.li_eeprom_info.ipaddr,
295 .maxlen = sizeof(int), 212 .maxlen = sizeof(int),
296 .mode = 0644, 213 .mode = 0644,
297 .proc_handler = &proc_lasat_ip, 214 .proc_handler = proc_lasat_ip,
298 .strategy = &sysctl_lasat_intvec
299 }, 215 },
300 { 216 {
301 .ctl_name = CTL_UNNUMBERED,
302 .procname = "netmask", 217 .procname = "netmask",
303 .data = &lasat_board_info.li_eeprom_info.netmask, 218 .data = &lasat_board_info.li_eeprom_info.netmask,
304 .maxlen = sizeof(int), 219 .maxlen = sizeof(int),
305 .mode = 0644, 220 .mode = 0644,
306 .proc_handler = &proc_lasat_ip, 221 .proc_handler = proc_lasat_ip,
307 .strategy = &sysctl_lasat_intvec
308 }, 222 },
309#endif 223#endif
310 { 224 {
311 .ctl_name = CTL_UNNUMBERED,
312 .procname = "passwd_hash", 225 .procname = "passwd_hash",
313 .data = &lasat_board_info.li_eeprom_info.passwd_hash, 226 .data = &lasat_board_info.li_eeprom_info.passwd_hash,
314 .maxlen = 227 .maxlen =
315 sizeof(lasat_board_info.li_eeprom_info.passwd_hash), 228 sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
316 .mode = 0600, 229 .mode = 0600,
317 .proc_handler = &proc_dolasatstring, 230 .proc_handler = proc_dolasatstring,
318 .strategy = &sysctl_lasatstring
319 }, 231 },
320 { 232 {
321 .ctl_name = CTL_UNNUMBERED,
322 .procname = "boot-service", 233 .procname = "boot-service",
323 .data = &lasat_boot_to_service, 234 .data = &lasat_boot_to_service,
324 .maxlen = sizeof(int), 235 .maxlen = sizeof(int),
325 .mode = 0644, 236 .mode = 0644,
326 .proc_handler = &proc_dointvec, 237 .proc_handler = proc_dointvec,
327 .strategy = &sysctl_intvec
328 }, 238 },
329#ifdef CONFIG_DS1603 239#ifdef CONFIG_DS1603
330 { 240 {
331 .ctl_name = CTL_UNNUMBERED,
332 .procname = "rtc", 241 .procname = "rtc",
333 .data = &rtctmp, 242 .data = &rtctmp,
334 .maxlen = sizeof(int), 243 .maxlen = sizeof(int),
335 .mode = 0644, 244 .mode = 0644,
336 .proc_handler = &proc_dolasatrtc, 245 .proc_handler = proc_dolasatrtc,
337 .strategy = &sysctl_lasat_rtc
338 }, 246 },
339#endif 247#endif
340 { 248 {
341 .ctl_name = CTL_UNNUMBERED,
342 .procname = "namestr", 249 .procname = "namestr",
343 .data = &lasat_board_info.li_namestr, 250 .data = &lasat_board_info.li_namestr,
344 .maxlen = sizeof(lasat_board_info.li_namestr), 251 .maxlen = sizeof(lasat_board_info.li_namestr),
345 .mode = 0444, 252 .mode = 0444,
346 .proc_handler = &proc_dostring, 253 .proc_handler = proc_dostring,
347 .strategy = &sysctl_string
348 }, 254 },
349 { 255 {
350 .ctl_name = CTL_UNNUMBERED,
351 .procname = "typestr", 256 .procname = "typestr",
352 .data = &lasat_board_info.li_typestr, 257 .data = &lasat_board_info.li_typestr,
353 .maxlen = sizeof(lasat_board_info.li_typestr), 258 .maxlen = sizeof(lasat_board_info.li_typestr),
354 .mode = 0444, 259 .mode = 0444,
355 .proc_handler = &proc_dostring, 260 .proc_handler = proc_dostring,
356 .strategy = &sysctl_string
357 }, 261 },
358 {} 262 {}
359}; 263};
360 264
361static ctl_table lasat_root_table[] = { 265static ctl_table lasat_root_table[] = {
362 { 266 {
363 .ctl_name = CTL_UNNUMBERED,
364 .procname = "lasat", 267 .procname = "lasat",
365 .mode = 0555, 268 .mode = 0555,
366 .child = lasat_table 269 .child = lasat_table
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 561388b17c91..76d23ec8dfaa 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -90,77 +90,6 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
90 return -ENOSYS; 90 return -ENOSYS;
91} 91}
92 92
93#ifdef CONFIG_SYSCTL
94
95struct __sysctl_args32 {
96 u32 name;
97 int nlen;
98 u32 oldval;
99 u32 oldlenp;
100 u32 newval;
101 u32 newlen;
102 u32 __unused[4];
103};
104
105asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
106{
107#ifndef CONFIG_SYSCTL_SYSCALL
108 return -ENOSYS;
109#else
110 struct __sysctl_args32 tmp;
111 int error;
112 unsigned int oldlen32;
113 size_t oldlen, __user *oldlenp = NULL;
114 unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
115
116 DBG(("sysctl32(%p)\n", args));
117
118 if (copy_from_user(&tmp, args, sizeof(tmp)))
119 return -EFAULT;
120
121 if (tmp.oldval && tmp.oldlenp) {
122 /* Duh, this is ugly and might not work if sysctl_args
123 is in read-only memory, but do_sysctl does indirectly
124 a lot of uaccess in both directions and we'd have to
125 basically copy the whole sysctl.c here, and
126 glibc's __sysctl uses rw memory for the structure
127 anyway. */
128 /* a possibly better hack than this, which will avoid the
129 * problem if the struct is read only, is to push the
130 * 'oldlen' value out to the user's stack instead. -PB
131 */
132 if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
133 return -EFAULT;
134 oldlen = oldlen32;
135 if (put_user(oldlen, (size_t *)addr))
136 return -EFAULT;
137 oldlenp = (size_t *)addr;
138 }
139
140 lock_kernel();
141 error = do_sysctl((int __user *)(u64)tmp.name, tmp.nlen,
142 (void __user *)(u64)tmp.oldval, oldlenp,
143 (void __user *)(u64)tmp.newval, tmp.newlen);
144 unlock_kernel();
145 if (oldlenp) {
146 if (!error) {
147 if (get_user(oldlen, (size_t *)addr)) {
148 error = -EFAULT;
149 } else {
150 oldlen32 = oldlen;
151 if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
152 error = -EFAULT;
153 }
154 }
155 if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
156 error = -EFAULT;
157 }
158 return error;
159#endif
160}
161
162#endif /* CONFIG_SYSCTL */
163
164asmlinkage long sys32_sched_rr_get_interval(pid_t pid, 93asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
165 struct compat_timespec __user *interval) 94 struct compat_timespec __user *interval)
166{ 95{
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 843f423dec67..01c4fcf8f481 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -234,7 +234,7 @@
234 ENTRY_SAME(getsid) 234 ENTRY_SAME(getsid)
235 ENTRY_SAME(fdatasync) 235 ENTRY_SAME(fdatasync)
236 /* struct __sysctl_args is a mess */ 236 /* struct __sysctl_args is a mess */
237 ENTRY_DIFF(sysctl) 237 ENTRY_COMP(sysctl)
238 ENTRY_SAME(mlock) /* 150 */ 238 ENTRY_SAME(mlock) /* 150 */
239 ENTRY_SAME(munlock) 239 ENTRY_SAME(munlock)
240 ENTRY_SAME(mlockall) 240 ENTRY_SAME(mlockall)
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 3b1005185390..bf3382f1904d 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -46,7 +46,7 @@ config DEBUG_STACK_USAGE
46 46
47config HCALL_STATS 47config HCALL_STATS
48 bool "Hypervisor call instrumentation" 48 bool "Hypervisor call instrumentation"
49 depends on PPC_PSERIES && DEBUG_FS 49 depends on PPC_PSERIES && DEBUG_FS && TRACEPOINTS
50 help 50 help
51 Adds code to keep track of the number of hypervisor calls made and 51 Adds code to keep track of the number of hypervisor calls made and
52 the amount of time spent in hypervisor calls. Wall time spent in 52 the amount of time spent in hypervisor calls. Wall time spent in
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index f1889abb89b1..c568329723b8 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1683,7 +1683,7 @@ CONFIG_HAVE_ARCH_KGDB=y
1683CONFIG_DEBUG_STACKOVERFLOW=y 1683CONFIG_DEBUG_STACKOVERFLOW=y
1684# CONFIG_DEBUG_STACK_USAGE is not set 1684# CONFIG_DEBUG_STACK_USAGE is not set
1685# CONFIG_DEBUG_PAGEALLOC is not set 1685# CONFIG_DEBUG_PAGEALLOC is not set
1686CONFIG_HCALL_STATS=y 1686# CONFIG_HCALL_STATS is not set
1687# CONFIG_CODE_PATCHING_SELFTEST is not set 1687# CONFIG_CODE_PATCHING_SELFTEST is not set
1688# CONFIG_FTR_FIXUP_SELFTEST is not set 1688# CONFIG_FTR_FIXUP_SELFTEST is not set
1689# CONFIG_MSI_BITMAP_SELFTEST is not set 1689# CONFIG_MSI_BITMAP_SELFTEST is not set
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h
index 9154e8526732..f0fb4fc1f6e6 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -19,6 +19,7 @@
19#define _ASM_POWERPC_EMULATED_OPS_H 19#define _ASM_POWERPC_EMULATED_OPS_H
20 20
21#include <asm/atomic.h> 21#include <asm/atomic.h>
22#include <linux/perf_event.h>
22 23
23 24
24#ifdef CONFIG_PPC_EMULATED_STATS 25#ifdef CONFIG_PPC_EMULATED_STATS
@@ -57,7 +58,7 @@ extern u32 ppc_warn_emulated;
57 58
58extern void ppc_warn_emulated_print(const char *type); 59extern void ppc_warn_emulated_print(const char *type);
59 60
60#define PPC_WARN_EMULATED(type) \ 61#define __PPC_WARN_EMULATED(type) \
61 do { \ 62 do { \
62 atomic_inc(&ppc_emulated.type.val); \ 63 atomic_inc(&ppc_emulated.type.val); \
63 if (ppc_warn_emulated) \ 64 if (ppc_warn_emulated) \
@@ -66,8 +67,22 @@ extern void ppc_warn_emulated_print(const char *type);
66 67
67#else /* !CONFIG_PPC_EMULATED_STATS */ 68#else /* !CONFIG_PPC_EMULATED_STATS */
68 69
69#define PPC_WARN_EMULATED(type) do { } while (0) 70#define __PPC_WARN_EMULATED(type) do { } while (0)
70 71
71#endif /* !CONFIG_PPC_EMULATED_STATS */ 72#endif /* !CONFIG_PPC_EMULATED_STATS */
72 73
74#define PPC_WARN_EMULATED(type, regs) \
75 do { \
76 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, \
77 1, 0, regs, 0); \
78 __PPC_WARN_EMULATED(type); \
79 } while (0)
80
81#define PPC_WARN_ALIGNMENT(type, regs) \
82 do { \
83 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, \
84 1, 0, regs, regs->dar); \
85 __PPC_WARN_EMULATED(type); \
86 } while (0)
87
73#endif /* _ASM_POWERPC_EMULATED_OPS_H */ 88#endif /* _ASM_POWERPC_EMULATED_OPS_H */
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 6251a4b10be7..c27caac47ad1 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -274,6 +274,8 @@ struct hcall_stats {
274 unsigned long num_calls; /* number of calls (on this CPU) */ 274 unsigned long num_calls; /* number of calls (on this CPU) */
275 unsigned long tb_total; /* total wall time (mftb) of calls. */ 275 unsigned long tb_total; /* total wall time (mftb) of calls. */
276 unsigned long purr_total; /* total cpu time (PURR) of calls. */ 276 unsigned long purr_total; /* total cpu time (PURR) of calls. */
277 unsigned long tb_start;
278 unsigned long purr_start;
277}; 279};
278#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) 280#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1)
279 281
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 6ff04185d2aa..2ab9cbd98826 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -1,3 +1,4 @@
1#include <linux/of.h> /* linux/of.h gets to determine #include ordering */
1#ifndef _POWERPC_PROM_H 2#ifndef _POWERPC_PROM_H
2#define _POWERPC_PROM_H 3#define _POWERPC_PROM_H
3#ifdef __KERNEL__ 4#ifdef __KERNEL__
@@ -16,6 +17,7 @@
16 * 2 of the License, or (at your option) any later version. 17 * 2 of the License, or (at your option) any later version.
17 */ 18 */
18#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/of_fdt.h>
19#include <linux/proc_fs.h> 21#include <linux/proc_fs.h>
20#include <linux/platform_device.h> 22#include <linux/platform_device.h>
21#include <asm/irq.h> 23#include <asm/irq.h>
@@ -28,133 +30,14 @@
28#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) 30#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
29#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) 31#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
30 32
31/* Definitions used by the flattened device tree */
32#define OF_DT_HEADER 0xd00dfeed /* marker */
33#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
34#define OF_DT_END_NODE 0x2 /* End node */
35#define OF_DT_PROP 0x3 /* Property: name off, size,
36 * content */
37#define OF_DT_NOP 0x4 /* nop */
38#define OF_DT_END 0x9
39
40#define OF_DT_VERSION 0x10
41
42/*
43 * This is what gets passed to the kernel by prom_init or kexec
44 *
45 * The dt struct contains the device tree structure, full pathes and
46 * property contents. The dt strings contain a separate block with just
47 * the strings for the property names, and is fully page aligned and
48 * self contained in a page, so that it can be kept around by the kernel,
49 * each property name appears only once in this page (cheap compression)
50 *
51 * the mem_rsvmap contains a map of reserved ranges of physical memory,
52 * passing it here instead of in the device-tree itself greatly simplifies
53 * the job of everybody. It's just a list of u64 pairs (base/size) that
54 * ends when size is 0
55 */
56struct boot_param_header
57{
58 u32 magic; /* magic word OF_DT_HEADER */
59 u32 totalsize; /* total size of DT block */
60 u32 off_dt_struct; /* offset to structure */
61 u32 off_dt_strings; /* offset to strings */
62 u32 off_mem_rsvmap; /* offset to memory reserve map */
63 u32 version; /* format version */
64 u32 last_comp_version; /* last compatible version */
65 /* version 2 fields below */
66 u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
67 /* version 3 fields below */
68 u32 dt_strings_size; /* size of the DT strings block */
69 /* version 17 fields below */
70 u32 dt_struct_size; /* size of the DT structure block */
71};
72
73
74
75typedef u32 phandle;
76typedef u32 ihandle;
77
78struct property {
79 char *name;
80 int length;
81 void *value;
82 struct property *next;
83};
84
85struct device_node {
86 const char *name;
87 const char *type;
88 phandle node;
89 phandle linux_phandle;
90 char *full_name;
91
92 struct property *properties;
93 struct property *deadprops; /* removed properties */
94 struct device_node *parent;
95 struct device_node *child;
96 struct device_node *sibling;
97 struct device_node *next; /* next device of same type */
98 struct device_node *allnext; /* next in list of all nodes */
99 struct proc_dir_entry *pde; /* this node's proc directory */
100 struct kref kref;
101 unsigned long _flags;
102 void *data;
103};
104
105extern struct device_node *of_chosen; 33extern struct device_node *of_chosen;
106 34
107static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
108{
109 return test_bit(flag, &n->_flags);
110}
111
112static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
113{
114 set_bit(flag, &n->_flags);
115}
116
117
118#define HAVE_ARCH_DEVTREE_FIXUPS 35#define HAVE_ARCH_DEVTREE_FIXUPS
119 36
120static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
121{
122 dn->pde = de;
123}
124
125
126extern struct device_node *of_find_all_nodes(struct device_node *prev);
127extern struct device_node *of_node_get(struct device_node *node);
128extern void of_node_put(struct device_node *node);
129
130/* For scanning the flat device-tree at boot time */
131extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
132 const char *uname, int depth,
133 void *data),
134 void *data);
135extern void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
136 unsigned long *size);
137extern int __init of_flat_dt_is_compatible(unsigned long node, const char *name);
138extern unsigned long __init of_get_flat_dt_root(void);
139
140/* For updating the device tree at runtime */ 37/* For updating the device tree at runtime */
141extern void of_attach_node(struct device_node *); 38extern void of_attach_node(struct device_node *);
142extern void of_detach_node(struct device_node *); 39extern void of_detach_node(struct device_node *);
143 40
144/* Other Prototypes */
145extern void finish_device_tree(void);
146extern void unflatten_device_tree(void);
147extern void early_init_devtree(void *);
148extern int machine_is_compatible(const char *compat);
149extern void print_properties(struct device_node *node);
150extern int prom_n_intr_cells(struct device_node* np);
151extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
152extern int prom_add_property(struct device_node* np, struct property* prop);
153extern int prom_remove_property(struct device_node *np, struct property *prop);
154extern int prom_update_property(struct device_node *np,
155 struct property *newprop,
156 struct property *oldprop);
157
158#ifdef CONFIG_PPC32 41#ifdef CONFIG_PPC32
159/* 42/*
160 * PCI <-> OF matching functions 43 * PCI <-> OF matching functions
@@ -178,26 +61,6 @@ extern int release_OF_resource(struct device_node* node, int index);
178 * OF address retreival & translation 61 * OF address retreival & translation
179 */ 62 */
180 63
181
182/* Helper to read a big number; size is in cells (not bytes) */
183static inline u64 of_read_number(const u32 *cell, int size)
184{
185 u64 r = 0;
186 while (size--)
187 r = (r << 32) | *(cell++);
188 return r;
189}
190
191/* Like of_read_number, but we want an unsigned long result */
192#ifdef CONFIG_PPC32
193static inline unsigned long of_read_ulong(const u32 *cell, int size)
194{
195 return cell[size-1];
196}
197#else
198#define of_read_ulong(cell, size) of_read_number(cell, size)
199#endif
200
201/* Translate an OF address block into a CPU physical address 64/* Translate an OF address block into a CPU physical address
202 */ 65 */
203extern u64 of_translate_address(struct device_node *np, const u32 *addr); 66extern u64 of_translate_address(struct device_node *np, const u32 *addr);
@@ -349,11 +212,5 @@ extern int of_irq_to_resource(struct device_node *dev, int index,
349 */ 212 */
350extern void __iomem *of_iomap(struct device_node *device, int index); 213extern void __iomem *of_iomap(struct device_node *device, int index);
351 214
352/*
353 * NB: This is here while we transition from using asm/prom.h
354 * to linux/of.h
355 */
356#include <linux/of.h>
357
358#endif /* __KERNEL__ */ 215#endif /* __KERNEL__ */
359#endif /* _POWERPC_PROM_H */ 216#endif /* _POWERPC_PROM_H */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 6315edc205d8..bc8dd53f718a 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -489,6 +489,8 @@
489#define SPRN_MMCR1 798 489#define SPRN_MMCR1 798
490#define SPRN_MMCRA 0x312 490#define SPRN_MMCRA 0x312
491#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ 491#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
492#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
493#define MMCRA_SDAR_ERAT_MISS 0x20000000UL
492#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ 494#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
493#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ 495#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
494#define MMCRA_SLOT 0x07000000UL /* SLOT bits (37-39) */ 496#define MMCRA_SLOT 0x07000000UL /* SLOT bits (37-39) */
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h
new file mode 100644
index 000000000000..cbe2297d68b6
--- /dev/null
+++ b/arch/powerpc/include/asm/trace.h
@@ -0,0 +1,133 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM powerpc
3
4#if !defined(_TRACE_POWERPC_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_POWERPC_H
6
7#include <linux/tracepoint.h>
8
9struct pt_regs;
10
11TRACE_EVENT(irq_entry,
12
13 TP_PROTO(struct pt_regs *regs),
14
15 TP_ARGS(regs),
16
17 TP_STRUCT__entry(
18 __field(struct pt_regs *, regs)
19 ),
20
21 TP_fast_assign(
22 __entry->regs = regs;
23 ),
24
25 TP_printk("pt_regs=%p", __entry->regs)
26);
27
28TRACE_EVENT(irq_exit,
29
30 TP_PROTO(struct pt_regs *regs),
31
32 TP_ARGS(regs),
33
34 TP_STRUCT__entry(
35 __field(struct pt_regs *, regs)
36 ),
37
38 TP_fast_assign(
39 __entry->regs = regs;
40 ),
41
42 TP_printk("pt_regs=%p", __entry->regs)
43);
44
45TRACE_EVENT(timer_interrupt_entry,
46
47 TP_PROTO(struct pt_regs *regs),
48
49 TP_ARGS(regs),
50
51 TP_STRUCT__entry(
52 __field(struct pt_regs *, regs)
53 ),
54
55 TP_fast_assign(
56 __entry->regs = regs;
57 ),
58
59 TP_printk("pt_regs=%p", __entry->regs)
60);
61
62TRACE_EVENT(timer_interrupt_exit,
63
64 TP_PROTO(struct pt_regs *regs),
65
66 TP_ARGS(regs),
67
68 TP_STRUCT__entry(
69 __field(struct pt_regs *, regs)
70 ),
71
72 TP_fast_assign(
73 __entry->regs = regs;
74 ),
75
76 TP_printk("pt_regs=%p", __entry->regs)
77);
78
79#ifdef CONFIG_PPC_PSERIES
80extern void hcall_tracepoint_regfunc(void);
81extern void hcall_tracepoint_unregfunc(void);
82
83TRACE_EVENT_FN(hcall_entry,
84
85 TP_PROTO(unsigned long opcode, unsigned long *args),
86
87 TP_ARGS(opcode, args),
88
89 TP_STRUCT__entry(
90 __field(unsigned long, opcode)
91 ),
92
93 TP_fast_assign(
94 __entry->opcode = opcode;
95 ),
96
97 TP_printk("opcode=%lu", __entry->opcode),
98
99 hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc
100);
101
102TRACE_EVENT_FN(hcall_exit,
103
104 TP_PROTO(unsigned long opcode, unsigned long retval,
105 unsigned long *retbuf),
106
107 TP_ARGS(opcode, retval, retbuf),
108
109 TP_STRUCT__entry(
110 __field(unsigned long, opcode)
111 __field(unsigned long, retval)
112 ),
113
114 TP_fast_assign(
115 __entry->opcode = opcode;
116 __entry->retval = retval;
117 ),
118
119 TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval),
120
121 hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc
122);
123#endif
124
125#endif /* _TRACE_POWERPC_H */
126
127#undef TRACE_INCLUDE_PATH
128#undef TRACE_INCLUDE_FILE
129
130#define TRACE_INCLUDE_PATH asm
131#define TRACE_INCLUDE_FILE trace
132
133#include <trace/define_trace.h>
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index a5b632e52fae..3839839f83c7 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -732,7 +732,7 @@ int fix_alignment(struct pt_regs *regs)
732 732
733#ifdef CONFIG_SPE 733#ifdef CONFIG_SPE
734 if ((instr >> 26) == 0x4) { 734 if ((instr >> 26) == 0x4) {
735 PPC_WARN_EMULATED(spe); 735 PPC_WARN_ALIGNMENT(spe, regs);
736 return emulate_spe(regs, reg, instr); 736 return emulate_spe(regs, reg, instr);
737 } 737 }
738#endif 738#endif
@@ -786,7 +786,7 @@ int fix_alignment(struct pt_regs *regs)
786 flags |= SPLT; 786 flags |= SPLT;
787 nb = 8; 787 nb = 8;
788 } 788 }
789 PPC_WARN_EMULATED(vsx); 789 PPC_WARN_ALIGNMENT(vsx, regs);
790 return emulate_vsx(addr, reg, areg, regs, flags, nb); 790 return emulate_vsx(addr, reg, areg, regs, flags, nb);
791 } 791 }
792#endif 792#endif
@@ -794,7 +794,7 @@ int fix_alignment(struct pt_regs *regs)
794 * the exception of DCBZ which is handled as a special case here 794 * the exception of DCBZ which is handled as a special case here
795 */ 795 */
796 if (instr == DCBZ) { 796 if (instr == DCBZ) {
797 PPC_WARN_EMULATED(dcbz); 797 PPC_WARN_ALIGNMENT(dcbz, regs);
798 return emulate_dcbz(regs, addr); 798 return emulate_dcbz(regs, addr);
799 } 799 }
800 if (unlikely(nb == 0)) 800 if (unlikely(nb == 0))
@@ -804,7 +804,7 @@ int fix_alignment(struct pt_regs *regs)
804 * function 804 * function
805 */ 805 */
806 if (flags & M) { 806 if (flags & M) {
807 PPC_WARN_EMULATED(multiple); 807 PPC_WARN_ALIGNMENT(multiple, regs);
808 return emulate_multiple(regs, addr, reg, nb, 808 return emulate_multiple(regs, addr, reg, nb,
809 flags, instr, swiz); 809 flags, instr, swiz);
810 } 810 }
@@ -825,11 +825,11 @@ int fix_alignment(struct pt_regs *regs)
825 825
826 /* Special case for 16-byte FP loads and stores */ 826 /* Special case for 16-byte FP loads and stores */
827 if (nb == 16) { 827 if (nb == 16) {
828 PPC_WARN_EMULATED(fp_pair); 828 PPC_WARN_ALIGNMENT(fp_pair, regs);
829 return emulate_fp_pair(addr, reg, flags); 829 return emulate_fp_pair(addr, reg, flags);
830 } 830 }
831 831
832 PPC_WARN_EMULATED(unaligned); 832 PPC_WARN_ALIGNMENT(unaligned, regs);
833 833
834 /* If we are loading, get the data from user space, else 834 /* If we are loading, get the data from user space, else
835 * get it from register values 835 * get it from register values
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 9763267e38b4..bdcb557d470a 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -551,7 +551,7 @@ restore:
551BEGIN_FW_FTR_SECTION 551BEGIN_FW_FTR_SECTION
552 ld r5,SOFTE(r1) 552 ld r5,SOFTE(r1)
553FW_FTR_SECTION_ELSE 553FW_FTR_SECTION_ELSE
554 b iseries_check_pending_irqs 554 b .Liseries_check_pending_irqs
555ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) 555ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
5562: 5562:
557 TRACE_AND_RESTORE_IRQ(r5); 557 TRACE_AND_RESTORE_IRQ(r5);
@@ -623,7 +623,7 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
623 623
624#endif /* CONFIG_PPC_BOOK3E */ 624#endif /* CONFIG_PPC_BOOK3E */
625 625
626iseries_check_pending_irqs: 626.Liseries_check_pending_irqs:
627#ifdef CONFIG_PPC_ISERIES 627#ifdef CONFIG_PPC_ISERIES
628 ld r5,SOFTE(r1) 628 ld r5,SOFTE(r1)
629 cmpdi 0,r5,0 629 cmpdi 0,r5,0
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 1808876edcc9..c7eb4e0eb86c 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -185,12 +185,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
185 * prolog code of the PerformanceMonitor one. A little 185 * prolog code of the PerformanceMonitor one. A little
186 * trickery is thus necessary 186 * trickery is thus necessary
187 */ 187 */
188performance_monitor_pSeries_1:
188 . = 0xf00 189 . = 0xf00
189 b performance_monitor_pSeries 190 b performance_monitor_pSeries
190 191
192altivec_unavailable_pSeries_1:
191 . = 0xf20 193 . = 0xf20
192 b altivec_unavailable_pSeries 194 b altivec_unavailable_pSeries
193 195
196vsx_unavailable_pSeries_1:
194 . = 0xf40 197 . = 0xf40
195 b vsx_unavailable_pSeries 198 b vsx_unavailable_pSeries
196 199
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 88d9c1d5e5fb..049dda60e475 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -110,18 +110,16 @@ int powersave_nap;
110 */ 110 */
111static ctl_table powersave_nap_ctl_table[]={ 111static ctl_table powersave_nap_ctl_table[]={
112 { 112 {
113 .ctl_name = KERN_PPC_POWERSAVE_NAP,
114 .procname = "powersave-nap", 113 .procname = "powersave-nap",
115 .data = &powersave_nap, 114 .data = &powersave_nap,
116 .maxlen = sizeof(int), 115 .maxlen = sizeof(int),
117 .mode = 0644, 116 .mode = 0644,
118 .proc_handler = &proc_dointvec, 117 .proc_handler = proc_dointvec,
119 }, 118 },
120 {} 119 {}
121}; 120};
122static ctl_table powersave_nap_sysctl_root[] = { 121static ctl_table powersave_nap_sysctl_root[] = {
123 { 122 {
124 .ctl_name = CTL_KERN,
125 .procname = "kernel", 123 .procname = "kernel",
126 .mode = 0555, 124 .mode = 0555,
127 .child = powersave_nap_ctl_table, 125 .child = powersave_nap_ctl_table,
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index e5d121177984..02a334662cc0 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -70,6 +70,8 @@
70#include <asm/firmware.h> 70#include <asm/firmware.h>
71#include <asm/lv1call.h> 71#include <asm/lv1call.h>
72#endif 72#endif
73#define CREATE_TRACE_POINTS
74#include <asm/trace.h>
73 75
74int __irq_offset_value; 76int __irq_offset_value;
75static int ppc_spurious_interrupts; 77static int ppc_spurious_interrupts;
@@ -325,6 +327,8 @@ void do_IRQ(struct pt_regs *regs)
325 struct pt_regs *old_regs = set_irq_regs(regs); 327 struct pt_regs *old_regs = set_irq_regs(regs);
326 unsigned int irq; 328 unsigned int irq;
327 329
330 trace_irq_entry(regs);
331
328 irq_enter(); 332 irq_enter();
329 333
330 check_stack_overflow(); 334 check_stack_overflow();
@@ -348,6 +352,8 @@ void do_IRQ(struct pt_regs *regs)
348 timer_interrupt(regs); 352 timer_interrupt(regs);
349 } 353 }
350#endif 354#endif
355
356 trace_irq_exit(regs);
351} 357}
352 358
353void __init init_IRQ(void) 359void __init init_IRQ(void)
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 87f1663584b0..1eb85fbf53a5 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1165,7 +1165,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
1165 */ 1165 */
1166 if (record) { 1166 if (record) {
1167 struct perf_sample_data data = { 1167 struct perf_sample_data data = {
1168 .addr = 0, 1168 .addr = ~0ULL,
1169 .period = event->hw.last_period, 1169 .period = event->hw.last_period,
1170 }; 1170 };
1171 1171
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index 0f4c1c73a6ad..199de527d411 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -73,10 +73,6 @@
73#define MMCR1_PMCSEL_MSK 0x7f 73#define MMCR1_PMCSEL_MSK 0x7f
74 74
75/* 75/*
76 * Bits in MMCRA
77 */
78
79/*
80 * Layout of constraint bits: 76 * Layout of constraint bits:
81 * 6666555555555544444444443333333333222222222211111111110000000000 77 * 6666555555555544444444443333333333222222222211111111110000000000
82 * 3210987654321098765432109876543210987654321098765432109876543210 78 * 3210987654321098765432109876543210987654321098765432109876543210
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index c351b3a57fbb..98b6a729a9dd 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -73,10 +73,6 @@
73#define MMCR1_PMCSEL_MSK 0x7f 73#define MMCR1_PMCSEL_MSK 0x7f
74 74
75/* 75/*
76 * Bits in MMCRA
77 */
78
79/*
80 * Layout of constraint bits: 76 * Layout of constraint bits:
81 * 6666555555555544444444443333333333222222222211111111110000000000 77 * 6666555555555544444444443333333333222222222211111111110000000000
82 * 3210987654321098765432109876543210987654321098765432109876543210 78 * 3210987654321098765432109876543210987654321098765432109876543210
@@ -390,7 +386,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
390 unsigned int hwc[], unsigned long mmcr[]) 386 unsigned int hwc[], unsigned long mmcr[])
391{ 387{
392 unsigned long mmcr1 = 0; 388 unsigned long mmcr1 = 0;
393 unsigned long mmcra = 0; 389 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
394 unsigned int pmc, unit, byte, psel; 390 unsigned int pmc, unit, byte, psel;
395 unsigned int ttm, grp; 391 unsigned int ttm, grp;
396 int i, isbus, bit, grsel; 392 int i, isbus, bit, grsel;
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index ca399ba5034c..84a607bda8fb 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -178,7 +178,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev,
178 unsigned int hwc[], unsigned long mmcr[]) 178 unsigned int hwc[], unsigned long mmcr[])
179{ 179{
180 unsigned long mmcr1 = 0; 180 unsigned long mmcr1 = 0;
181 unsigned long mmcra = 0; 181 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
182 int i; 182 int i;
183 unsigned int pmc, ev, b, u, s, psel; 183 unsigned int pmc, ev, b, u, s, psel;
184 unsigned int ttmset = 0; 184 unsigned int ttmset = 0;
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 28a4daacdc02..852f7b7f6b40 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -51,10 +51,6 @@
51#define MMCR1_PMCSEL_MSK 0xff 51#define MMCR1_PMCSEL_MSK 0xff
52 52
53/* 53/*
54 * Bits in MMCRA
55 */
56
57/*
58 * Layout of constraint bits: 54 * Layout of constraint bits:
59 * 6666555555555544444444443333333333222222222211111111110000000000 55 * 6666555555555544444444443333333333222222222211111111110000000000
60 * 3210987654321098765432109876543210987654321098765432109876543210 56 * 3210987654321098765432109876543210987654321098765432109876543210
@@ -230,7 +226,7 @@ static int power7_compute_mmcr(u64 event[], int n_ev,
230 unsigned int hwc[], unsigned long mmcr[]) 226 unsigned int hwc[], unsigned long mmcr[])
231{ 227{
232 unsigned long mmcr1 = 0; 228 unsigned long mmcr1 = 0;
233 unsigned long mmcra = 0; 229 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
234 unsigned int pmc, unit, combine, l2sel, psel; 230 unsigned int pmc, unit, combine, l2sel, psel;
235 unsigned int pmc_inuse = 0; 231 unsigned int pmc_inuse = 0;
236 int i; 232 int i;
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 479574413a93..8eff48e20dba 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -84,10 +84,6 @@ static short mmcr1_adder_bits[8] = {
84}; 84};
85 85
86/* 86/*
87 * Bits in MMCRA
88 */
89
90/*
91 * Layout of constraint bits: 87 * Layout of constraint bits:
92 * 6666555555555544444444443333333333222222222211111111110000000000 88 * 6666555555555544444444443333333333222222222211111111110000000000
93 * 3210987654321098765432109876543210987654321098765432109876543210 89 * 3210987654321098765432109876543210987654321098765432109876543210
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d4405b95bfaa..4ec300862466 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1317,29 +1317,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np)
1317} 1317}
1318 1318
1319/** 1319/**
1320 * of_find_all_nodes - Get next node in global list
1321 * @prev: Previous node or NULL to start iteration
1322 * of_node_put() will be called on it
1323 *
1324 * Returns a node pointer with refcount incremented, use
1325 * of_node_put() on it when done.
1326 */
1327struct device_node *of_find_all_nodes(struct device_node *prev)
1328{
1329 struct device_node *np;
1330
1331 read_lock(&devtree_lock);
1332 np = prev ? prev->allnext : allnodes;
1333 for (; np != 0; np = np->allnext)
1334 if (of_node_get(np))
1335 break;
1336 of_node_put(prev);
1337 read_unlock(&devtree_lock);
1338 return np;
1339}
1340EXPORT_SYMBOL(of_find_all_nodes);
1341
1342/**
1343 * of_node_get - Increment refcount of a node 1320 * of_node_get - Increment refcount of a node
1344 * @node: Node to inc refcount, NULL is supported to 1321 * @node: Node to inc refcount, NULL is supported to
1345 * simplify writing of callers 1322 * simplify writing of callers
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 4271f7a655a3..845c72ab7357 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -660,6 +660,7 @@ late_initcall(check_cache_coherency);
660 660
661#ifdef CONFIG_DEBUG_FS 661#ifdef CONFIG_DEBUG_FS
662struct dentry *powerpc_debugfs_root; 662struct dentry *powerpc_debugfs_root;
663EXPORT_SYMBOL(powerpc_debugfs_root);
663 664
664static int powerpc_debugfs_init(void) 665static int powerpc_debugfs_init(void)
665{ 666{
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index b97c2d67f4ac..c5a4732bcc48 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -520,58 +520,6 @@ asmlinkage long compat_sys_umask(u32 mask)
520 return sys_umask((int)mask); 520 return sys_umask((int)mask);
521} 521}
522 522
523#ifdef CONFIG_SYSCTL_SYSCALL
524struct __sysctl_args32 {
525 u32 name;
526 int nlen;
527 u32 oldval;
528 u32 oldlenp;
529 u32 newval;
530 u32 newlen;
531 u32 __unused[4];
532};
533
534asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
535{
536 struct __sysctl_args32 tmp;
537 int error;
538 size_t oldlen;
539 size_t __user *oldlenp = NULL;
540 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
541
542 if (copy_from_user(&tmp, args, sizeof(tmp)))
543 return -EFAULT;
544
545 if (tmp.oldval && tmp.oldlenp) {
546 /* Duh, this is ugly and might not work if sysctl_args
547 is in read-only memory, but do_sysctl does indirectly
548 a lot of uaccess in both directions and we'd have to
549 basically copy the whole sysctl.c here, and
550 glibc's __sysctl uses rw memory for the structure
551 anyway. */
552 oldlenp = (size_t __user *)addr;
553 if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
554 put_user(oldlen, oldlenp))
555 return -EFAULT;
556 }
557
558 lock_kernel();
559 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
560 compat_ptr(tmp.oldval), oldlenp,
561 compat_ptr(tmp.newval), tmp.newlen);
562 unlock_kernel();
563 if (oldlenp) {
564 if (!error) {
565 if (get_user(oldlen, oldlenp) ||
566 put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
567 error = -EFAULT;
568 }
569 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
570 }
571 return error;
572}
573#endif
574
575unsigned long compat_sys_mmap2(unsigned long addr, size_t len, 523unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
576 unsigned long prot, unsigned long flags, 524 unsigned long prot, unsigned long flags,
577 unsigned long fd, unsigned long pgoff) 525 unsigned long fd, unsigned long pgoff)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a136a11c490d..36707dec94d7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -54,6 +54,7 @@
54#include <linux/irq.h> 54#include <linux/irq.h>
55#include <linux/delay.h> 55#include <linux/delay.h>
56#include <linux/perf_event.h> 56#include <linux/perf_event.h>
57#include <asm/trace.h>
57 58
58#include <asm/io.h> 59#include <asm/io.h>
59#include <asm/processor.h> 60#include <asm/processor.h>
@@ -571,6 +572,8 @@ void timer_interrupt(struct pt_regs * regs)
571 struct clock_event_device *evt = &decrementer->event; 572 struct clock_event_device *evt = &decrementer->event;
572 u64 now; 573 u64 now;
573 574
575 trace_timer_interrupt_entry(regs);
576
574 /* Ensure a positive value is written to the decrementer, or else 577 /* Ensure a positive value is written to the decrementer, or else
575 * some CPUs will continuue to take decrementer exceptions */ 578 * some CPUs will continuue to take decrementer exceptions */
576 set_dec(DECREMENTER_MAX); 579 set_dec(DECREMENTER_MAX);
@@ -590,6 +593,7 @@ void timer_interrupt(struct pt_regs * regs)
590 now = decrementer->next_tb - now; 593 now = decrementer->next_tb - now;
591 if (now <= DECREMENTER_MAX) 594 if (now <= DECREMENTER_MAX)
592 set_dec((int)now); 595 set_dec((int)now);
596 trace_timer_interrupt_exit(regs);
593 return; 597 return;
594 } 598 }
595 old_regs = set_irq_regs(regs); 599 old_regs = set_irq_regs(regs);
@@ -620,6 +624,8 @@ void timer_interrupt(struct pt_regs * regs)
620 624
621 irq_exit(); 625 irq_exit();
622 set_irq_regs(old_regs); 626 set_irq_regs(old_regs);
627
628 trace_timer_interrupt_exit(regs);
623} 629}
624 630
625void wakeup_decrementer(void) 631void wakeup_decrementer(void)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6f0ae1a9bfae..9d1f9354d6ca 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -759,7 +759,7 @@ static int emulate_instruction(struct pt_regs *regs)
759 759
760 /* Emulate the mfspr rD, PVR. */ 760 /* Emulate the mfspr rD, PVR. */
761 if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { 761 if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
762 PPC_WARN_EMULATED(mfpvr); 762 PPC_WARN_EMULATED(mfpvr, regs);
763 rd = (instword >> 21) & 0x1f; 763 rd = (instword >> 21) & 0x1f;
764 regs->gpr[rd] = mfspr(SPRN_PVR); 764 regs->gpr[rd] = mfspr(SPRN_PVR);
765 return 0; 765 return 0;
@@ -767,7 +767,7 @@ static int emulate_instruction(struct pt_regs *regs)
767 767
768 /* Emulating the dcba insn is just a no-op. */ 768 /* Emulating the dcba insn is just a no-op. */
769 if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) { 769 if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) {
770 PPC_WARN_EMULATED(dcba); 770 PPC_WARN_EMULATED(dcba, regs);
771 return 0; 771 return 0;
772 } 772 }
773 773
@@ -776,7 +776,7 @@ static int emulate_instruction(struct pt_regs *regs)
776 int shift = (instword >> 21) & 0x1c; 776 int shift = (instword >> 21) & 0x1c;
777 unsigned long msk = 0xf0000000UL >> shift; 777 unsigned long msk = 0xf0000000UL >> shift;
778 778
779 PPC_WARN_EMULATED(mcrxr); 779 PPC_WARN_EMULATED(mcrxr, regs);
780 regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); 780 regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
781 regs->xer &= ~0xf0000000UL; 781 regs->xer &= ~0xf0000000UL;
782 return 0; 782 return 0;
@@ -784,19 +784,19 @@ static int emulate_instruction(struct pt_regs *regs)
784 784
785 /* Emulate load/store string insn. */ 785 /* Emulate load/store string insn. */
786 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { 786 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) {
787 PPC_WARN_EMULATED(string); 787 PPC_WARN_EMULATED(string, regs);
788 return emulate_string_inst(regs, instword); 788 return emulate_string_inst(regs, instword);
789 } 789 }
790 790
791 /* Emulate the popcntb (Population Count Bytes) instruction. */ 791 /* Emulate the popcntb (Population Count Bytes) instruction. */
792 if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { 792 if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
793 PPC_WARN_EMULATED(popcntb); 793 PPC_WARN_EMULATED(popcntb, regs);
794 return emulate_popcntb_inst(regs, instword); 794 return emulate_popcntb_inst(regs, instword);
795 } 795 }
796 796
797 /* Emulate isel (Integer Select) instruction */ 797 /* Emulate isel (Integer Select) instruction */
798 if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { 798 if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
799 PPC_WARN_EMULATED(isel); 799 PPC_WARN_EMULATED(isel, regs);
800 return emulate_isel(regs, instword); 800 return emulate_isel(regs, instword);
801 } 801 }
802 802
@@ -995,7 +995,7 @@ void SoftwareEmulation(struct pt_regs *regs)
995#ifdef CONFIG_MATH_EMULATION 995#ifdef CONFIG_MATH_EMULATION
996 errcode = do_mathemu(regs); 996 errcode = do_mathemu(regs);
997 if (errcode >= 0) 997 if (errcode >= 0)
998 PPC_WARN_EMULATED(math); 998 PPC_WARN_EMULATED(math, regs);
999 999
1000 switch (errcode) { 1000 switch (errcode) {
1001 case 0: 1001 case 0:
@@ -1018,7 +1018,7 @@ void SoftwareEmulation(struct pt_regs *regs)
1018#elif defined(CONFIG_8XX_MINIMAL_FPEMU) 1018#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
1019 errcode = Soft_emulate_8xx(regs); 1019 errcode = Soft_emulate_8xx(regs);
1020 if (errcode >= 0) 1020 if (errcode >= 0)
1021 PPC_WARN_EMULATED(8xx); 1021 PPC_WARN_EMULATED(8xx, regs);
1022 1022
1023 switch (errcode) { 1023 switch (errcode) {
1024 case 0: 1024 case 0:
@@ -1129,7 +1129,7 @@ void altivec_assist_exception(struct pt_regs *regs)
1129 1129
1130 flush_altivec_to_thread(current); 1130 flush_altivec_to_thread(current);
1131 1131
1132 PPC_WARN_EMULATED(altivec); 1132 PPC_WARN_EMULATED(altivec, regs);
1133 err = emulate_altivec(regs); 1133 err = emulate_altivec(regs);
1134 if (err == 0) { 1134 if (err == 0) {
1135 regs->nip += 4; /* skip emulated instruction */ 1135 regs->nip += 4; /* skip emulated instruction */
diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S
index 75f3267fdc30..e68beac0a171 100644
--- a/arch/powerpc/lib/copypage_64.S
+++ b/arch/powerpc/lib/copypage_64.S
@@ -26,11 +26,11 @@ BEGIN_FTR_SECTION
26 srd r8,r5,r11 26 srd r8,r5,r11
27 27
28 mtctr r8 28 mtctr r8
29setup: 29.Lsetup:
30 dcbt r9,r4 30 dcbt r9,r4
31 dcbz r9,r3 31 dcbz r9,r3
32 add r9,r9,r12 32 add r9,r9,r12
33 bdnz setup 33 bdnz .Lsetup
34END_FTR_SECTION_IFSET(CPU_FTR_CP_USE_DCBTZ) 34END_FTR_SECTION_IFSET(CPU_FTR_CP_USE_DCBTZ)
35 addi r3,r3,-8 35 addi r3,r3,-8
36 srdi r8,r5,7 /* page is copied in 128 byte strides */ 36 srdi r8,r5,7 /* page is copied in 128 byte strides */
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index c1427b3634ec..383a5d0e9818 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -14,68 +14,94 @@
14 14
15#define STK_PARM(i) (48 + ((i)-3)*8) 15#define STK_PARM(i) (48 + ((i)-3)*8)
16 16
17#ifdef CONFIG_HCALL_STATS 17#ifdef CONFIG_TRACEPOINTS
18
19 .section ".toc","aw"
20
21 .globl hcall_tracepoint_refcount
22hcall_tracepoint_refcount:
23 .llong 0
24
25 .section ".text"
26
18/* 27/*
19 * precall must preserve all registers. use unused STK_PARM() 28 * precall must preserve all registers. use unused STK_PARM()
20 * areas to save snapshots and opcode. 29 * areas to save snapshots and opcode. We branch around this
30 * in early init (eg when populating the MMU hashtable) by using an
31 * unconditional cpu feature.
21 */ 32 */
22#define HCALL_INST_PRECALL \ 33#define HCALL_INST_PRECALL(FIRST_REG) \
23 std r3,STK_PARM(r3)(r1); /* save opcode */ \
24 mftb r0; /* get timebase and */ \
25 std r0,STK_PARM(r5)(r1); /* save for later */ \
26BEGIN_FTR_SECTION; \ 34BEGIN_FTR_SECTION; \
27 mfspr r0,SPRN_PURR; /* get PURR and */ \ 35 b 1f; \
28 std r0,STK_PARM(r6)(r1); /* save for later */ \ 36END_FTR_SECTION(0, 1); \
29END_FTR_SECTION_IFSET(CPU_FTR_PURR); 37 ld r12,hcall_tracepoint_refcount@toc(r2); \
30 38 cmpdi r12,0; \
39 beq+ 1f; \
40 mflr r0; \
41 std r3,STK_PARM(r3)(r1); \
42 std r4,STK_PARM(r4)(r1); \
43 std r5,STK_PARM(r5)(r1); \
44 std r6,STK_PARM(r6)(r1); \
45 std r7,STK_PARM(r7)(r1); \
46 std r8,STK_PARM(r8)(r1); \
47 std r9,STK_PARM(r9)(r1); \
48 std r10,STK_PARM(r10)(r1); \
49 std r0,16(r1); \
50 addi r4,r1,STK_PARM(FIRST_REG); \
51 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
52 bl .__trace_hcall_entry; \
53 addi r1,r1,STACK_FRAME_OVERHEAD; \
54 ld r0,16(r1); \
55 ld r3,STK_PARM(r3)(r1); \
56 ld r4,STK_PARM(r4)(r1); \
57 ld r5,STK_PARM(r5)(r1); \
58 ld r6,STK_PARM(r6)(r1); \
59 ld r7,STK_PARM(r7)(r1); \
60 ld r8,STK_PARM(r8)(r1); \
61 ld r9,STK_PARM(r9)(r1); \
62 ld r10,STK_PARM(r10)(r1); \
63 mtlr r0; \
641:
65
31/* 66/*
32 * postcall is performed immediately before function return which 67 * postcall is performed immediately before function return which
33 * allows liberal use of volatile registers. We branch around this 68 * allows liberal use of volatile registers. We branch around this
34 * in early init (eg when populating the MMU hashtable) by using an 69 * in early init (eg when populating the MMU hashtable) by using an
35 * unconditional cpu feature. 70 * unconditional cpu feature.
36 */ 71 */
37#define HCALL_INST_POSTCALL \ 72#define __HCALL_INST_POSTCALL \
38BEGIN_FTR_SECTION; \ 73BEGIN_FTR_SECTION; \
39 b 1f; \ 74 b 1f; \
40END_FTR_SECTION(0, 1); \ 75END_FTR_SECTION(0, 1); \
41 ld r4,STK_PARM(r3)(r1); /* validate opcode */ \ 76 ld r12,hcall_tracepoint_refcount@toc(r2); \
42 cmpldi cr7,r4,MAX_HCALL_OPCODE; \ 77 cmpdi r12,0; \
43 bgt- cr7,1f; \ 78 beq+ 1f; \
44 \ 79 mflr r0; \
45 /* get time and PURR snapshots after hcall */ \ 80 ld r6,STK_PARM(r3)(r1); \
46 mftb r7; /* timebase after */ \ 81 std r3,STK_PARM(r3)(r1); \
47BEGIN_FTR_SECTION; \ 82 mr r4,r3; \
48 mfspr r8,SPRN_PURR; /* PURR after */ \ 83 mr r3,r6; \
49 ld r6,STK_PARM(r6)(r1); /* PURR before */ \ 84 std r0,16(r1); \
50 subf r6,r6,r8; /* delta */ \ 85 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
51END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ 86 bl .__trace_hcall_exit; \
52 ld r5,STK_PARM(r5)(r1); /* timebase before */ \ 87 addi r1,r1,STACK_FRAME_OVERHEAD; \
53 subf r5,r5,r7; /* time delta */ \ 88 ld r0,16(r1); \
54 \ 89 ld r3,STK_PARM(r3)(r1); \
55 /* calculate address of stat structure r4 = opcode */ \ 90 mtlr r0; \
56 srdi r4,r4,2; /* index into array */ \
57 mulli r4,r4,HCALL_STAT_SIZE; \
58 LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \
59 add r4,r4,r7; \
60 ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \
61 add r4,r4,r7; \
62 \
63 /* update stats */ \
64 ld r7,HCALL_STAT_CALLS(r4); /* count */ \
65 addi r7,r7,1; \
66 std r7,HCALL_STAT_CALLS(r4); \
67 ld r7,HCALL_STAT_TB(r4); /* timebase */ \
68 add r7,r7,r5; \
69 std r7,HCALL_STAT_TB(r4); \
70BEGIN_FTR_SECTION; \
71 ld r7,HCALL_STAT_PURR(r4); /* PURR */ \
72 add r7,r7,r6; \
73 std r7,HCALL_STAT_PURR(r4); \
74END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
751: 911:
92
93#define HCALL_INST_POSTCALL_NORETS \
94 li r5,0; \
95 __HCALL_INST_POSTCALL
96
97#define HCALL_INST_POSTCALL(BUFREG) \
98 mr r5,BUFREG; \
99 __HCALL_INST_POSTCALL
100
76#else 101#else
77#define HCALL_INST_PRECALL 102#define HCALL_INST_PRECALL(FIRST_ARG)
78#define HCALL_INST_POSTCALL 103#define HCALL_INST_POSTCALL_NORETS
104#define HCALL_INST_POSTCALL(BUFREG)
79#endif 105#endif
80 106
81 .text 107 .text
@@ -86,11 +112,11 @@ _GLOBAL(plpar_hcall_norets)
86 mfcr r0 112 mfcr r0
87 stw r0,8(r1) 113 stw r0,8(r1)
88 114
89 HCALL_INST_PRECALL 115 HCALL_INST_PRECALL(r4)
90 116
91 HVSC /* invoke the hypervisor */ 117 HVSC /* invoke the hypervisor */
92 118
93 HCALL_INST_POSTCALL 119 HCALL_INST_POSTCALL_NORETS
94 120
95 lwz r0,8(r1) 121 lwz r0,8(r1)
96 mtcrf 0xff,r0 122 mtcrf 0xff,r0
@@ -102,7 +128,7 @@ _GLOBAL(plpar_hcall)
102 mfcr r0 128 mfcr r0
103 stw r0,8(r1) 129 stw r0,8(r1)
104 130
105 HCALL_INST_PRECALL 131 HCALL_INST_PRECALL(r5)
106 132
107 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 133 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
108 134
@@ -121,7 +147,7 @@ _GLOBAL(plpar_hcall)
121 std r6, 16(r12) 147 std r6, 16(r12)
122 std r7, 24(r12) 148 std r7, 24(r12)
123 149
124 HCALL_INST_POSTCALL 150 HCALL_INST_POSTCALL(r12)
125 151
126 lwz r0,8(r1) 152 lwz r0,8(r1)
127 mtcrf 0xff,r0 153 mtcrf 0xff,r0
@@ -168,7 +194,7 @@ _GLOBAL(plpar_hcall9)
168 mfcr r0 194 mfcr r0
169 stw r0,8(r1) 195 stw r0,8(r1)
170 196
171 HCALL_INST_PRECALL 197 HCALL_INST_PRECALL(r5)
172 198
173 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 199 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
174 200
@@ -196,7 +222,7 @@ _GLOBAL(plpar_hcall9)
196 std r11,56(r12) 222 std r11,56(r12)
197 std r0, 64(r12) 223 std r0, 64(r12)
198 224
199 HCALL_INST_POSTCALL 225 HCALL_INST_POSTCALL(r12)
200 226
201 lwz r0,8(r1) 227 lwz r0,8(r1)
202 mtcrf 0xff,r0 228 mtcrf 0xff,r0
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 3631a4f277eb..2f58c71b7259 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -26,6 +26,7 @@
26#include <asm/hvcall.h> 26#include <asm/hvcall.h>
27#include <asm/firmware.h> 27#include <asm/firmware.h>
28#include <asm/cputable.h> 28#include <asm/cputable.h>
29#include <asm/trace.h>
29 30
30DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); 31DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats);
31 32
@@ -100,6 +101,35 @@ static const struct file_operations hcall_inst_seq_fops = {
100#define HCALL_ROOT_DIR "hcall_inst" 101#define HCALL_ROOT_DIR "hcall_inst"
101#define CPU_NAME_BUF_SIZE 32 102#define CPU_NAME_BUF_SIZE 32
102 103
104
105static void probe_hcall_entry(unsigned long opcode, unsigned long *args)
106{
107 struct hcall_stats *h;
108
109 if (opcode > MAX_HCALL_OPCODE)
110 return;
111
112 h = &get_cpu_var(hcall_stats)[opcode / 4];
113 h->tb_start = mftb();
114 h->purr_start = mfspr(SPRN_PURR);
115}
116
117static void probe_hcall_exit(unsigned long opcode, unsigned long retval,
118 unsigned long *retbuf)
119{
120 struct hcall_stats *h;
121
122 if (opcode > MAX_HCALL_OPCODE)
123 return;
124
125 h = &__get_cpu_var(hcall_stats)[opcode / 4];
126 h->num_calls++;
127 h->tb_total = mftb() - h->tb_start;
128 h->purr_total = mfspr(SPRN_PURR) - h->purr_start;
129
130 put_cpu_var(hcall_stats);
131}
132
103static int __init hcall_inst_init(void) 133static int __init hcall_inst_init(void)
104{ 134{
105 struct dentry *hcall_root; 135 struct dentry *hcall_root;
@@ -110,6 +140,14 @@ static int __init hcall_inst_init(void)
110 if (!firmware_has_feature(FW_FEATURE_LPAR)) 140 if (!firmware_has_feature(FW_FEATURE_LPAR))
111 return 0; 141 return 0;
112 142
143 if (register_trace_hcall_entry(probe_hcall_entry))
144 return -EINVAL;
145
146 if (register_trace_hcall_exit(probe_hcall_exit)) {
147 unregister_trace_hcall_entry(probe_hcall_entry);
148 return -EINVAL;
149 }
150
113 hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL); 151 hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
114 if (!hcall_root) 152 if (!hcall_root)
115 return -ENOMEM; 153 return -ENOMEM;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 903eb9eec687..0707653612ba 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -39,6 +39,7 @@
39#include <asm/cputable.h> 39#include <asm/cputable.h>
40#include <asm/udbg.h> 40#include <asm/udbg.h>
41#include <asm/smp.h> 41#include <asm/smp.h>
42#include <asm/trace.h>
42 43
43#include "plpar_wrappers.h" 44#include "plpar_wrappers.h"
44#include "pseries.h" 45#include "pseries.h"
@@ -661,3 +662,35 @@ void arch_free_page(struct page *page, int order)
661EXPORT_SYMBOL(arch_free_page); 662EXPORT_SYMBOL(arch_free_page);
662 663
663#endif 664#endif
665
666#ifdef CONFIG_TRACEPOINTS
667/*
668 * We optimise our hcall path by placing hcall_tracepoint_refcount
669 * directly in the TOC so we can check if the hcall tracepoints are
670 * enabled via a single load.
671 */
672
673/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
674extern long hcall_tracepoint_refcount;
675
676void hcall_tracepoint_regfunc(void)
677{
678 hcall_tracepoint_refcount++;
679}
680
681void hcall_tracepoint_unregfunc(void)
682{
683 hcall_tracepoint_refcount--;
684}
685
686void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
687{
688 trace_hcall_entry(opcode, args);
689}
690
691void __trace_hcall_exit(long opcode, unsigned long retval,
692 unsigned long *retbuf)
693{
694 trace_hcall_exit(opcode, retval, retbuf);
695}
696#endif
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index b55fd7ed1c31..495589950dc7 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -61,12 +61,12 @@ static struct ctl_table appldata_table[] = {
61 { 61 {
62 .procname = "timer", 62 .procname = "timer",
63 .mode = S_IRUGO | S_IWUSR, 63 .mode = S_IRUGO | S_IWUSR,
64 .proc_handler = &appldata_timer_handler, 64 .proc_handler = appldata_timer_handler,
65 }, 65 },
66 { 66 {
67 .procname = "interval", 67 .procname = "interval",
68 .mode = S_IRUGO | S_IWUSR, 68 .mode = S_IRUGO | S_IWUSR,
69 .proc_handler = &appldata_interval_handler, 69 .proc_handler = appldata_interval_handler,
70 }, 70 },
71 { }, 71 { },
72}; 72};
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 0debcec23a39..fda1a8123f9b 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -527,59 +527,6 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
527 return ret; 527 return ret;
528} 528}
529 529
530#ifdef CONFIG_SYSCTL_SYSCALL
531struct __sysctl_args32 {
532 u32 name;
533 int nlen;
534 u32 oldval;
535 u32 oldlenp;
536 u32 newval;
537 u32 newlen;
538 u32 __unused[4];
539};
540
541asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
542{
543 struct __sysctl_args32 tmp;
544 int error;
545 size_t oldlen;
546 size_t __user *oldlenp = NULL;
547 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
548
549 if (copy_from_user(&tmp, args, sizeof(tmp)))
550 return -EFAULT;
551
552 if (tmp.oldval && tmp.oldlenp) {
553 /* Duh, this is ugly and might not work if sysctl_args
554 is in read-only memory, but do_sysctl does indirectly
555 a lot of uaccess in both directions and we'd have to
556 basically copy the whole sysctl.c here, and
557 glibc's __sysctl uses rw memory for the structure
558 anyway. */
559 if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
560 put_user(oldlen, (size_t __user *)addr))
561 return -EFAULT;
562 oldlenp = (size_t __user *)addr;
563 }
564
565 lock_kernel();
566 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
567 oldlenp, compat_ptr(tmp.newval), tmp.newlen);
568 unlock_kernel();
569 if (oldlenp) {
570 if (!error) {
571 if (get_user(oldlen, (size_t __user *)addr) ||
572 put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
573 error = -EFAULT;
574 }
575 if (copy_to_user(args->__unused, tmp.__unused,
576 sizeof(tmp.__unused)))
577 error = -EFAULT;
578 }
579 return error;
580}
581#endif
582
583struct stat64_emu31 { 530struct stat64_emu31 {
584 unsigned long long st_dev; 531 unsigned long long st_dev;
585 unsigned int __pad1; 532 unsigned int __pad1;
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index c07f9ca05ade..45e9092b3aad 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -162,7 +162,6 @@ struct ucontext32 {
162 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 162 compat_sigset_t uc_sigmask; /* mask last for extensibility */
163}; 163};
164 164
165struct __sysctl_args32;
166struct stat64_emu31; 165struct stat64_emu31;
167struct mmap_arg_struct_emu31; 166struct mmap_arg_struct_emu31;
168struct fadvise64_64_args; 167struct fadvise64_64_args;
@@ -212,7 +211,6 @@ long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
212 size_t count); 211 size_t count);
213long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, 212long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
214 s32 count); 213 s32 count);
215long sys32_sysctl(struct __sysctl_args32 __user *args);
216long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf); 214long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
217long sys32_lstat64(char __user * filename, 215long sys32_lstat64(char __user * filename,
218 struct stat64_emu31 __user * statbuf); 216 struct stat64_emu31 __user * statbuf);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index cbd9901dc0f8..30de2d0e52bb 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -689,8 +689,6 @@ sys32_fdatasync_wrapper:
689 llgfr %r2,%r2 # unsigned int 689 llgfr %r2,%r2 # unsigned int
690 jg sys_fdatasync # branch to system call 690 jg sys_fdatasync # branch to system call
691 691
692#sys32_sysctl_wrapper # tbd
693
694 .globl sys32_mlock_wrapper 692 .globl sys32_mlock_wrapper
695sys32_mlock_wrapper: 693sys32_mlock_wrapper:
696 llgfr %r2,%r2 # unsigned long 694 llgfr %r2,%r2 # unsigned long
@@ -1087,8 +1085,8 @@ sys32_stime_wrapper:
1087 1085
1088 .globl sys32_sysctl_wrapper 1086 .globl sys32_sysctl_wrapper
1089sys32_sysctl_wrapper: 1087sys32_sysctl_wrapper:
1090 llgtr %r2,%r2 # struct __sysctl_args32 * 1088 llgtr %r2,%r2 # struct compat_sysctl_args *
1091 jg sys32_sysctl 1089 jg compat_sys_sysctl
1092 1090
1093 .globl sys32_fstat64_wrapper 1091 .globl sys32_fstat64_wrapper
1094sys32_fstat64_wrapper: 1092sys32_fstat64_wrapper:
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 20f282c911c2..071c81f179ef 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -893,35 +893,30 @@ s390dbf_procactive(ctl_table *table, int write,
893 893
894static struct ctl_table s390dbf_table[] = { 894static struct ctl_table s390dbf_table[] = {
895 { 895 {
896 .ctl_name = CTL_S390DBF_STOPPABLE,
897 .procname = "debug_stoppable", 896 .procname = "debug_stoppable",
898 .data = &debug_stoppable, 897 .data = &debug_stoppable,
899 .maxlen = sizeof(int), 898 .maxlen = sizeof(int),
900 .mode = S_IRUGO | S_IWUSR, 899 .mode = S_IRUGO | S_IWUSR,
901 .proc_handler = &proc_dointvec, 900 .proc_handler = proc_dointvec,
902 .strategy = &sysctl_intvec,
903 }, 901 },
904 { 902 {
905 .ctl_name = CTL_S390DBF_ACTIVE,
906 .procname = "debug_active", 903 .procname = "debug_active",
907 .data = &debug_active, 904 .data = &debug_active,
908 .maxlen = sizeof(int), 905 .maxlen = sizeof(int),
909 .mode = S_IRUGO | S_IWUSR, 906 .mode = S_IRUGO | S_IWUSR,
910 .proc_handler = &s390dbf_procactive, 907 .proc_handler = s390dbf_procactive,
911 .strategy = &sysctl_intvec,
912 }, 908 },
913 { .ctl_name = 0 } 909 { }
914}; 910};
915 911
916static struct ctl_table s390dbf_dir_table[] = { 912static struct ctl_table s390dbf_dir_table[] = {
917 { 913 {
918 .ctl_name = CTL_S390DBF,
919 .procname = "s390dbf", 914 .procname = "s390dbf",
920 .maxlen = 0, 915 .maxlen = 0,
921 .mode = S_IRUGO | S_IXUGO, 916 .mode = S_IRUGO | S_IXUGO,
922 .child = s390dbf_table, 917 .child = s390dbf_table,
923 }, 918 },
924 { .ctl_name = 0 } 919 { }
925}; 920};
926 921
927static struct ctl_table_header *s390dbf_sysctl_header; 922static struct ctl_table_header *s390dbf_sysctl_header;
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index b201135cc18c..ff58779bf7e9 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -343,30 +343,29 @@ static struct ctl_table cmm_table[] = {
343 { 343 {
344 .procname = "cmm_pages", 344 .procname = "cmm_pages",
345 .mode = 0644, 345 .mode = 0644,
346 .proc_handler = &cmm_pages_handler, 346 .proc_handler = cmm_pages_handler,
347 }, 347 },
348 { 348 {
349 .procname = "cmm_timed_pages", 349 .procname = "cmm_timed_pages",
350 .mode = 0644, 350 .mode = 0644,
351 .proc_handler = &cmm_pages_handler, 351 .proc_handler = cmm_pages_handler,
352 }, 352 },
353 { 353 {
354 .procname = "cmm_timeout", 354 .procname = "cmm_timeout",
355 .mode = 0644, 355 .mode = 0644,
356 .proc_handler = &cmm_timeout_handler, 356 .proc_handler = cmm_timeout_handler,
357 }, 357 },
358 { .ctl_name = 0 } 358 { }
359}; 359};
360 360
361static struct ctl_table cmm_dir_table[] = { 361static struct ctl_table cmm_dir_table[] = {
362 { 362 {
363 .ctl_name = CTL_VM,
364 .procname = "vm", 363 .procname = "vm",
365 .maxlen = 0, 364 .maxlen = 0,
366 .mode = 0555, 365 .mode = 0555,
367 .child = cmm_table, 366 .child = cmm_table,
368 }, 367 },
369 { .ctl_name = 0 } 368 { }
370}; 369};
371#endif 370#endif
372 371
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
index 8f305b36358b..e6dd5e96321e 100644
--- a/arch/sh/boards/mach-hp6xx/setup.c
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/irq.h> 15#include <linux/irq.h>
16#include <sound/sh_dac_audio.h>
16#include <asm/hd64461.h> 17#include <asm/hd64461.h>
17#include <asm/io.h> 18#include <asm/io.h>
18#include <mach/hp6xx.h> 19#include <mach/hp6xx.h>
@@ -51,9 +52,63 @@ static struct platform_device jornadakbd_device = {
51 .id = -1, 52 .id = -1,
52}; 53};
53 54
55static void dac_audio_start(struct dac_audio_pdata *pdata)
56{
57 u16 v;
58 u8 v8;
59
60 /* HP Jornada 680/690 speaker on */
61 v = inw(HD64461_GPADR);
62 v &= ~HD64461_GPADR_SPEAKER;
63 outw(v, HD64461_GPADR);
64
65 /* HP Palmtop 620lx/660lx speaker on */
66 v8 = inb(PKDR);
67 v8 &= ~PKDR_SPEAKER;
68 outb(v8, PKDR);
69
70 sh_dac_enable(pdata->channel);
71}
72
73static void dac_audio_stop(struct dac_audio_pdata *pdata)
74{
75 u16 v;
76 u8 v8;
77
78 /* HP Jornada 680/690 speaker off */
79 v = inw(HD64461_GPADR);
80 v |= HD64461_GPADR_SPEAKER;
81 outw(v, HD64461_GPADR);
82
83 /* HP Palmtop 620lx/660lx speaker off */
84 v8 = inb(PKDR);
85 v8 |= PKDR_SPEAKER;
86 outb(v8, PKDR);
87
88 sh_dac_output(0, pdata->channel);
89 sh_dac_disable(pdata->channel);
90}
91
92static struct dac_audio_pdata dac_audio_platform_data = {
93 .buffer_size = 64000,
94 .channel = 1,
95 .start = dac_audio_start,
96 .stop = dac_audio_stop,
97};
98
99static struct platform_device dac_audio_device = {
100 .name = "dac_audio",
101 .id = -1,
102 .dev = {
103 .platform_data = &dac_audio_platform_data,
104 }
105
106};
107
54static struct platform_device *hp6xx_devices[] __initdata = { 108static struct platform_device *hp6xx_devices[] __initdata = {
55 &cf_ide_device, 109 &cf_ide_device,
56 &jornadakbd_device, 110 &jornadakbd_device,
111 &dac_audio_device,
57}; 112};
58 113
59static void __init hp6xx_init_irq(void) 114static void __init hp6xx_init_irq(void)
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index e78c3be8ad2f..0894bba9fade 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -313,6 +313,9 @@ static struct platform_device fsi_device = {
313 .dev = { 313 .dev = {
314 .platform_data = &fsi_info, 314 .platform_data = &fsi_info,
315 }, 315 },
316 .archdata = {
317 .hwblk_id = HWBLK_SPU, /* FSI needs SPU hwblk */
318 },
316}; 319};
317 320
318/* KEYSC in SoC (Needs SW33-2 set to ON) */ 321/* KEYSC in SoC (Needs SW33-2 set to ON) */
diff --git a/arch/sh/include/mach-common/mach/hp6xx.h b/arch/sh/include/mach-common/mach/hp6xx.h
index 0d4165a32dcd..bcc301ac12f4 100644
--- a/arch/sh/include/mach-common/mach/hp6xx.h
+++ b/arch/sh/include/mach-common/mach/hp6xx.h
@@ -29,6 +29,9 @@
29 29
30#define PKDR_LED_GREEN 0x10 30#define PKDR_LED_GREEN 0x10
31 31
32/* HP Palmtop 620lx/660lx speaker on/off */
33#define PKDR_SPEAKER 0x20
34
32#define SCPDR_TS_SCAN_ENABLE 0x20 35#define SCPDR_TS_SCAN_ENABLE 0x20
33#define SCPDR_TS_SCAN_Y 0x02 36#define SCPDR_TS_SCAN_Y 0x02
34#define SCPDR_TS_SCAN_X 0x01 37#define SCPDR_TS_SCAN_X 0x01
@@ -42,6 +45,7 @@
42#define ADC_CHANNEL_BACKUP 4 45#define ADC_CHANNEL_BACKUP 4
43#define ADC_CHANNEL_CHARGE 5 46#define ADC_CHANNEL_CHARGE 5
44 47
48/* HP Jornada 680/690 speaker on/off */
45#define HD64461_GPADR_SPEAKER 0x01 49#define HD64461_GPADR_SPEAKER 0x01
46#define HD64461_GPADR_PCMCIA0 (0x02|0x08) 50#define HD64461_GPADR_PCMCIA0 (0x02|0x08)
47 51
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 267e5ebbb475..75c0cbe2eda0 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -877,44 +877,39 @@ static int misaligned_fixup(struct pt_regs *regs)
877 877
878static ctl_table unaligned_table[] = { 878static ctl_table unaligned_table[] = {
879 { 879 {
880 .ctl_name = CTL_UNNUMBERED,
881 .procname = "kernel_reports", 880 .procname = "kernel_reports",
882 .data = &kernel_mode_unaligned_fixup_count, 881 .data = &kernel_mode_unaligned_fixup_count,
883 .maxlen = sizeof(int), 882 .maxlen = sizeof(int),
884 .mode = 0644, 883 .mode = 0644,
885 .proc_handler = &proc_dointvec 884 .proc_handler = proc_dointvec
886 }, 885 },
887 { 886 {
888 .ctl_name = CTL_UNNUMBERED,
889 .procname = "user_reports", 887 .procname = "user_reports",
890 .data = &user_mode_unaligned_fixup_count, 888 .data = &user_mode_unaligned_fixup_count,
891 .maxlen = sizeof(int), 889 .maxlen = sizeof(int),
892 .mode = 0644, 890 .mode = 0644,
893 .proc_handler = &proc_dointvec 891 .proc_handler = proc_dointvec
894 }, 892 },
895 { 893 {
896 .ctl_name = CTL_UNNUMBERED,
897 .procname = "user_enable", 894 .procname = "user_enable",
898 .data = &user_mode_unaligned_fixup_enable, 895 .data = &user_mode_unaligned_fixup_enable,
899 .maxlen = sizeof(int), 896 .maxlen = sizeof(int),
900 .mode = 0644, 897 .mode = 0644,
901 .proc_handler = &proc_dointvec}, 898 .proc_handler = proc_dointvec},
902 {} 899 {}
903}; 900};
904 901
905static ctl_table unaligned_root[] = { 902static ctl_table unaligned_root[] = {
906 { 903 {
907 .ctl_name = CTL_UNNUMBERED,
908 .procname = "unaligned_fixup", 904 .procname = "unaligned_fixup",
909 .mode = 0555, 905 .mode = 0555,
910 unaligned_table 906 .child = unaligned_table
911 }, 907 },
912 {} 908 {}
913}; 909};
914 910
915static ctl_table sh64_root[] = { 911static ctl_table sh64_root[] = {
916 { 912 {
917 .ctl_name = CTL_UNNUMBERED,
918 .procname = "sh64", 913 .procname = "sh64",
919 .mode = 0555, 914 .mode = 0555,
920 .child = unaligned_root 915 .child = unaligned_root
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 05ef5380a687..33ac1a9ac881 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -221,6 +221,13 @@ config SPARC64_SMP
221 default y 221 default y
222 depends on SPARC64 && SMP 222 depends on SPARC64 && SMP
223 223
224config EARLYFB
225 bool "Support for early boot text console"
226 default y
227 depends on SPARC64
228 help
229 Say Y here to enable a faster early framebuffer boot console.
230
224choice 231choice
225 prompt "Kernel page size" if SPARC64 232 prompt "Kernel page size" if SPARC64
226 default SPARC64_PAGE_SIZE_8KB 233 default SPARC64_PAGE_SIZE_8KB
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index dfe272d14465..113225b241e0 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -27,6 +27,7 @@ AS := $(AS) -32
27LDFLAGS := -m elf32_sparc 27LDFLAGS := -m elf32_sparc
28CHECKFLAGS += -D__sparc__ 28CHECKFLAGS += -D__sparc__
29export BITS := 32 29export BITS := 32
30UTS_MACHINE := sparc
30 31
31#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 32#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
32KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 33KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
@@ -46,6 +47,7 @@ CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
46 47
47LDFLAGS := -m elf64_sparc 48LDFLAGS := -m elf64_sparc
48export BITS := 64 49export BITS := 64
50UTS_MACHINE := sparc64
49 51
50KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ 52KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
51 -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ 53 -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \
diff --git a/arch/sparc/include/asm/btext.h b/arch/sparc/include/asm/btext.h
new file mode 100644
index 000000000000..9b2bc6b6ed0a
--- /dev/null
+++ b/arch/sparc/include/asm/btext.h
@@ -0,0 +1,6 @@
1#ifndef _SPARC_BTEXT_H
2#define _SPARC_BTEXT_H
3
4extern int btext_find_display(void);
5
6#endif /* _SPARC_BTEXT_H */
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index 28a42b73f64f..3ea5964c43b4 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -148,7 +148,7 @@ static inline unsigned long leon_load_reg(unsigned long paddr)
148 return retval; 148 return retval;
149} 149}
150 150
151extern inline void leon_srmmu_disabletlb(void) 151static inline void leon_srmmu_disabletlb(void)
152{ 152{
153 unsigned int retval; 153 unsigned int retval;
154 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0), 154 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
@@ -158,7 +158,7 @@ extern inline void leon_srmmu_disabletlb(void)
158 "i"(ASI_LEON_MMUREGS) : "memory"); 158 "i"(ASI_LEON_MMUREGS) : "memory");
159} 159}
160 160
161extern inline void leon_srmmu_enabletlb(void) 161static inline void leon_srmmu_enabletlb(void)
162{ 162{
163 unsigned int retval; 163 unsigned int retval;
164 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0), 164 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
@@ -190,7 +190,7 @@ extern void leon_init_IRQ(void);
190 190
191extern unsigned long last_valid_pfn; 191extern unsigned long last_valid_pfn;
192 192
193extern inline unsigned long sparc_leon3_get_dcachecfg(void) 193static inline unsigned long sparc_leon3_get_dcachecfg(void)
194{ 194{
195 unsigned int retval; 195 unsigned int retval;
196 __asm__ __volatile__("lda [%1] %2, %0\n\t" : 196 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
@@ -201,7 +201,7 @@ extern inline unsigned long sparc_leon3_get_dcachecfg(void)
201} 201}
202 202
203/* enable snooping */ 203/* enable snooping */
204extern inline void sparc_leon3_enable_snooping(void) 204static inline void sparc_leon3_enable_snooping(void)
205{ 205{
206 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t" 206 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
207 "set 0x800000, %%l2\n\t" 207 "set 0x800000, %%l2\n\t"
@@ -209,7 +209,14 @@ extern inline void sparc_leon3_enable_snooping(void)
209 "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); 209 "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
210}; 210};
211 211
212extern inline void sparc_leon3_disable_cache(void) 212static inline int sparc_leon3_snooping_enabled(void)
213{
214 u32 cctrl;
215 __asm__ __volatile__("lda [%%g0] 2, %0\n\t" : "=r"(cctrl));
216 return (cctrl >> 23) & 1;
217};
218
219static inline void sparc_leon3_disable_cache(void)
213{ 220{
214 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t" 221 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
215 "set 0x00000f, %%l2\n\t" 222 "set 0x00000f, %%l2\n\t"
@@ -340,6 +347,30 @@ extern int leon_flush_needed(void);
340extern void leon_switch_mm(void); 347extern void leon_switch_mm(void);
341extern int srmmu_swprobe_trace; 348extern int srmmu_swprobe_trace;
342 349
350#ifdef CONFIG_SMP
351extern int leon_smp_nrcpus(void);
352extern void leon_clear_profile_irq(int cpu);
353extern void leon_smp_done(void);
354extern void leon_boot_cpus(void);
355extern int leon_boot_one_cpu(int i);
356void leon_init_smp(void);
357extern void cpu_probe(void);
358extern void cpu_idle(void);
359extern void init_IRQ(void);
360extern void cpu_panic(void);
361extern int __leon_processor_id(void);
362void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
363
364extern unsigned int real_irq_entry[], smpleon_ticker[];
365extern unsigned int patchme_maybe_smp_msg[];
366extern unsigned long trapbase_cpu1[];
367extern unsigned long trapbase_cpu2[];
368extern unsigned long trapbase_cpu3[];
369extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
370extern unsigned int linux_trap_ipi15_sun4m[];
371
372#endif /* CONFIG_SMP */
373
343#endif /* __KERNEL__ */ 374#endif /* __KERNEL__ */
344 375
345#endif /* __ASSEMBLY__ */ 376#endif /* __ASSEMBLY__ */
@@ -356,6 +387,10 @@ extern int srmmu_swprobe_trace;
356#define leon_switch_mm() do {} while (0) 387#define leon_switch_mm() do {} while (0)
357#define leon_init_IRQ() do {} while (0) 388#define leon_init_IRQ() do {} while (0)
358#define init_leon() do {} while (0) 389#define init_leon() do {} while (0)
390#define leon_smp_done() do {} while (0)
391#define leon_boot_cpus() do {} while (0)
392#define leon_boot_one_cpu(i) 1
393#define leon_init_smp() do {} while (0)
359 394
360#endif /* !defined(CONFIG_SPARC_LEON) */ 395#endif /* !defined(CONFIG_SPARC_LEON) */
361 396
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 82a190d7efc1..f845828ca4c6 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -1,3 +1,4 @@
1#include <linux/of.h> /* linux/of.h gets to determine #include ordering */
1#ifndef _SPARC_PROM_H 2#ifndef _SPARC_PROM_H
2#define _SPARC_PROM_H 3#define _SPARC_PROM_H
3#ifdef __KERNEL__ 4#ifdef __KERNEL__
@@ -28,50 +29,11 @@
28#define of_prop_cmp(s1, s2) strcasecmp((s1), (s2)) 29#define of_prop_cmp(s1, s2) strcasecmp((s1), (s2))
29#define of_node_cmp(s1, s2) strcmp((s1), (s2)) 30#define of_node_cmp(s1, s2) strcmp((s1), (s2))
30 31
31typedef u32 phandle;
32typedef u32 ihandle;
33
34struct property {
35 char *name;
36 int length;
37 void *value;
38 struct property *next;
39 unsigned long _flags;
40 unsigned int unique_id;
41};
42
43struct of_irq_controller;
44struct device_node {
45 const char *name;
46 const char *type;
47 phandle node;
48 char *path_component_name;
49 char *full_name;
50
51 struct property *properties;
52 struct property *deadprops; /* removed properties */
53 struct device_node *parent;
54 struct device_node *child;
55 struct device_node *sibling;
56 struct device_node *next; /* next device of same type */
57 struct device_node *allnext; /* next in list of all nodes */
58 struct proc_dir_entry *pde; /* this node's proc directory */
59 struct kref kref;
60 unsigned long _flags;
61 void *data;
62 unsigned int unique_id;
63
64 struct of_irq_controller *irq_trans;
65};
66
67struct of_irq_controller { 32struct of_irq_controller {
68 unsigned int (*irq_build)(struct device_node *, unsigned int, void *); 33 unsigned int (*irq_build)(struct device_node *, unsigned int, void *);
69 void *data; 34 void *data;
70}; 35};
71 36
72#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
73#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
74
75extern struct device_node *of_find_node_by_cpuid(int cpuid); 37extern struct device_node *of_find_node_by_cpuid(int cpuid);
76extern int of_set_property(struct device_node *node, const char *name, void *val, int len); 38extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
77extern struct mutex of_set_property_mutex; 39extern struct mutex of_set_property_mutex;
@@ -89,15 +51,6 @@ extern void prom_build_devicetree(void);
89extern void of_populate_present_mask(void); 51extern void of_populate_present_mask(void);
90extern void of_fill_in_cpu_data(void); 52extern void of_fill_in_cpu_data(void);
91 53
92/* Dummy ref counting routines - to be implemented later */
93static inline struct device_node *of_node_get(struct device_node *node)
94{
95 return node;
96}
97static inline void of_node_put(struct device_node *node)
98{
99}
100
101/* These routines are here to provide compatibility with how powerpc 54/* These routines are here to provide compatibility with how powerpc
102 * handles IRQ mapping for OF device nodes. We precompute and permanently 55 * handles IRQ mapping for OF device nodes. We precompute and permanently
103 * register them in the of_device objects, whereas powerpc computes them 56 * register them in the of_device objects, whereas powerpc computes them
@@ -108,12 +61,6 @@ static inline void irq_dispose_mapping(unsigned int virq)
108{ 61{
109} 62}
110 63
111/*
112 * NB: This is here while we transition from using asm/prom.h
113 * to linux/of.h
114 */
115#include <linux/of.h>
116
117extern struct device_node *of_console_device; 64extern struct device_node *of_console_device;
118extern char *of_console_path; 65extern char *of_console_path;
119extern char *of_console_options; 66extern char *of_console_options;
diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h
index 1dc129ac2feb..6e5621006f85 100644
--- a/arch/sparc/include/asm/rwsem.h
+++ b/arch/sparc/include/asm/rwsem.h
@@ -35,8 +35,8 @@ struct rw_semaphore {
35#endif 35#endif
36 36
37#define __RWSEM_INITIALIZER(name) \ 37#define __RWSEM_INITIALIZER(name) \
38{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \ 38{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
39 __RWSEM_DEP_MAP_INIT(name) } 39 LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
40 40
41#define DECLARE_RWSEM(name) \ 41#define DECLARE_RWSEM(name) \
42 struct rw_semaphore name = __RWSEM_INITIALIZER(name) 42 struct rw_semaphore name = __RWSEM_INITIALIZER(name)
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 58101dc70493..841905c10215 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -106,6 +106,15 @@ static inline int hard_smp4d_processor_id(void)
106 return cpuid; 106 return cpuid;
107} 107}
108 108
109extern inline int hard_smpleon_processor_id(void)
110{
111 int cpuid;
112 __asm__ __volatile__("rd %%asr17,%0\n\t"
113 "srl %0,28,%0" :
114 "=&r" (cpuid) : );
115 return cpuid;
116}
117
109#ifndef MODULE 118#ifndef MODULE
110static inline int hard_smp_processor_id(void) 119static inline int hard_smp_processor_id(void)
111{ 120{
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 5b47fab9966e..c6316142db4e 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -72,7 +72,7 @@ obj-y += dma.o
72obj-$(CONFIG_SPARC32_PCI) += pcic.o 72obj-$(CONFIG_SPARC32_PCI) += pcic.o
73 73
74obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o 74obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o
75obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o 75obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o
76obj-$(CONFIG_SPARC64_SMP) += hvtramp.o 76obj-$(CONFIG_SPARC64_SMP) += hvtramp.o
77 77
78obj-y += auxio_$(BITS).o 78obj-y += auxio_$(BITS).o
@@ -87,6 +87,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).o
87obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 87obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
88CFLAGS_REMOVE_ftrace.o := -pg 88CFLAGS_REMOVE_ftrace.o := -pg
89 89
90obj-$(CONFIG_EARLYFB) += btext.o
90obj-$(CONFIG_STACKTRACE) += stacktrace.o 91obj-$(CONFIG_STACKTRACE) += stacktrace.o
91# sparc64 PCI 92# sparc64 PCI
92obj-$(CONFIG_SPARC64_PCI) += pci.o pci_common.o psycho_common.o 93obj-$(CONFIG_SPARC64_PCI) += pci.o pci_common.o psycho_common.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 9c115823c4b5..71ec90b9e316 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -10,7 +10,6 @@
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/miscdevice.h> 12#include <linux/miscdevice.h>
13#include <linux/smp_lock.h>
14#include <linux/pm.h> 13#include <linux/pm.h>
15#include <linux/of.h> 14#include <linux/of.h>
16#include <linux/of_device.h> 15#include <linux/of_device.h>
@@ -76,7 +75,6 @@ static inline void apc_free(struct of_device *op)
76 75
77static int apc_open(struct inode *inode, struct file *f) 76static int apc_open(struct inode *inode, struct file *f)
78{ 77{
79 cycle_kernel_lock();
80 return 0; 78 return 0;
81} 79}
82 80
@@ -87,61 +85,46 @@ static int apc_release(struct inode *inode, struct file *f)
87 85
88static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) 86static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
89{ 87{
90 __u8 inarg, __user *arg; 88 __u8 inarg, __user *arg = (__u8 __user *) __arg;
91
92 arg = (__u8 __user *) __arg;
93
94 lock_kernel();
95 89
96 switch (cmd) { 90 switch (cmd) {
97 case APCIOCGFANCTL: 91 case APCIOCGFANCTL:
98 if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg)) { 92 if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg))
99 unlock_kernel();
100 return -EFAULT; 93 return -EFAULT;
101 }
102 break; 94 break;
103 95
104 case APCIOCGCPWR: 96 case APCIOCGCPWR:
105 if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg)) { 97 if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg))
106 unlock_kernel();
107 return -EFAULT; 98 return -EFAULT;
108 }
109 break; 99 break;
110 100
111 case APCIOCGBPORT: 101 case APCIOCGBPORT:
112 if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg)) { 102 if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg))
113 unlock_kernel();
114 return -EFAULT; 103 return -EFAULT;
115 }
116 break; 104 break;
117 105
118 case APCIOCSFANCTL: 106 case APCIOCSFANCTL:
119 if (get_user(inarg, arg)) { 107 if (get_user(inarg, arg))
120 unlock_kernel();
121 return -EFAULT; 108 return -EFAULT;
122 }
123 apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG); 109 apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG);
124 break; 110 break;
111
125 case APCIOCSCPWR: 112 case APCIOCSCPWR:
126 if (get_user(inarg, arg)) { 113 if (get_user(inarg, arg))
127 unlock_kernel();
128 return -EFAULT; 114 return -EFAULT;
129 }
130 apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG); 115 apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG);
131 break; 116 break;
117
132 case APCIOCSBPORT: 118 case APCIOCSBPORT:
133 if (get_user(inarg, arg)) { 119 if (get_user(inarg, arg))
134 unlock_kernel();
135 return -EFAULT; 120 return -EFAULT;
136 }
137 apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG); 121 apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG);
138 break; 122 break;
123
139 default: 124 default:
140 unlock_kernel();
141 return -EINVAL; 125 return -EINVAL;
142 }; 126 };
143 127
144 unlock_kernel();
145 return 0; 128 return 0;
146} 129}
147 130
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index 45c41232fc4c..ee8d214cae1e 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -28,6 +28,7 @@ void __init auxio_probe(void)
28 struct resource r; 28 struct resource r;
29 29
30 switch (sparc_cpu_model) { 30 switch (sparc_cpu_model) {
31 case sparc_leon:
31 case sun4d: 32 case sun4d:
32 case sun4: 33 case sun4:
33 return; 34 return;
diff --git a/arch/sparc/kernel/btext.c b/arch/sparc/kernel/btext.c
new file mode 100644
index 000000000000..8cc2d56ffe9a
--- /dev/null
+++ b/arch/sparc/kernel/btext.c
@@ -0,0 +1,673 @@
1/*
2 * Procedures for drawing on the screen early on in the boot process.
3 *
4 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
5 */
6#include <linux/kernel.h>
7#include <linux/string.h>
8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/console.h>
11
12#include <asm/btext.h>
13#include <asm/oplib.h>
14#include <asm/io.h>
15
16#define NO_SCROLL
17
18#ifndef NO_SCROLL
19static void scrollscreen(void);
20#endif
21
22static void draw_byte(unsigned char c, long locX, long locY);
23static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
24static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
25static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
26
27#define __force_data __attribute__((__section__(".data")))
28
29static int g_loc_X __force_data;
30static int g_loc_Y __force_data;
31static int g_max_loc_X __force_data;
32static int g_max_loc_Y __force_data;
33
34static int dispDeviceRowBytes __force_data;
35static int dispDeviceDepth __force_data;
36static int dispDeviceRect[4] __force_data;
37static unsigned char *dispDeviceBase __force_data;
38
39#define cmapsz (16*256)
40
41static unsigned char vga_font[cmapsz];
42
43static int __init btext_initialize(unsigned int node)
44{
45 unsigned int width, height, depth, pitch;
46 unsigned long address = 0;
47 u32 prop;
48
49 if (prom_getproperty(node, "width", (char *)&width, 4) < 0)
50 return -EINVAL;
51 if (prom_getproperty(node, "height", (char *)&height, 4) < 0)
52 return -EINVAL;
53 if (prom_getproperty(node, "depth", (char *)&depth, 4) < 0)
54 return -EINVAL;
55 pitch = width * ((depth + 7) / 8);
56
57 if (prom_getproperty(node, "linebytes", (char *)&prop, 4) >= 0 &&
58 prop != 0xffffffffu)
59 pitch = prop;
60
61 if (pitch == 1)
62 pitch = 0x1000;
63
64 if (prom_getproperty(node, "address", (char *)&prop, 4) >= 0)
65 address = prop;
66
67 /* FIXME: Add support for PCI reg properties. Right now, only
68 * reliable on macs
69 */
70 if (address == 0)
71 return -EINVAL;
72
73 g_loc_X = 0;
74 g_loc_Y = 0;
75 g_max_loc_X = width / 8;
76 g_max_loc_Y = height / 16;
77 dispDeviceBase = (unsigned char *)address;
78 dispDeviceRowBytes = pitch;
79 dispDeviceDepth = depth == 15 ? 16 : depth;
80 dispDeviceRect[0] = dispDeviceRect[1] = 0;
81 dispDeviceRect[2] = width;
82 dispDeviceRect[3] = height;
83
84 return 0;
85}
86
87/* Calc the base address of a given point (x,y) */
88static unsigned char * calc_base(int x, int y)
89{
90 unsigned char *base = dispDeviceBase;
91
92 base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);
93 base += (y + dispDeviceRect[1]) * dispDeviceRowBytes;
94 return base;
95}
96
97static void btext_clearscreen(void)
98{
99 unsigned int *base = (unsigned int *)calc_base(0, 0);
100 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
101 (dispDeviceDepth >> 3)) >> 2;
102 int i,j;
103
104 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
105 {
106 unsigned int *ptr = base;
107 for(j=width; j; --j)
108 *(ptr++) = 0;
109 base += (dispDeviceRowBytes >> 2);
110 }
111}
112
113#ifndef NO_SCROLL
114static void scrollscreen(void)
115{
116 unsigned int *src = (unsigned int *)calc_base(0,16);
117 unsigned int *dst = (unsigned int *)calc_base(0,0);
118 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
119 (dispDeviceDepth >> 3)) >> 2;
120 int i,j;
121
122 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
123 {
124 unsigned int *src_ptr = src;
125 unsigned int *dst_ptr = dst;
126 for(j=width; j; --j)
127 *(dst_ptr++) = *(src_ptr++);
128 src += (dispDeviceRowBytes >> 2);
129 dst += (dispDeviceRowBytes >> 2);
130 }
131 for (i=0; i<16; i++)
132 {
133 unsigned int *dst_ptr = dst;
134 for(j=width; j; --j)
135 *(dst_ptr++) = 0;
136 dst += (dispDeviceRowBytes >> 2);
137 }
138}
139#endif /* ndef NO_SCROLL */
140
141void btext_drawchar(char c)
142{
143 int cline = 0;
144#ifdef NO_SCROLL
145 int x;
146#endif
147 switch (c) {
148 case '\b':
149 if (g_loc_X > 0)
150 --g_loc_X;
151 break;
152 case '\t':
153 g_loc_X = (g_loc_X & -8) + 8;
154 break;
155 case '\r':
156 g_loc_X = 0;
157 break;
158 case '\n':
159 g_loc_X = 0;
160 g_loc_Y++;
161 cline = 1;
162 break;
163 default:
164 draw_byte(c, g_loc_X++, g_loc_Y);
165 }
166 if (g_loc_X >= g_max_loc_X) {
167 g_loc_X = 0;
168 g_loc_Y++;
169 cline = 1;
170 }
171#ifndef NO_SCROLL
172 while (g_loc_Y >= g_max_loc_Y) {
173 scrollscreen();
174 g_loc_Y--;
175 }
176#else
177 /* wrap around from bottom to top of screen so we don't
178 waste time scrolling each line. -- paulus. */
179 if (g_loc_Y >= g_max_loc_Y)
180 g_loc_Y = 0;
181 if (cline) {
182 for (x = 0; x < g_max_loc_X; ++x)
183 draw_byte(' ', x, g_loc_Y);
184 }
185#endif
186}
187
188static void btext_drawtext(const char *c, unsigned int len)
189{
190 while (len--)
191 btext_drawchar(*c++);
192}
193
194static void draw_byte(unsigned char c, long locX, long locY)
195{
196 unsigned char *base = calc_base(locX << 3, locY << 4);
197 unsigned char *font = &vga_font[((unsigned int)c) * 16];
198 int rb = dispDeviceRowBytes;
199
200 switch(dispDeviceDepth) {
201 case 24:
202 case 32:
203 draw_byte_32(font, (unsigned int *)base, rb);
204 break;
205 case 15:
206 case 16:
207 draw_byte_16(font, (unsigned int *)base, rb);
208 break;
209 case 8:
210 draw_byte_8(font, (unsigned int *)base, rb);
211 break;
212 }
213}
214
215static unsigned int expand_bits_8[16] = {
216 0x00000000,
217 0x000000ff,
218 0x0000ff00,
219 0x0000ffff,
220 0x00ff0000,
221 0x00ff00ff,
222 0x00ffff00,
223 0x00ffffff,
224 0xff000000,
225 0xff0000ff,
226 0xff00ff00,
227 0xff00ffff,
228 0xffff0000,
229 0xffff00ff,
230 0xffffff00,
231 0xffffffff
232};
233
234static unsigned int expand_bits_16[4] = {
235 0x00000000,
236 0x0000ffff,
237 0xffff0000,
238 0xffffffff
239};
240
241
242static void draw_byte_32(unsigned char *font, unsigned int *base, int rb)
243{
244 int l, bits;
245 int fg = 0xFFFFFFFFUL;
246 int bg = 0x00000000UL;
247
248 for (l = 0; l < 16; ++l)
249 {
250 bits = *font++;
251 base[0] = (-(bits >> 7) & fg) ^ bg;
252 base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
253 base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
254 base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
255 base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
256 base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
257 base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
258 base[7] = (-(bits & 1) & fg) ^ bg;
259 base = (unsigned int *) ((char *)base + rb);
260 }
261}
262
263static void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
264{
265 int l, bits;
266 int fg = 0xFFFFFFFFUL;
267 int bg = 0x00000000UL;
268 unsigned int *eb = (int *)expand_bits_16;
269
270 for (l = 0; l < 16; ++l)
271 {
272 bits = *font++;
273 base[0] = (eb[bits >> 6] & fg) ^ bg;
274 base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
275 base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
276 base[3] = (eb[bits & 3] & fg) ^ bg;
277 base = (unsigned int *) ((char *)base + rb);
278 }
279}
280
281static void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
282{
283 int l, bits;
284 int fg = 0x0F0F0F0FUL;
285 int bg = 0x00000000UL;
286 unsigned int *eb = (int *)expand_bits_8;
287
288 for (l = 0; l < 16; ++l)
289 {
290 bits = *font++;
291 base[0] = (eb[bits >> 4] & fg) ^ bg;
292 base[1] = (eb[bits & 0xf] & fg) ^ bg;
293 base = (unsigned int *) ((char *)base + rb);
294 }
295}
296
297static void btext_console_write(struct console *con, const char *s,
298 unsigned int n)
299{
300 btext_drawtext(s, n);
301}
302
303static struct console btext_console = {
304 .name = "btext",
305 .write = btext_console_write,
306 .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME,
307 .index = 0,
308};
309
310int __init btext_find_display(void)
311{
312 unsigned int node;
313 char type[32];
314 int ret;
315
316 node = prom_inst2pkg(prom_stdout);
317 if (prom_getproperty(node, "device_type", type, 32) < 0)
318 return -ENODEV;
319 if (strcmp(type, "display"))
320 return -ENODEV;
321
322 ret = btext_initialize(node);
323 if (!ret) {
324 btext_clearscreen();
325 register_console(&btext_console);
326 }
327 return ret;
328}
329
330static unsigned char vga_font[cmapsz] = {
3310x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
3330x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
3340xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
3350x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
3360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
3370x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
3380x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
3390x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
3400x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
3410x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3420xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3430x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
3440x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
3450xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
3460x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
3470x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
3480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
3490x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
3500x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
3510x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
3520x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
3530xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
3540x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
3550x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
3560x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
3570x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
3580xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
3590x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
3600x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3610xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
3620x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
3630x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
3640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
3650x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3670x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
3680x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
3690xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3710x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
3720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
3730x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3740x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3750x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
3760x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
3770x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
3780x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
3790x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
3800x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
3810x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
3820x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
3830x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3840x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
3850x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
3860x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
3870x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
3880x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
3890x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3900x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
3910x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
3920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3930x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3940x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
3950x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
3960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
3970x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
3980x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
3990x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
4000x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
4010x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
4020xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
4030x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
4040x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
4050x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
4060xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
4070x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
4080x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
4090x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4100x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
4110x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
4120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
4130x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
4140x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
4150x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
4160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
4170xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
4180x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
4190x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
4200x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
4210xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
4220x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
4230x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
4240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
4250x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
4260xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
4270x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
4280x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
4290x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
4300x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
4310x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
4320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
4330x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
4340xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
4350x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
4360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
4370xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
4380x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
4390x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
4400x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
4410x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
4420xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
4430x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
4440x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
4450xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
4460xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
4470x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
4480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
4490x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
4500xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
4510x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
4520x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
4530x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
4540xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
4550x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
4560x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
4570x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4580x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
4590x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4600x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
4610xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
4620x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
4630x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
4640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
4650xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4660x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
4670x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
4680x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
4690xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
4700x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
4710x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
4720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
4730x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
4740x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
4750x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
4760x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
4770xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4780x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
4790x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
4800x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
4810x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
4820x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
4830x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
4840x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
4850x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
4860x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
4870x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
4880x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
4890xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4900x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
4910x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
4920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
4930xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
4940x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
4950x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
4960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
4970x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
4980x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
4990x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5000x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
5010xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
5020xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
5030x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
5040x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
5050xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
5060x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
5070x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
5080x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
5090xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
5100x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
5110x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
5120x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
5130xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
5140x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
5150x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
5160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
5170x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
5180x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
5190x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
5200x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
5210xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
5220x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
5230x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
5240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
5250x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
5260xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
5270x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
5280x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
5290xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
5300x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
5310x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
5320x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
5330xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
5340x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
5350x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
5360x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
5370xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
5380xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
5390x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
5400x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
5410xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
5420x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
5430x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
5440xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
5450xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
5460x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
5470x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
5480x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
5490xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
5500x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
5510x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
5520x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
5530x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
5540x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5550x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
5560x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
5570xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5580x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
5590x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
5600x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
5610x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
5620x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
5630x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
5640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
5650x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
5660x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
5670x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
5680x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
5690xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
5700x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
5710x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
5720x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
5730x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
5740x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5750x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
5760x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
5770x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
5780x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5790x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5800x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
5810x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5820x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5830x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
5840x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
5850x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5860x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
5870x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
5880x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
5890x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5900x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
5910x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
5920x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
5930x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
5940x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
5950x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
5960x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
5970x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5980x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5990x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
6000x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
6010x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6020x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
6030x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
6040x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
6050x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
6060x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
6070x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
6080x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
6090x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6100x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
6110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
6120x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
6130x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
6140x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6150x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
6160x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
6170x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
6180x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
6190x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
6200x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
6210x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6220x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
6230xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6240xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
6250xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
6260xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
6270x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
6280x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
6290x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6300x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
6310x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
6320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
6330xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6340xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
6350x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
6360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
6370xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6380x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
6390x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
6400x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
6410x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
6420x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
6430x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
6440x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
6450x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6460x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6470x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
6480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
6490x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
6500xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
6510x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
6520x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
6530x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
6540x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
6550x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
6560x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
6570x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
6580x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
6590x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
6600x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
6610x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
6620x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6630x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
6640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6650x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
6660x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
6670x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
6680x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
6690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6700x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
6710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6720x00, 0x00, 0x00, 0x00,
673};
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 1446df90ef85..e447938d39cf 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -185,6 +185,17 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
185 FPU(-1, NULL) 185 FPU(-1, NULL)
186 } 186 }
187},{ 187},{
188 0xF, /* Aeroflex Gaisler */
189 .cpu_info = {
190 CPU(3, "LEON"),
191 CPU(-1, NULL)
192 },
193 .fpu_info = {
194 FPU(2, "GRFPU"),
195 FPU(3, "GRFPU-Lite"),
196 FPU(-1, NULL)
197 }
198},{
188 0x17, 199 0x17,
189 .cpu_info = { 200 .cpu_info = {
190 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), 201 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"),
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index f41ecc5ac0b4..ec9c7bc67d21 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -400,6 +400,39 @@ linux_trap_ipi15_sun4d:
400 /* FIXME */ 400 /* FIXME */
4011: b,a 1b 4011: b,a 1b
402 402
403#ifdef CONFIG_SPARC_LEON
404
405 .globl smpleon_ticker
406 /* SMP per-cpu ticker interrupts are handled specially. */
407smpleon_ticker:
408 SAVE_ALL
409 or %l0, PSR_PIL, %g2
410 wr %g2, 0x0, %psr
411 WRITE_PAUSE
412 wr %g2, PSR_ET, %psr
413 WRITE_PAUSE
414 call leon_percpu_timer_interrupt
415 add %sp, STACKFRAME_SZ, %o0
416 wr %l0, PSR_ET, %psr
417 WRITE_PAUSE
418 RESTORE_ALL
419
420 .align 4
421 .globl linux_trap_ipi15_leon
422linux_trap_ipi15_leon:
423 SAVE_ALL
424 or %l0, PSR_PIL, %l4
425 wr %l4, 0x0, %psr
426 WRITE_PAUSE
427 wr %l4, PSR_ET, %psr
428 WRITE_PAUSE
429 call leon_cross_call_irq
430 nop
431 b ret_trap_lockless_ipi
432 clr %l6
433
434#endif /* CONFIG_SPARC_LEON */
435
403#endif /* CONFIG_SMP */ 436#endif /* CONFIG_SMP */
404 437
405 /* This routine handles illegal instructions and privileged 438 /* This routine handles illegal instructions and privileged
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 439d82a95ac9..21bb2590d4ae 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -811,9 +811,31 @@ found_version:
811got_prop: 811got_prop:
812#ifdef CONFIG_SPARC_LEON 812#ifdef CONFIG_SPARC_LEON
813 /* no cpu-type check is needed, it is a SPARC-LEON */ 813 /* no cpu-type check is needed, it is a SPARC-LEON */
814#ifdef CONFIG_SMP
815 ba leon_smp_init
816 nop
817
818 .global leon_smp_init
819leon_smp_init:
820 sethi %hi(boot_cpu_id), %g1 ! master always 0
821 stb %g0, [%g1 + %lo(boot_cpu_id)]
822 sethi %hi(boot_cpu_id4), %g1 ! master always 0
823 stb %g0, [%g1 + %lo(boot_cpu_id4)]
824
825 rd %asr17,%g1
826 srl %g1,28,%g1
827
828 cmp %g0,%g1
829 beq sun4c_continue_boot !continue with master
830 nop
831
832 ba leon_smp_cpu_startup
833 nop
834#else
814 ba sun4c_continue_boot 835 ba sun4c_continue_boot
815 nop 836 nop
816#endif 837#endif
838#endif
817 set cputypval, %o2 839 set cputypval, %o2
818 ldub [%o2 + 0x4], %l1 840 ldub [%o2 + 0x4], %l1
819 841
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 9f61fd8cbb7b..3c8c44f6a41c 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -48,8 +48,13 @@
48#include <asm/dma.h> 48#include <asm/dma.h>
49#include <asm/iommu.h> 49#include <asm/iommu.h>
50#include <asm/io-unit.h> 50#include <asm/io-unit.h>
51#include <asm/leon.h>
51 52
53#ifdef CONFIG_SPARC_LEON
54#define mmu_inval_dma_area(p, l) leon_flush_dcache_all()
55#else
52#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ 56#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */
57#endif
53 58
54static struct resource *_sparc_find_resource(struct resource *r, 59static struct resource *_sparc_find_resource(struct resource *r,
55 unsigned long); 60 unsigned long);
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 8ab1d4728a4b..ce996f97855f 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -187,7 +187,7 @@ int show_interrupts(struct seq_file *p, void *v)
187 for_each_online_cpu(j) 187 for_each_online_cpu(j)
188 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); 188 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
189#endif 189#endif
190 seq_printf(p, " %9s", irq_desc[i].chip->typename); 190 seq_printf(p, " %9s", irq_desc[i].chip->name);
191 seq_printf(p, " %s", action->name); 191 seq_printf(p, " %s", action->name);
192 192
193 for (action=action->next; action; action = action->next) 193 for (action=action->next; action; action = action->next)
@@ -484,7 +484,7 @@ static void sun4v_virq_eoi(unsigned int virt_irq)
484} 484}
485 485
486static struct irq_chip sun4u_irq = { 486static struct irq_chip sun4u_irq = {
487 .typename = "sun4u", 487 .name = "sun4u",
488 .enable = sun4u_irq_enable, 488 .enable = sun4u_irq_enable,
489 .disable = sun4u_irq_disable, 489 .disable = sun4u_irq_disable,
490 .eoi = sun4u_irq_eoi, 490 .eoi = sun4u_irq_eoi,
@@ -492,7 +492,7 @@ static struct irq_chip sun4u_irq = {
492}; 492};
493 493
494static struct irq_chip sun4v_irq = { 494static struct irq_chip sun4v_irq = {
495 .typename = "sun4v", 495 .name = "sun4v",
496 .enable = sun4v_irq_enable, 496 .enable = sun4v_irq_enable,
497 .disable = sun4v_irq_disable, 497 .disable = sun4v_irq_disable,
498 .eoi = sun4v_irq_eoi, 498 .eoi = sun4v_irq_eoi,
@@ -500,7 +500,7 @@ static struct irq_chip sun4v_irq = {
500}; 500};
501 501
502static struct irq_chip sun4v_virq = { 502static struct irq_chip sun4v_virq = {
503 .typename = "vsun4v", 503 .name = "vsun4v",
504 .enable = sun4v_virq_enable, 504 .enable = sun4v_virq_enable,
505 .disable = sun4v_virq_disable, 505 .disable = sun4v_virq_disable,
506 .eoi = sun4v_virq_eoi, 506 .eoi = sun4v_virq_eoi,
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 54d8a5bd4824..87f1760c0aa2 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -12,11 +12,14 @@
12#include <linux/of_platform.h> 12#include <linux/of_platform.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/of_device.h> 14#include <linux/of_device.h>
15
15#include <asm/oplib.h> 16#include <asm/oplib.h>
16#include <asm/timer.h> 17#include <asm/timer.h>
17#include <asm/prom.h> 18#include <asm/prom.h>
18#include <asm/leon.h> 19#include <asm/leon.h>
19#include <asm/leon_amba.h> 20#include <asm/leon_amba.h>
21#include <asm/traps.h>
22#include <asm/cacheflush.h>
20 23
21#include "prom.h" 24#include "prom.h"
22#include "irq.h" 25#include "irq.h"
@@ -115,6 +118,21 @@ void __init leon_init_timers(irq_handler_t counter_fn)
115 (((1000000 / 100) - 1))); 118 (((1000000 / 100) - 1)));
116 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); 119 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
117 120
121#ifdef CONFIG_SMP
122 leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
123 leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1;
124
125 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
126 (1<<LEON3_GPTIMER_SEPIRQ))) {
127 prom_printf("irq timer not configured with seperate irqs \n");
128 BUG();
129 }
130
131 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
132 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1)));
133 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
134# endif
135
118 } else { 136 } else {
119 printk(KERN_ERR "No Timer/irqctrl found\n"); 137 printk(KERN_ERR "No Timer/irqctrl found\n");
120 BUG(); 138 BUG();
@@ -130,11 +148,41 @@ void __init leon_init_timers(irq_handler_t counter_fn)
130 prom_halt(); 148 prom_halt();
131 } 149 }
132 150
151# ifdef CONFIG_SMP
152 {
153 unsigned long flags;
154 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)];
155
156 /* For SMP we use the level 14 ticker, however the bootup code
157 * has copied the firmwares level 14 vector into boot cpu's
158 * trap table, we must fix this now or we get squashed.
159 */
160 local_irq_save(flags);
161
162 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
163
164 /* Adjust so that we jump directly to smpleon_ticker */
165 trap_table->inst_three += smpleon_ticker - real_irq_entry;
166
167 local_flush_cache_all();
168 local_irq_restore(flags);
169 }
170# endif
171
133 if (leon3_gptimer_regs) { 172 if (leon3_gptimer_regs) {
134 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 173 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
135 LEON3_GPTIMER_EN | 174 LEON3_GPTIMER_EN |
136 LEON3_GPTIMER_RL | 175 LEON3_GPTIMER_RL |
137 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); 176 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
177
178#ifdef CONFIG_SMP
179 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl,
180 LEON3_GPTIMER_EN |
181 LEON3_GPTIMER_RL |
182 LEON3_GPTIMER_LD |
183 LEON3_GPTIMER_IRQEN);
184#endif
185
138 } 186 }
139} 187}
140 188
@@ -175,6 +223,42 @@ void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
175 } 223 }
176} 224}
177 225
226#ifdef CONFIG_SMP
227
228void leon_set_cpu_int(int cpu, int level)
229{
230 unsigned long mask;
231 mask = get_irqmask(level);
232 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
233}
234
235static void leon_clear_ipi(int cpu, int level)
236{
237 unsigned long mask;
238 mask = get_irqmask(level);
239 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16);
240}
241
242static void leon_set_udt(int cpu)
243{
244}
245
246void leon_clear_profile_irq(int cpu)
247{
248}
249
250void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
251{
252 unsigned long mask, flags, *addr;
253 mask = get_irqmask(irq_nr);
254 local_irq_save(flags);
255 addr = (unsigned long *)&(leon3_irqctrl_regs->mask[cpu]);
256 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | (mask)));
257 local_irq_restore(flags);
258}
259
260#endif
261
178void __init leon_init_IRQ(void) 262void __init leon_init_IRQ(void)
179{ 263{
180 sparc_init_timers = leon_init_timers; 264 sparc_init_timers = leon_init_timers;
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
new file mode 100644
index 000000000000..05c0dadd6371
--- /dev/null
+++ b/arch/sparc/kernel/leon_smp.c
@@ -0,0 +1,468 @@
1/* leon_smp.c: Sparc-Leon SMP support.
2 *
3 * based on sun4m_smp.c
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
6 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
7 */
8
9#include <asm/head.h>
10
11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/threads.h>
14#include <linux/smp.h>
15#include <linux/smp_lock.h>
16#include <linux/interrupt.h>
17#include <linux/kernel_stat.h>
18#include <linux/init.h>
19#include <linux/spinlock.h>
20#include <linux/mm.h>
21#include <linux/swap.h>
22#include <linux/profile.h>
23#include <linux/pm.h>
24#include <linux/delay.h>
25
26#include <asm/cacheflush.h>
27#include <asm/tlbflush.h>
28
29#include <asm/ptrace.h>
30#include <asm/atomic.h>
31#include <asm/irq_regs.h>
32
33#include <asm/delay.h>
34#include <asm/irq.h>
35#include <asm/page.h>
36#include <asm/pgalloc.h>
37#include <asm/pgtable.h>
38#include <asm/oplib.h>
39#include <asm/cpudata.h>
40#include <asm/asi.h>
41#include <asm/leon.h>
42#include <asm/leon_amba.h>
43
44#ifdef CONFIG_SPARC_LEON
45
46#include "irq.h"
47
48extern ctxd_t *srmmu_ctx_table_phys;
49static int smp_processors_ready;
50extern volatile unsigned long cpu_callin_map[NR_CPUS];
51extern unsigned char boot_cpu_id;
52extern cpumask_t smp_commenced_mask;
53void __init leon_configure_cache_smp(void);
54
55static inline unsigned long do_swap(volatile unsigned long *ptr,
56 unsigned long val)
57{
58 __asm__ __volatile__("swapa [%1] %2, %0\n\t" : "=&r"(val)
59 : "r"(ptr), "i"(ASI_LEON_DCACHE_MISS)
60 : "memory");
61 return val;
62}
63
64static void smp_setup_percpu_timer(void);
65
66void __cpuinit leon_callin(void)
67{
68 int cpuid = hard_smpleon_processor_id();
69
70 local_flush_cache_all();
71 local_flush_tlb_all();
72 leon_configure_cache_smp();
73
74 /* Get our local ticker going. */
75 smp_setup_percpu_timer();
76
77 calibrate_delay();
78 smp_store_cpu_info(cpuid);
79
80 local_flush_cache_all();
81 local_flush_tlb_all();
82
83 /*
84 * Unblock the master CPU _only_ when the scheduler state
85 * of all secondary CPUs will be up-to-date, so after
86 * the SMP initialization the master will be just allowed
87 * to call the scheduler code.
88 * Allow master to continue.
89 */
90 do_swap(&cpu_callin_map[cpuid], 1);
91
92 local_flush_cache_all();
93 local_flush_tlb_all();
94
95 cpu_probe();
96
97 /* Fix idle thread fields. */
98 __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid])
99 : "memory" /* paranoid */);
100
101 /* Attach to the address space of init_task. */
102 atomic_inc(&init_mm.mm_count);
103 current->active_mm = &init_mm;
104
105 while (!cpu_isset(cpuid, smp_commenced_mask))
106 mb();
107
108 local_irq_enable();
109 cpu_set(cpuid, cpu_online_map);
110}
111
112/*
113 * Cycle through the processors asking the PROM to start each one.
114 */
115
116extern struct linux_prom_registers smp_penguin_ctable;
117
118void __init leon_configure_cache_smp(void)
119{
120 unsigned long cfg = sparc_leon3_get_dcachecfg();
121 int me = smp_processor_id();
122
123 if (ASI_LEON3_SYSCTRL_CFG_SSIZE(cfg) > 4) {
124 printk(KERN_INFO "Note: SMP with snooping only works on 4k cache, found %dk(0x%x) on cpu %d, disabling caches\n",
125 (unsigned int)ASI_LEON3_SYSCTRL_CFG_SSIZE(cfg),
126 (unsigned int)cfg, (unsigned int)me);
127 sparc_leon3_disable_cache();
128 } else {
129 if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) {
130 sparc_leon3_enable_snooping();
131 } else {
132 printk(KERN_INFO "Note: You have to enable snooping in the vhdl model cpu %d, disabling caches\n",
133 me);
134 sparc_leon3_disable_cache();
135 }
136 }
137
138 local_flush_cache_all();
139 local_flush_tlb_all();
140}
141
142void leon_smp_setbroadcast(unsigned int mask)
143{
144 int broadcast =
145 ((LEON3_BYPASS_LOAD_PA(&(leon3_irqctrl_regs->mpstatus)) >>
146 LEON3_IRQMPSTATUS_BROADCAST) & 1);
147 if (!broadcast) {
148 prom_printf("######## !!!! The irqmp-ctrl must have broadcast enabled, smp wont work !!!!! ####### nr cpus: %d\n",
149 leon_smp_nrcpus());
150 if (leon_smp_nrcpus() > 1) {
151 BUG();
152 } else {
153 prom_printf("continue anyway\n");
154 return;
155 }
156 }
157 LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpbroadcast), mask);
158}
159
160unsigned int leon_smp_getbroadcast(void)
161{
162 unsigned int mask;
163 mask = LEON_BYPASS_LOAD_PA(&(leon3_irqctrl_regs->mpbroadcast));
164 return mask;
165}
166
167int leon_smp_nrcpus(void)
168{
169 int nrcpu =
170 ((LEON3_BYPASS_LOAD_PA(&(leon3_irqctrl_regs->mpstatus)) >>
171 LEON3_IRQMPSTATUS_CPUNR) & 0xf) + 1;
172 return nrcpu;
173}
174
175void __init leon_boot_cpus(void)
176{
177 int nrcpu = leon_smp_nrcpus();
178 int me = smp_processor_id();
179
180 printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x \n", (unsigned int)me,
181 (unsigned int)nrcpu, (unsigned int)NR_CPUS,
182 (unsigned int)&(leon3_irqctrl_regs->mpstatus));
183
184 leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me);
185 leon_enable_irq_cpu(LEON3_IRQ_TICKER, me);
186 leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, me);
187
188 leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
189
190 leon_configure_cache_smp();
191 smp_setup_percpu_timer();
192 local_flush_cache_all();
193
194}
195
196int __cpuinit leon_boot_one_cpu(int i)
197{
198
199 struct task_struct *p;
200 int timeout;
201
202 /* Cook up an idler for this guy. */
203 p = fork_idle(i);
204
205 current_set[i] = task_thread_info(p);
206
207 /* See trampoline.S:leon_smp_cpu_startup for details...
208 * Initialize the contexts table
209 * Since the call to prom_startcpu() trashes the structure,
210 * we need to re-initialize it for each cpu
211 */
212 smp_penguin_ctable.which_io = 0;
213 smp_penguin_ctable.phys_addr = (unsigned int)srmmu_ctx_table_phys;
214 smp_penguin_ctable.reg_size = 0;
215
216 /* whirrr, whirrr, whirrrrrrrrr... */
217 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
218 (unsigned int)&leon3_irqctrl_regs->mpstatus);
219 local_flush_cache_all();
220
221 LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpstatus), 1 << i);
222
223 /* wheee... it's going... */
224 for (timeout = 0; timeout < 10000; timeout++) {
225 if (cpu_callin_map[i])
226 break;
227 udelay(200);
228 }
229 printk(KERN_INFO "Started CPU %d \n", (unsigned int)i);
230
231 if (!(cpu_callin_map[i])) {
232 printk(KERN_ERR "Processor %d is stuck.\n", i);
233 return -ENODEV;
234 } else {
235 leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i);
236 leon_enable_irq_cpu(LEON3_IRQ_TICKER, i);
237 leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, i);
238 }
239
240 local_flush_cache_all();
241 return 0;
242}
243
244void __init leon_smp_done(void)
245{
246
247 int i, first;
248 int *prev;
249
250 /* setup cpu list for irq rotation */
251 first = 0;
252 prev = &first;
253 for (i = 0; i < NR_CPUS; i++) {
254 if (cpu_online(i)) {
255 *prev = i;
256 prev = &cpu_data(i).next;
257 }
258 }
259 *prev = first;
260 local_flush_cache_all();
261
262 /* Free unneeded trap tables */
263 if (!cpu_isset(1, cpu_present_map)) {
264 ClearPageReserved(virt_to_page(trapbase_cpu1));
265 init_page_count(virt_to_page(trapbase_cpu1));
266 free_page((unsigned long)trapbase_cpu1);
267 totalram_pages++;
268 num_physpages++;
269 }
270 if (!cpu_isset(2, cpu_present_map)) {
271 ClearPageReserved(virt_to_page(trapbase_cpu2));
272 init_page_count(virt_to_page(trapbase_cpu2));
273 free_page((unsigned long)trapbase_cpu2);
274 totalram_pages++;
275 num_physpages++;
276 }
277 if (!cpu_isset(3, cpu_present_map)) {
278 ClearPageReserved(virt_to_page(trapbase_cpu3));
279 init_page_count(virt_to_page(trapbase_cpu3));
280 free_page((unsigned long)trapbase_cpu3);
281 totalram_pages++;
282 num_physpages++;
283 }
284 /* Ok, they are spinning and ready to go. */
285 smp_processors_ready = 1;
286
287}
288
289void leon_irq_rotate(int cpu)
290{
291}
292
293static struct smp_funcall {
294 smpfunc_t func;
295 unsigned long arg1;
296 unsigned long arg2;
297 unsigned long arg3;
298 unsigned long arg4;
299 unsigned long arg5;
300 unsigned long processors_in[NR_CPUS]; /* Set when ipi entered. */
301 unsigned long processors_out[NR_CPUS]; /* Set when ipi exited. */
302} ccall_info;
303
304static DEFINE_SPINLOCK(cross_call_lock);
305
306/* Cross calls must be serialized, at least currently. */
307static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
308 unsigned long arg2, unsigned long arg3,
309 unsigned long arg4)
310{
311 if (smp_processors_ready) {
312 register int high = NR_CPUS - 1;
313 unsigned long flags;
314
315 spin_lock_irqsave(&cross_call_lock, flags);
316
317 {
318 /* If you make changes here, make sure gcc generates proper code... */
319 register smpfunc_t f asm("i0") = func;
320 register unsigned long a1 asm("i1") = arg1;
321 register unsigned long a2 asm("i2") = arg2;
322 register unsigned long a3 asm("i3") = arg3;
323 register unsigned long a4 asm("i4") = arg4;
324 register unsigned long a5 asm("i5") = 0;
325
326 __asm__ __volatile__("std %0, [%6]\n\t"
327 "std %2, [%6 + 8]\n\t"
328 "std %4, [%6 + 16]\n\t" : :
329 "r"(f), "r"(a1), "r"(a2), "r"(a3),
330 "r"(a4), "r"(a5),
331 "r"(&ccall_info.func));
332 }
333
334 /* Init receive/complete mapping, plus fire the IPI's off. */
335 {
336 register int i;
337
338 cpu_clear(smp_processor_id(), mask);
339 cpus_and(mask, cpu_online_map, mask);
340 for (i = 0; i <= high; i++) {
341 if (cpu_isset(i, mask)) {
342 ccall_info.processors_in[i] = 0;
343 ccall_info.processors_out[i] = 0;
344 set_cpu_int(i, LEON3_IRQ_CROSS_CALL);
345
346 }
347 }
348 }
349
350 {
351 register int i;
352
353 i = 0;
354 do {
355 if (!cpu_isset(i, mask))
356 continue;
357
358 while (!ccall_info.processors_in[i])
359 barrier();
360 } while (++i <= high);
361
362 i = 0;
363 do {
364 if (!cpu_isset(i, mask))
365 continue;
366
367 while (!ccall_info.processors_out[i])
368 barrier();
369 } while (++i <= high);
370 }
371
372 spin_unlock_irqrestore(&cross_call_lock, flags);
373 }
374}
375
376/* Running cross calls. */
377void leon_cross_call_irq(void)
378{
379 int i = smp_processor_id();
380
381 ccall_info.processors_in[i] = 1;
382 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
383 ccall_info.arg4, ccall_info.arg5);
384 ccall_info.processors_out[i] = 1;
385}
386
387void leon_percpu_timer_interrupt(struct pt_regs *regs)
388{
389 struct pt_regs *old_regs;
390 int cpu = smp_processor_id();
391
392 old_regs = set_irq_regs(regs);
393
394 leon_clear_profile_irq(cpu);
395
396 profile_tick(CPU_PROFILING);
397
398 if (!--prof_counter(cpu)) {
399 int user = user_mode(regs);
400
401 irq_enter();
402 update_process_times(user);
403 irq_exit();
404
405 prof_counter(cpu) = prof_multiplier(cpu);
406 }
407 set_irq_regs(old_regs);
408}
409
410static void __init smp_setup_percpu_timer(void)
411{
412 int cpu = smp_processor_id();
413
414 prof_counter(cpu) = prof_multiplier(cpu) = 1;
415}
416
417void __init leon_blackbox_id(unsigned *addr)
418{
419 int rd = *addr & 0x3e000000;
420 int rs1 = rd >> 11;
421
422 /* patch places where ___b_hard_smp_processor_id appears */
423 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
424 addr[1] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
425 addr[2] = 0x01000000; /* nop */
426}
427
428void __init leon_blackbox_current(unsigned *addr)
429{
430 int rd = *addr & 0x3e000000;
431 int rs1 = rd >> 11;
432
433 /* patch LOAD_CURRENT macro where ___b_load_current appears */
434 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
435 addr[2] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
436 addr[4] = 0x81282002 | rd | rs1; /* sll reg, 0x2, reg */
437
438}
439
440/*
441 * CPU idle callback function
442 * See .../arch/sparc/kernel/process.c
443 */
444void pmc_leon_idle(void)
445{
446 __asm__ volatile ("mov %g0, %asr19");
447}
448
449void __init leon_init_smp(void)
450{
451 /* Patch ipi15 trap table */
452 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
453
454 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id);
455 BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current);
456 BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
457 BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
458 BTFIXUPCALL_NORM);
459
460#ifndef PMC_NO_IDLE
461 /* Assign power management IDLE handler */
462 pm_idle = pmc_leon_idle;
463 printk(KERN_INFO "leon: power management initialized\n");
464#endif
465
466}
467
468#endif /* CONFIG_SPARC_LEON */
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c
index f1be37a7b123..e1b0541feb19 100644
--- a/arch/sparc/kernel/pci_msi.c
+++ b/arch/sparc/kernel/pci_msi.c
@@ -112,7 +112,7 @@ static void free_msi(struct pci_pbm_info *pbm, int msi_num)
112} 112}
113 113
114static struct irq_chip msi_irq = { 114static struct irq_chip msi_irq = {
115 .typename = "PCI-MSI", 115 .name = "PCI-MSI",
116 .mask = mask_msi_irq, 116 .mask = mask_msi_irq,
117 .unmask = unmask_msi_irq, 117 .unmask = unmask_msi_irq,
118 .enable = unmask_msi_irq, 118 .enable = unmask_msi_irq,
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 21180339cb09..a2a79e76344f 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -46,6 +46,7 @@
46#include <asm/setup.h> 46#include <asm/setup.h>
47#include <asm/mmu.h> 47#include <asm/mmu.h>
48#include <asm/ns87303.h> 48#include <asm/ns87303.h>
49#include <asm/btext.h>
49 50
50#ifdef CONFIG_IP_PNP 51#ifdef CONFIG_IP_PNP
51#include <net/ipconfig.h> 52#include <net/ipconfig.h>
@@ -286,7 +287,10 @@ void __init setup_arch(char **cmdline_p)
286 parse_early_param(); 287 parse_early_param();
287 288
288 boot_flags_init(*cmdline_p); 289 boot_flags_init(*cmdline_p);
289 register_console(&prom_early_console); 290#ifdef CONFIG_EARLYFB
291 if (btext_find_display())
292#endif
293 register_console(&prom_early_console);
290 294
291 if (tlb_type == hypervisor) 295 if (tlb_type == hypervisor)
292 printk("ARCH: SUN4V\n"); 296 printk("ARCH: SUN4V\n");
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 132d81fb2616..91c10fb70858 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -32,6 +32,7 @@
32#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
33#include <asm/tlbflush.h> 33#include <asm/tlbflush.h>
34#include <asm/cpudata.h> 34#include <asm/cpudata.h>
35#include <asm/leon.h>
35 36
36#include "irq.h" 37#include "irq.h"
37 38
@@ -96,6 +97,9 @@ void __init smp_cpus_done(unsigned int max_cpus)
96 case sun4d: 97 case sun4d:
97 smp4d_smp_done(); 98 smp4d_smp_done();
98 break; 99 break;
100 case sparc_leon:
101 leon_smp_done();
102 break;
99 case sun4e: 103 case sun4e:
100 printk("SUN4E\n"); 104 printk("SUN4E\n");
101 BUG(); 105 BUG();
@@ -306,6 +310,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
306 case sun4d: 310 case sun4d:
307 smp4d_boot_cpus(); 311 smp4d_boot_cpus();
308 break; 312 break;
313 case sparc_leon:
314 leon_boot_cpus();
315 break;
309 case sun4e: 316 case sun4e:
310 printk("SUN4E\n"); 317 printk("SUN4E\n");
311 BUG(); 318 BUG();
@@ -376,6 +383,9 @@ int __cpuinit __cpu_up(unsigned int cpu)
376 case sun4d: 383 case sun4d:
377 ret = smp4d_boot_one_cpu(cpu); 384 ret = smp4d_boot_one_cpu(cpu);
378 break; 385 break;
386 case sparc_leon:
387 ret = leon_boot_one_cpu(cpu);
388 break;
379 case sun4e: 389 case sun4e:
380 printk("SUN4E\n"); 390 printk("SUN4E\n");
381 BUG(); 391 BUG();
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index 04e28b2671c8..00abe87e5b51 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -26,11 +26,6 @@
26#include <linux/nfs_fs.h> 26#include <linux/nfs_fs.h>
27#include <linux/quota.h> 27#include <linux/quota.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/sunrpc/svc.h>
30#include <linux/nfsd/nfsd.h>
31#include <linux/nfsd/cache.h>
32#include <linux/nfsd/xdr.h>
33#include <linux/nfsd/syscall.h>
34#include <linux/poll.h> 29#include <linux/poll.h>
35#include <linux/personality.h> 30#include <linux/personality.h>
36#include <linux/stat.h> 31#include <linux/stat.h>
@@ -591,63 +586,6 @@ out:
591 return ret; 586 return ret;
592} 587}
593 588
594struct __sysctl_args32 {
595 u32 name;
596 int nlen;
597 u32 oldval;
598 u32 oldlenp;
599 u32 newval;
600 u32 newlen;
601 u32 __unused[4];
602};
603
604asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
605{
606#ifndef CONFIG_SYSCTL_SYSCALL
607 return -ENOSYS;
608#else
609 struct __sysctl_args32 tmp;
610 int error;
611 size_t oldlen, __user *oldlenp = NULL;
612 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
613
614 if (copy_from_user(&tmp, args, sizeof(tmp)))
615 return -EFAULT;
616
617 if (tmp.oldval && tmp.oldlenp) {
618 /* Duh, this is ugly and might not work if sysctl_args
619 is in read-only memory, but do_sysctl does indirectly
620 a lot of uaccess in both directions and we'd have to
621 basically copy the whole sysctl.c here, and
622 glibc's __sysctl uses rw memory for the structure
623 anyway. */
624 if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
625 put_user(oldlen, (size_t __user *)addr))
626 return -EFAULT;
627 oldlenp = (size_t __user *)addr;
628 }
629
630 lock_kernel();
631 error = do_sysctl((int __user *)(unsigned long) tmp.name,
632 tmp.nlen,
633 (void __user *)(unsigned long) tmp.oldval,
634 oldlenp,
635 (void __user *)(unsigned long) tmp.newval,
636 tmp.newlen);
637 unlock_kernel();
638 if (oldlenp) {
639 if (!error) {
640 if (get_user(oldlen, (size_t __user *)addr) ||
641 put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
642 error = -EFAULT;
643 }
644 if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
645 error = -EFAULT;
646 }
647 return error;
648#endif
649}
650
651long sys32_lookup_dcookie(unsigned long cookie_high, 589long sys32_lookup_dcookie(unsigned long cookie_high,
652 unsigned long cookie_low, 590 unsigned long cookie_low,
653 char __user *buf, size_t len) 591 char __user *buf, size_t len)
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index f37bef747e60..cc8e7862e95a 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -68,7 +68,7 @@ sys_call_table32:
68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall 68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler 69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep 70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
71/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl 71/*250*/ .word sys32_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep 72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun 73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy 74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 614ac7b4a9dd..5b2f595fe65b 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -210,9 +210,6 @@ static void __init sbus_time_init(void)
210 btfixup(); 210 btfixup();
211 211
212 sparc_init_timers(timer_interrupt); 212 sparc_init_timers(timer_interrupt);
213
214 /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */
215 local_irq_enable();
216} 213}
217 214
218void __init time_init(void) 215void __init time_init(void)
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S
index 5e235c52d667..691f484e03b3 100644
--- a/arch/sparc/kernel/trampoline_32.S
+++ b/arch/sparc/kernel/trampoline_32.S
@@ -15,7 +15,7 @@
15#include <asm/contregs.h> 15#include <asm/contregs.h>
16#include <asm/thread_info.h> 16#include <asm/thread_info.h>
17 17
18 .globl sun4m_cpu_startup, __smp4m_processor_id 18 .globl sun4m_cpu_startup, __smp4m_processor_id, __leon_processor_id
19 .globl sun4d_cpu_startup, __smp4d_processor_id 19 .globl sun4d_cpu_startup, __smp4d_processor_id
20 20
21 __CPUINIT 21 __CPUINIT
@@ -106,6 +106,12 @@ __smp4d_processor_id:
106 retl 106 retl
107 mov %g1, %o7 107 mov %g1, %o7
108 108
109__leon_processor_id:
110 rd %asr17,%g2
111 srl %g2,28,%g2
112 retl
113 mov %g1, %o7
114
109/* CPUID in bootbus can be found at PA 0xff0140000 */ 115/* CPUID in bootbus can be found at PA 0xff0140000 */
110#define SUN4D_BOOTBUS_CPUID 0xf0140000 116#define SUN4D_BOOTBUS_CPUID 0xf0140000
111 117
@@ -160,3 +166,64 @@ sun4d_cpu_startup:
160 nop 166 nop
161 167
162 b,a smp_do_cpu_idle 168 b,a smp_do_cpu_idle
169
170#ifdef CONFIG_SPARC_LEON
171
172 __CPUINIT
173 .align 4
174 .global leon_smp_cpu_startup, smp_penguin_ctable
175
176leon_smp_cpu_startup:
177
178 set smp_penguin_ctable,%g1
179 ld [%g1+4],%g1
180 srl %g1,4,%g1
181 set 0x00000100,%g5 /* SRMMU_CTXTBL_PTR */
182 sta %g1, [%g5] ASI_M_MMUREGS
183
184 /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */
185 set (PSR_PIL | PSR_S | PSR_PS), %g1
186 wr %g1, 0x0, %psr ! traps off though
187 WRITE_PAUSE
188
189 /* Our %wim is one behind CWP */
190 mov 2, %g1
191 wr %g1, 0x0, %wim
192 WRITE_PAUSE
193
194 /* Set tbr - we use just one trap table. */
195 set trapbase, %g1
196 wr %g1, 0x0, %tbr
197 WRITE_PAUSE
198
199 /* Get our CPU id */
200 rd %asr17,%g3
201
202 /* Give ourselves a stack and curptr. */
203 set current_set, %g5
204 srl %g3, 28, %g4
205 sll %g4, 2, %g4
206 ld [%g5 + %g4], %g6
207
208 sethi %hi(THREAD_SIZE - STACKFRAME_SZ), %sp
209 or %sp, %lo(THREAD_SIZE - STACKFRAME_SZ), %sp
210 add %g6, %sp, %sp
211
212 /* Turn on traps (PSR_ET). */
213 rd %psr, %g1
214 wr %g1, PSR_ET, %psr ! traps on
215 WRITE_PAUSE
216
217 /* Init our caches, etc. */
218 set poke_srmmu, %g5
219 ld [%g5], %g5
220 call %g5
221 nop
222
223 /* Start this processor. */
224 call leon_callin
225 nop
226
227 b,a smp_do_cpu_idle
228
229#endif
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 509b1ffeba66..367321a030dd 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1990,7 +1990,7 @@ void __init poke_leonsparc(void)
1990void __init init_leon(void) 1990void __init init_leon(void)
1991{ 1991{
1992 1992
1993 srmmu_name = "Leon"; 1993 srmmu_name = "LEON";
1994 1994
1995 BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all, 1995 BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all,
1996 BTFIXUPCALL_NORM); 1996 BTFIXUPCALL_NORM);
@@ -2037,8 +2037,6 @@ static void __init get_srmmu_type(void)
2037 2037
2038 /* First, check for sparc-leon. */ 2038 /* First, check for sparc-leon. */
2039 if (sparc_cpu_model == sparc_leon) { 2039 if (sparc_cpu_model == sparc_leon) {
2040 psr_typ = 0xf; /* hardcoded ids for older models/simulators */
2041 psr_vers = 2;
2042 init_leon(); 2040 init_leon();
2043 return; 2041 return;
2044 } 2042 }
@@ -2301,7 +2299,8 @@ void __init ld_mmu_srmmu(void)
2301 BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM); 2299 BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM);
2302 BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM); 2300 BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM);
2303 BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM); 2301 BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM);
2304 if (sparc_cpu_model != sun4d) { 2302 if (sparc_cpu_model != sun4d &&
2303 sparc_cpu_model != sparc_leon) {
2305 BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM); 2304 BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM);
2306 BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM); 2305 BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM);
2307 BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM); 2306 BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM);
@@ -2330,6 +2329,8 @@ void __init ld_mmu_srmmu(void)
2330#ifdef CONFIG_SMP 2329#ifdef CONFIG_SMP
2331 if (sparc_cpu_model == sun4d) 2330 if (sparc_cpu_model == sun4d)
2332 sun4d_init_smp(); 2331 sun4d_init_smp();
2332 else if (sparc_cpu_model == sparc_leon)
2333 leon_init_smp();
2333 else 2334 else
2334 sun4m_init_smp(); 2335 sun4m_init_smp();
2335#endif 2336#endif
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 72ace9515a07..178084b4377c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -49,6 +49,7 @@ config X86
49 select HAVE_KERNEL_GZIP 49 select HAVE_KERNEL_GZIP
50 select HAVE_KERNEL_BZIP2 50 select HAVE_KERNEL_BZIP2
51 select HAVE_KERNEL_LZMA 51 select HAVE_KERNEL_LZMA
52 select HAVE_HW_BREAKPOINT
52 select HAVE_ARCH_KMEMCHECK 53 select HAVE_ARCH_KMEMCHECK
53 54
54config OUTPUT_FORMAT 55config OUTPUT_FORMAT
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 2649840d888f..5e99762eb5c2 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -406,7 +406,7 @@ config X86_CMPXCHG64
406# generates cmov. 406# generates cmov.
407config X86_CMOV 407config X86_CMOV
408 def_bool y 408 def_bool y
409 depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM) 409 depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX)
410 410
411config X86_MINIMUM_CPU_FAMILY 411config X86_MINIMUM_CPU_FAMILY
412 int 412 int
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index d105f29bb6bb..731318e5ac1d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -186,6 +186,15 @@ config X86_DS_SELFTEST
186config HAVE_MMIOTRACE_SUPPORT 186config HAVE_MMIOTRACE_SUPPORT
187 def_bool y 187 def_bool y
188 188
189config X86_DECODER_SELFTEST
190 bool "x86 instruction decoder selftest"
191 depends on DEBUG_KERNEL
192 ---help---
193 Perform x86 instruction decoder selftests at build time.
194 This option is useful for checking the sanity of x86 instruction
195 decoder code.
196 If unsure, say "N".
197
189# 198#
190# IO delay types: 199# IO delay types:
191# 200#
@@ -287,4 +296,18 @@ config OPTIMIZE_INLINING
287 296
288 If unsure, say N. 297 If unsure, say N.
289 298
299config DEBUG_STRICT_USER_COPY_CHECKS
300 bool "Strict copy size checks"
301 depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
302 ---help---
303 Enabling this option turns a certain set of sanity checks for user
304 copy operations into compile time failures.
305
306 The copy_from_user() etc checks are there to help test if there
307 are sufficient security checks on the length argument of
308 the copy operation, by having gcc prove that the argument is
309 within bounds.
310
311 If unsure, or if you run an older (pre 4.4) gcc, say N.
312
290endmenu 313endmenu
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index d2d24c9ee64d..78b32be55e9e 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -155,6 +155,9 @@ all: bzImage
155KBUILD_IMAGE := $(boot)/bzImage 155KBUILD_IMAGE := $(boot)/bzImage
156 156
157bzImage: vmlinux 157bzImage: vmlinux
158ifeq ($(CONFIG_X86_DECODER_SELFTEST),y)
159 $(Q)$(MAKE) $(build)=arch/x86/tools posttest
160endif
158 $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE) 161 $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
159 $(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot 162 $(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
160 $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@ 163 $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@
diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu
index 30e9a264f69d..cbf0776dbec1 100644
--- a/arch/x86/Makefile_32.cpu
+++ b/arch/x86/Makefile_32.cpu
@@ -41,7 +41,7 @@ cflags-$(CONFIG_X86_ELAN) += -march=i486
41 41
42# Geode GX1 support 42# Geode GX1 support
43cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx 43cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx
44 44cflags-$(CONFIG_MGEODE_LX) += $(call cc-option,-march=geode,-march=pentium-mmx)
45# add at the end to overwrite eventual tuning options from earlier 45# add at the end to overwrite eventual tuning options from earlier
46# cpu entries 46# cpu entries
47cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686)) 47cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686))
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index d23b98782653..4eefdca9832b 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -653,7 +653,7 @@ ia32_sys_call_table:
653 .quad compat_sys_writev 653 .quad compat_sys_writev
654 .quad sys_getsid 654 .quad sys_getsid
655 .quad sys_fdatasync 655 .quad sys_fdatasync
656 .quad sys32_sysctl /* sysctl */ 656 .quad compat_sys_sysctl /* sysctl */
657 .quad sys_mlock /* 150 */ 657 .quad sys_mlock /* 150 */
658 .quad sys_munlock 658 .quad sys_munlock
659 .quad sys_mlockall 659 .quad sys_mlockall
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 9f5527198825..df82c0e48ded 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -434,62 +434,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig,
434 return ret; 434 return ret;
435} 435}
436 436
437#ifdef CONFIG_SYSCTL_SYSCALL
438struct sysctl_ia32 {
439 unsigned int name;
440 int nlen;
441 unsigned int oldval;
442 unsigned int oldlenp;
443 unsigned int newval;
444 unsigned int newlen;
445 unsigned int __unused[4];
446};
447
448
449asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *args32)
450{
451 struct sysctl_ia32 a32;
452 mm_segment_t old_fs = get_fs();
453 void __user *oldvalp, *newvalp;
454 size_t oldlen;
455 int __user *namep;
456 long ret;
457
458 if (copy_from_user(&a32, args32, sizeof(a32)))
459 return -EFAULT;
460
461 /*
462 * We need to pre-validate these because we have to disable
463 * address checking before calling do_sysctl() because of
464 * OLDLEN but we can't run the risk of the user specifying bad
465 * addresses here. Well, since we're dealing with 32 bit
466 * addresses, we KNOW that access_ok() will always succeed, so
467 * this is an expensive NOP, but so what...
468 */
469 namep = compat_ptr(a32.name);
470 oldvalp = compat_ptr(a32.oldval);
471 newvalp = compat_ptr(a32.newval);
472
473 if ((oldvalp && get_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
474 || !access_ok(VERIFY_WRITE, namep, 0)
475 || !access_ok(VERIFY_WRITE, oldvalp, 0)
476 || !access_ok(VERIFY_WRITE, newvalp, 0))
477 return -EFAULT;
478
479 set_fs(KERNEL_DS);
480 lock_kernel();
481 ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *)&oldlen,
482 newvalp, (size_t) a32.newlen);
483 unlock_kernel();
484 set_fs(old_fs);
485
486 if (oldvalp && put_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
487 return -EFAULT;
488
489 return ret;
490}
491#endif
492
493/* warning: next two assume little endian */ 437/* warning: next two assume little endian */
494asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count, 438asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count,
495 u32 poslo, u32 poshi) 439 u32 poslo, u32 poshi)
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 4a8e80cdcfa5..9f828f87ca35 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -10,6 +10,7 @@ header-y += ptrace-abi.h
10header-y += sigcontext32.h 10header-y += sigcontext32.h
11header-y += ucontext.h 11header-y += ucontext.h
12header-y += processor-flags.h 12header-y += processor-flags.h
13header-y += hw_breakpoint.h
13 14
14unifdef-y += e820.h 15unifdef-y += e820.h
15unifdef-y += ist.h 16unifdef-y += ist.h
diff --git a/arch/x86/include/asm/a.out-core.h b/arch/x86/include/asm/a.out-core.h
index bb70e397aa84..7a15588e45d4 100644
--- a/arch/x86/include/asm/a.out-core.h
+++ b/arch/x86/include/asm/a.out-core.h
@@ -17,6 +17,7 @@
17 17
18#include <linux/user.h> 18#include <linux/user.h>
19#include <linux/elfcore.h> 19#include <linux/elfcore.h>
20#include <asm/debugreg.h>
20 21
21/* 22/*
22 * fill in the user structure for an a.out core dump 23 * fill in the user structure for an a.out core dump
@@ -32,14 +33,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
32 >> PAGE_SHIFT; 33 >> PAGE_SHIFT;
33 dump->u_dsize -= dump->u_tsize; 34 dump->u_dsize -= dump->u_tsize;
34 dump->u_ssize = 0; 35 dump->u_ssize = 0;
35 dump->u_debugreg[0] = current->thread.debugreg0; 36 aout_dump_debugregs(dump);
36 dump->u_debugreg[1] = current->thread.debugreg1;
37 dump->u_debugreg[2] = current->thread.debugreg2;
38 dump->u_debugreg[3] = current->thread.debugreg3;
39 dump->u_debugreg[4] = 0;
40 dump->u_debugreg[5] = 0;
41 dump->u_debugreg[6] = current->thread.debugreg6;
42 dump->u_debugreg[7] = current->thread.debugreg7;
43 37
44 if (dump->start_stack < TASK_SIZE) 38 if (dump->start_stack < TASK_SIZE)
45 dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack)) 39 dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index e2077d343c33..b97f786a48d5 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -1,17 +1,13 @@
1#ifdef __ASSEMBLY__ 1#ifdef __ASSEMBLY__
2 2
3#ifdef CONFIG_X86_32 3#include <asm/asm.h>
4# define X86_ALIGN .long
5#else
6# define X86_ALIGN .quad
7#endif
8 4
9#ifdef CONFIG_SMP 5#ifdef CONFIG_SMP
10 .macro LOCK_PREFIX 6 .macro LOCK_PREFIX
111: lock 71: lock
12 .section .smp_locks,"a" 8 .section .smp_locks,"a"
13 .align 4 9 _ASM_ALIGN
14 X86_ALIGN 1b 10 _ASM_PTR 1b
15 .previous 11 .previous
16 .endm 12 .endm
17#else 13#else
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index c240efc74e00..69b74a7b877f 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -84,6 +84,7 @@ static inline void alternatives_smp_switch(int smp) {}
84 " .byte " __stringify(feature) "\n" /* feature bit */ \ 84 " .byte " __stringify(feature) "\n" /* feature bit */ \
85 " .byte 662b-661b\n" /* sourcelen */ \ 85 " .byte 662b-661b\n" /* sourcelen */ \
86 " .byte 664f-663f\n" /* replacementlen */ \ 86 " .byte 664f-663f\n" /* replacementlen */ \
87 " .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */ \
87 ".previous\n" \ 88 ".previous\n" \
88 ".section .altinstr_replacement, \"ax\"\n" \ 89 ".section .altinstr_replacement, \"ax\"\n" \
89 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 90 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 474d80d3e6cc..b4ac2cdcb64f 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -297,20 +297,20 @@ struct apic {
297 int disable_esr; 297 int disable_esr;
298 298
299 int dest_logical; 299 int dest_logical;
300 unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); 300 unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
301 unsigned long (*check_apicid_present)(int apicid); 301 unsigned long (*check_apicid_present)(int apicid);
302 302
303 void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); 303 void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
304 void (*init_apic_ldr)(void); 304 void (*init_apic_ldr)(void);
305 305
306 physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); 306 void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
307 307
308 void (*setup_apic_routing)(void); 308 void (*setup_apic_routing)(void);
309 int (*multi_timer_check)(int apic, int irq); 309 int (*multi_timer_check)(int apic, int irq);
310 int (*apicid_to_node)(int logical_apicid); 310 int (*apicid_to_node)(int logical_apicid);
311 int (*cpu_to_logical_apicid)(int cpu); 311 int (*cpu_to_logical_apicid)(int cpu);
312 int (*cpu_present_to_apicid)(int mps_cpu); 312 int (*cpu_present_to_apicid)(int mps_cpu);
313 physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); 313 void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
314 void (*setup_portio_remap)(void); 314 void (*setup_portio_remap)(void);
315 int (*check_phys_apicid_present)(int phys_apicid); 315 int (*check_phys_apicid_present)(int phys_apicid);
316 void (*enable_apic_mode)(void); 316 void (*enable_apic_mode)(void);
@@ -488,6 +488,8 @@ static inline unsigned int read_apic_id(void)
488 488
489extern void default_setup_apic_routing(void); 489extern void default_setup_apic_routing(void);
490 490
491extern struct apic apic_noop;
492
491#ifdef CONFIG_X86_32 493#ifdef CONFIG_X86_32
492 494
493extern struct apic apic_default; 495extern struct apic apic_default;
@@ -532,9 +534,9 @@ default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
532 return (unsigned int)(mask1 & mask2 & mask3); 534 return (unsigned int)(mask1 & mask2 & mask3);
533} 535}
534 536
535static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid) 537static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid)
536{ 538{
537 return physid_isset(apicid, bitmap); 539 return physid_isset(apicid, *map);
538} 540}
539 541
540static inline unsigned long default_check_apicid_present(int bit) 542static inline unsigned long default_check_apicid_present(int bit)
@@ -542,9 +544,9 @@ static inline unsigned long default_check_apicid_present(int bit)
542 return physid_isset(bit, phys_cpu_present_map); 544 return physid_isset(bit, phys_cpu_present_map);
543} 545}
544 546
545static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) 547static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
546{ 548{
547 return phys_map; 549 *retmap = *phys_map;
548} 550}
549 551
550/* Mapping from cpu number to logical apicid */ 552/* Mapping from cpu number to logical apicid */
@@ -583,11 +585,6 @@ extern int default_cpu_present_to_apicid(int mps_cpu);
583extern int default_check_phys_apicid_present(int phys_apicid); 585extern int default_check_phys_apicid_present(int phys_apicid);
584#endif 586#endif
585 587
586static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid)
587{
588 return physid_mask_of_physid(phys_apicid);
589}
590
591#endif /* CONFIG_X86_LOCAL_APIC */ 588#endif /* CONFIG_X86_LOCAL_APIC */
592 589
593#ifdef CONFIG_X86_32 590#ifdef CONFIG_X86_32
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 3b62da926de9..7fe3b3060f08 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -11,6 +11,12 @@
11#define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000 11#define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000
12#define APIC_DEFAULT_PHYS_BASE 0xfee00000 12#define APIC_DEFAULT_PHYS_BASE 0xfee00000
13 13
14/*
15 * This is the IO-APIC register space as specified
16 * by Intel docs:
17 */
18#define IO_APIC_SLOT_SIZE 1024
19
14#define APIC_ID 0x20 20#define APIC_ID 0x20
15 21
16#define APIC_LVR 0x30 22#define APIC_LVR 0x30
diff --git a/arch/x86/include/asm/apicnum.h b/arch/x86/include/asm/apicnum.h
deleted file mode 100644
index 82f613c607ce..000000000000
--- a/arch/x86/include/asm/apicnum.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#ifndef _ASM_X86_APICNUM_H
2#define _ASM_X86_APICNUM_H
3
4/* define MAX_IO_APICS */
5#ifdef CONFIG_X86_32
6# define MAX_IO_APICS 64
7#else
8# define MAX_IO_APICS 128
9# define MAX_LOCAL_APIC 32768
10#endif
11
12#endif /* _ASM_X86_APICNUM_H */
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index ee1931be6593..ffb9bb6b6c37 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -8,14 +8,50 @@
8 * you need to test for the feature in boot_cpu_data. 8 * you need to test for the feature in boot_cpu_data.
9 */ 9 */
10 10
11#define xchg(ptr, v) \ 11extern void __xchg_wrong_size(void);
12 ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), sizeof(*(ptr)))) 12
13/*
14 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
15 * Note 2: xchg has side effect, so that attribute volatile is necessary,
16 * but generally the primitive is invalid, *ptr is output argument. --ANK
17 */
13 18
14struct __xchg_dummy { 19struct __xchg_dummy {
15 unsigned long a[100]; 20 unsigned long a[100];
16}; 21};
17#define __xg(x) ((struct __xchg_dummy *)(x)) 22#define __xg(x) ((struct __xchg_dummy *)(x))
18 23
24#define __xchg(x, ptr, size) \
25({ \
26 __typeof(*(ptr)) __x = (x); \
27 switch (size) { \
28 case 1: \
29 asm volatile("xchgb %b0,%1" \
30 : "=q" (__x) \
31 : "m" (*__xg(ptr)), "0" (__x) \
32 : "memory"); \
33 break; \
34 case 2: \
35 asm volatile("xchgw %w0,%1" \
36 : "=r" (__x) \
37 : "m" (*__xg(ptr)), "0" (__x) \
38 : "memory"); \
39 break; \
40 case 4: \
41 asm volatile("xchgl %0,%1" \
42 : "=r" (__x) \
43 : "m" (*__xg(ptr)), "0" (__x) \
44 : "memory"); \
45 break; \
46 default: \
47 __xchg_wrong_size(); \
48 } \
49 __x; \
50})
51
52#define xchg(ptr, v) \
53 __xchg((v), (ptr), sizeof(*ptr))
54
19/* 55/*
20 * The semantics of XCHGCMP8B are a bit strange, this is why 56 * The semantics of XCHGCMP8B are a bit strange, this is why
21 * there is a loop and the loading of %%eax and %%edx has to 57 * there is a loop and the loading of %%eax and %%edx has to
@@ -71,57 +107,63 @@ static inline void __set_64bit_var(unsigned long long *ptr,
71 (unsigned int)((value) >> 32)) \ 107 (unsigned int)((value) >> 32)) \
72 : __set_64bit(ptr, ll_low((value)), ll_high((value)))) 108 : __set_64bit(ptr, ll_low((value)), ll_high((value))))
73 109
74/* 110extern void __cmpxchg_wrong_size(void);
75 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
76 * Note 2: xchg has side effect, so that attribute volatile is necessary,
77 * but generally the primitive is invalid, *ptr is output argument. --ANK
78 */
79static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
80 int size)
81{
82 switch (size) {
83 case 1:
84 asm volatile("xchgb %b0,%1"
85 : "=q" (x)
86 : "m" (*__xg(ptr)), "0" (x)
87 : "memory");
88 break;
89 case 2:
90 asm volatile("xchgw %w0,%1"
91 : "=r" (x)
92 : "m" (*__xg(ptr)), "0" (x)
93 : "memory");
94 break;
95 case 4:
96 asm volatile("xchgl %0,%1"
97 : "=r" (x)
98 : "m" (*__xg(ptr)), "0" (x)
99 : "memory");
100 break;
101 }
102 return x;
103}
104 111
105/* 112/*
106 * Atomic compare and exchange. Compare OLD with MEM, if identical, 113 * Atomic compare and exchange. Compare OLD with MEM, if identical,
107 * store NEW in MEM. Return the initial value in MEM. Success is 114 * store NEW in MEM. Return the initial value in MEM. Success is
108 * indicated by comparing RETURN with OLD. 115 * indicated by comparing RETURN with OLD.
109 */ 116 */
117#define __raw_cmpxchg(ptr, old, new, size, lock) \
118({ \
119 __typeof__(*(ptr)) __ret; \
120 __typeof__(*(ptr)) __old = (old); \
121 __typeof__(*(ptr)) __new = (new); \
122 switch (size) { \
123 case 1: \
124 asm volatile(lock "cmpxchgb %b1,%2" \
125 : "=a"(__ret) \
126 : "q"(__new), "m"(*__xg(ptr)), "0"(__old) \
127 : "memory"); \
128 break; \
129 case 2: \
130 asm volatile(lock "cmpxchgw %w1,%2" \
131 : "=a"(__ret) \
132 : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \
133 : "memory"); \
134 break; \
135 case 4: \
136 asm volatile(lock "cmpxchgl %1,%2" \
137 : "=a"(__ret) \
138 : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \
139 : "memory"); \
140 break; \
141 default: \
142 __cmpxchg_wrong_size(); \
143 } \
144 __ret; \
145})
146
147#define __cmpxchg(ptr, old, new, size) \
148 __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
149
150#define __sync_cmpxchg(ptr, old, new, size) \
151 __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
152
153#define __cmpxchg_local(ptr, old, new, size) \
154 __raw_cmpxchg((ptr), (old), (new), (size), "")
110 155
111#ifdef CONFIG_X86_CMPXCHG 156#ifdef CONFIG_X86_CMPXCHG
112#define __HAVE_ARCH_CMPXCHG 1 157#define __HAVE_ARCH_CMPXCHG 1
113#define cmpxchg(ptr, o, n) \ 158
114 ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ 159#define cmpxchg(ptr, old, new) \
115 (unsigned long)(n), \ 160 __cmpxchg((ptr), (old), (new), sizeof(*ptr))
116 sizeof(*(ptr)))) 161
117#define sync_cmpxchg(ptr, o, n) \ 162#define sync_cmpxchg(ptr, old, new) \
118 ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o), \ 163 __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
119 (unsigned long)(n), \ 164
120 sizeof(*(ptr)))) 165#define cmpxchg_local(ptr, old, new) \
121#define cmpxchg_local(ptr, o, n) \ 166 __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
122 ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
123 (unsigned long)(n), \
124 sizeof(*(ptr))))
125#endif 167#endif
126 168
127#ifdef CONFIG_X86_CMPXCHG64 169#ifdef CONFIG_X86_CMPXCHG64
@@ -133,94 +175,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
133 (unsigned long long)(n))) 175 (unsigned long long)(n)))
134#endif 176#endif
135 177
136static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
137 unsigned long new, int size)
138{
139 unsigned long prev;
140 switch (size) {
141 case 1:
142 asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
143 : "=a"(prev)
144 : "q"(new), "m"(*__xg(ptr)), "0"(old)
145 : "memory");
146 return prev;
147 case 2:
148 asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
149 : "=a"(prev)
150 : "r"(new), "m"(*__xg(ptr)), "0"(old)
151 : "memory");
152 return prev;
153 case 4:
154 asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
155 : "=a"(prev)
156 : "r"(new), "m"(*__xg(ptr)), "0"(old)
157 : "memory");
158 return prev;
159 }
160 return old;
161}
162
163/*
164 * Always use locked operations when touching memory shared with a
165 * hypervisor, since the system may be SMP even if the guest kernel
166 * isn't.
167 */
168static inline unsigned long __sync_cmpxchg(volatile void *ptr,
169 unsigned long old,
170 unsigned long new, int size)
171{
172 unsigned long prev;
173 switch (size) {
174 case 1:
175 asm volatile("lock; cmpxchgb %b1,%2"
176 : "=a"(prev)
177 : "q"(new), "m"(*__xg(ptr)), "0"(old)
178 : "memory");
179 return prev;
180 case 2:
181 asm volatile("lock; cmpxchgw %w1,%2"
182 : "=a"(prev)
183 : "r"(new), "m"(*__xg(ptr)), "0"(old)
184 : "memory");
185 return prev;
186 case 4:
187 asm volatile("lock; cmpxchgl %1,%2"
188 : "=a"(prev)
189 : "r"(new), "m"(*__xg(ptr)), "0"(old)
190 : "memory");
191 return prev;
192 }
193 return old;
194}
195
196static inline unsigned long __cmpxchg_local(volatile void *ptr,
197 unsigned long old,
198 unsigned long new, int size)
199{
200 unsigned long prev;
201 switch (size) {
202 case 1:
203 asm volatile("cmpxchgb %b1,%2"
204 : "=a"(prev)
205 : "q"(new), "m"(*__xg(ptr)), "0"(old)
206 : "memory");
207 return prev;
208 case 2:
209 asm volatile("cmpxchgw %w1,%2"
210 : "=a"(prev)
211 : "r"(new), "m"(*__xg(ptr)), "0"(old)
212 : "memory");
213 return prev;
214 case 4:
215 asm volatile("cmpxchgl %1,%2"
216 : "=a"(prev)
217 : "r"(new), "m"(*__xg(ptr)), "0"(old)
218 : "memory");
219 return prev;
220 }
221 return old;
222}
223
224static inline unsigned long long __cmpxchg64(volatile void *ptr, 178static inline unsigned long long __cmpxchg64(volatile void *ptr,
225 unsigned long long old, 179 unsigned long long old,
226 unsigned long long new) 180 unsigned long long new)
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 52de72e0de8c..485ae415faec 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -3,9 +3,6 @@
3 3
4#include <asm/alternative.h> /* Provides LOCK_PREFIX */ 4#include <asm/alternative.h> /* Provides LOCK_PREFIX */
5 5
6#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), \
7 (ptr), sizeof(*(ptr))))
8
9#define __xg(x) ((volatile long *)(x)) 6#define __xg(x) ((volatile long *)(x))
10 7
11static inline void set_64bit(volatile unsigned long *ptr, unsigned long val) 8static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
@@ -15,167 +12,118 @@ static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
15 12
16#define _set_64bit set_64bit 13#define _set_64bit set_64bit
17 14
15extern void __xchg_wrong_size(void);
16extern void __cmpxchg_wrong_size(void);
17
18/* 18/*
19 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway 19 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
20 * Note 2: xchg has side effect, so that attribute volatile is necessary, 20 * Note 2: xchg has side effect, so that attribute volatile is necessary,
21 * but generally the primitive is invalid, *ptr is output argument. --ANK 21 * but generally the primitive is invalid, *ptr is output argument. --ANK
22 */ 22 */
23static inline unsigned long __xchg(unsigned long x, volatile void *ptr, 23#define __xchg(x, ptr, size) \
24 int size) 24({ \
25{ 25 __typeof(*(ptr)) __x = (x); \
26 switch (size) { 26 switch (size) { \
27 case 1: 27 case 1: \
28 asm volatile("xchgb %b0,%1" 28 asm volatile("xchgb %b0,%1" \
29 : "=q" (x) 29 : "=q" (__x) \
30 : "m" (*__xg(ptr)), "0" (x) 30 : "m" (*__xg(ptr)), "0" (__x) \
31 : "memory"); 31 : "memory"); \
32 break; 32 break; \
33 case 2: 33 case 2: \
34 asm volatile("xchgw %w0,%1" 34 asm volatile("xchgw %w0,%1" \
35 : "=r" (x) 35 : "=r" (__x) \
36 : "m" (*__xg(ptr)), "0" (x) 36 : "m" (*__xg(ptr)), "0" (__x) \
37 : "memory"); 37 : "memory"); \
38 break; 38 break; \
39 case 4: 39 case 4: \
40 asm volatile("xchgl %k0,%1" 40 asm volatile("xchgl %k0,%1" \
41 : "=r" (x) 41 : "=r" (__x) \
42 : "m" (*__xg(ptr)), "0" (x) 42 : "m" (*__xg(ptr)), "0" (__x) \
43 : "memory"); 43 : "memory"); \
44 break; 44 break; \
45 case 8: 45 case 8: \
46 asm volatile("xchgq %0,%1" 46 asm volatile("xchgq %0,%1" \
47 : "=r" (x) 47 : "=r" (__x) \
48 : "m" (*__xg(ptr)), "0" (x) 48 : "m" (*__xg(ptr)), "0" (__x) \
49 : "memory"); 49 : "memory"); \
50 break; 50 break; \
51 } 51 default: \
52 return x; 52 __xchg_wrong_size(); \
53} 53 } \
54 __x; \
55})
56
57#define xchg(ptr, v) \
58 __xchg((v), (ptr), sizeof(*ptr))
59
60#define __HAVE_ARCH_CMPXCHG 1
54 61
55/* 62/*
56 * Atomic compare and exchange. Compare OLD with MEM, if identical, 63 * Atomic compare and exchange. Compare OLD with MEM, if identical,
57 * store NEW in MEM. Return the initial value in MEM. Success is 64 * store NEW in MEM. Return the initial value in MEM. Success is
58 * indicated by comparing RETURN with OLD. 65 * indicated by comparing RETURN with OLD.
59 */ 66 */
67#define __raw_cmpxchg(ptr, old, new, size, lock) \
68({ \
69 __typeof__(*(ptr)) __ret; \
70 __typeof__(*(ptr)) __old = (old); \
71 __typeof__(*(ptr)) __new = (new); \
72 switch (size) { \
73 case 1: \
74 asm volatile(lock "cmpxchgb %b1,%2" \
75 : "=a"(__ret) \
76 : "q"(__new), "m"(*__xg(ptr)), "0"(__old) \
77 : "memory"); \
78 break; \
79 case 2: \
80 asm volatile(lock "cmpxchgw %w1,%2" \
81 : "=a"(__ret) \
82 : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \
83 : "memory"); \
84 break; \
85 case 4: \
86 asm volatile(lock "cmpxchgl %k1,%2" \
87 : "=a"(__ret) \
88 : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \
89 : "memory"); \
90 break; \
91 case 8: \
92 asm volatile(lock "cmpxchgq %1,%2" \
93 : "=a"(__ret) \
94 : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \
95 : "memory"); \
96 break; \
97 default: \
98 __cmpxchg_wrong_size(); \
99 } \
100 __ret; \
101})
60 102
61#define __HAVE_ARCH_CMPXCHG 1 103#define __cmpxchg(ptr, old, new, size) \
104 __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
62 105
63static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 106#define __sync_cmpxchg(ptr, old, new, size) \
64 unsigned long new, int size) 107 __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
65{
66 unsigned long prev;
67 switch (size) {
68 case 1:
69 asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
70 : "=a"(prev)
71 : "q"(new), "m"(*__xg(ptr)), "0"(old)
72 : "memory");
73 return prev;
74 case 2:
75 asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
76 : "=a"(prev)
77 : "r"(new), "m"(*__xg(ptr)), "0"(old)
78 : "memory");
79 return prev;
80 case 4:
81 asm volatile(LOCK_PREFIX "cmpxchgl %k1,%2"
82 : "=a"(prev)
83 : "r"(new), "m"(*__xg(ptr)), "0"(old)
84 : "memory");
85 return prev;
86 case 8:
87 asm volatile(LOCK_PREFIX "cmpxchgq %1,%2"
88 : "=a"(prev)
89 : "r"(new), "m"(*__xg(ptr)), "0"(old)
90 : "memory");
91 return prev;
92 }
93 return old;
94}
95 108
96/* 109#define __cmpxchg_local(ptr, old, new, size) \
97 * Always use locked operations when touching memory shared with a 110 __raw_cmpxchg((ptr), (old), (new), (size), "")
98 * hypervisor, since the system may be SMP even if the guest kernel
99 * isn't.
100 */
101static inline unsigned long __sync_cmpxchg(volatile void *ptr,
102 unsigned long old,
103 unsigned long new, int size)
104{
105 unsigned long prev;
106 switch (size) {
107 case 1:
108 asm volatile("lock; cmpxchgb %b1,%2"
109 : "=a"(prev)
110 : "q"(new), "m"(*__xg(ptr)), "0"(old)
111 : "memory");
112 return prev;
113 case 2:
114 asm volatile("lock; cmpxchgw %w1,%2"
115 : "=a"(prev)
116 : "r"(new), "m"(*__xg(ptr)), "0"(old)
117 : "memory");
118 return prev;
119 case 4:
120 asm volatile("lock; cmpxchgl %1,%2"
121 : "=a"(prev)
122 : "r"(new), "m"(*__xg(ptr)), "0"(old)
123 : "memory");
124 return prev;
125 }
126 return old;
127}
128 111
129static inline unsigned long __cmpxchg_local(volatile void *ptr, 112#define cmpxchg(ptr, old, new) \
130 unsigned long old, 113 __cmpxchg((ptr), (old), (new), sizeof(*ptr))
131 unsigned long new, int size) 114
132{ 115#define sync_cmpxchg(ptr, old, new) \
133 unsigned long prev; 116 __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
134 switch (size) { 117
135 case 1: 118#define cmpxchg_local(ptr, old, new) \
136 asm volatile("cmpxchgb %b1,%2" 119 __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
137 : "=a"(prev)
138 : "q"(new), "m"(*__xg(ptr)), "0"(old)
139 : "memory");
140 return prev;
141 case 2:
142 asm volatile("cmpxchgw %w1,%2"
143 : "=a"(prev)
144 : "r"(new), "m"(*__xg(ptr)), "0"(old)
145 : "memory");
146 return prev;
147 case 4:
148 asm volatile("cmpxchgl %k1,%2"
149 : "=a"(prev)
150 : "r"(new), "m"(*__xg(ptr)), "0"(old)
151 : "memory");
152 return prev;
153 case 8:
154 asm volatile("cmpxchgq %1,%2"
155 : "=a"(prev)
156 : "r"(new), "m"(*__xg(ptr)), "0"(old)
157 : "memory");
158 return prev;
159 }
160 return old;
161}
162 120
163#define cmpxchg(ptr, o, n) \
164 ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
165 (unsigned long)(n), sizeof(*(ptr))))
166#define cmpxchg64(ptr, o, n) \ 121#define cmpxchg64(ptr, o, n) \
167({ \ 122({ \
168 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 123 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
169 cmpxchg((ptr), (o), (n)); \ 124 cmpxchg((ptr), (o), (n)); \
170}) 125})
171#define cmpxchg_local(ptr, o, n) \ 126
172 ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
173 (unsigned long)(n), \
174 sizeof(*(ptr))))
175#define sync_cmpxchg(ptr, o, n) \
176 ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o), \
177 (unsigned long)(n), \
178 sizeof(*(ptr))))
179#define cmpxchg64_local(ptr, o, n) \ 127#define cmpxchg64_local(ptr, o, n) \
180({ \ 128({ \
181 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 129 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h
index 3ea6f37be9e2..8240f76b531e 100644
--- a/arch/x86/include/asm/debugreg.h
+++ b/arch/x86/include/asm/debugreg.h
@@ -18,6 +18,7 @@
18#define DR_TRAP1 (0x2) /* db1 */ 18#define DR_TRAP1 (0x2) /* db1 */
19#define DR_TRAP2 (0x4) /* db2 */ 19#define DR_TRAP2 (0x4) /* db2 */
20#define DR_TRAP3 (0x8) /* db3 */ 20#define DR_TRAP3 (0x8) /* db3 */
21#define DR_TRAP_BITS (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)
21 22
22#define DR_STEP (0x4000) /* single-step */ 23#define DR_STEP (0x4000) /* single-step */
23#define DR_SWITCH (0x8000) /* task switch */ 24#define DR_SWITCH (0x8000) /* task switch */
@@ -49,6 +50,8 @@
49 50
50#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ 51#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */
51#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ 52#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */
53#define DR_LOCAL_ENABLE (0x1) /* Local enable for reg 0 */
54#define DR_GLOBAL_ENABLE (0x2) /* Global enable for reg 0 */
52#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ 55#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */
53 56
54#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ 57#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */
@@ -67,4 +70,34 @@
67#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ 70#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */
68#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ 71#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */
69 72
73/*
74 * HW breakpoint additions
75 */
76#ifdef __KERNEL__
77
78DECLARE_PER_CPU(unsigned long, cpu_dr7);
79
80static inline void hw_breakpoint_disable(void)
81{
82 /* Zero the control register for HW Breakpoint */
83 set_debugreg(0UL, 7);
84
85 /* Zero-out the individual HW breakpoint address registers */
86 set_debugreg(0UL, 0);
87 set_debugreg(0UL, 1);
88 set_debugreg(0UL, 2);
89 set_debugreg(0UL, 3);
90}
91
92static inline int hw_breakpoint_active(void)
93{
94 return __get_cpu_var(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
95}
96
97extern void aout_dump_debugregs(struct user *dump);
98
99extern void hw_breakpoint_restore(void);
100
101#endif /* __KERNEL__ */
102
70#endif /* _ASM_X86_DEBUGREG_H */ 103#endif /* _ASM_X86_DEBUGREG_H */
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 82e3e8f01043..108eb6fd1ae7 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -20,11 +20,11 @@ typedef struct {
20 unsigned int irq_call_count; 20 unsigned int irq_call_count;
21 unsigned int irq_tlb_count; 21 unsigned int irq_tlb_count;
22#endif 22#endif
23#ifdef CONFIG_X86_MCE 23#ifdef CONFIG_X86_THERMAL_VECTOR
24 unsigned int irq_thermal_count; 24 unsigned int irq_thermal_count;
25# ifdef CONFIG_X86_MCE_THRESHOLD 25#endif
26#ifdef CONFIG_X86_MCE_THRESHOLD
26 unsigned int irq_threshold_count; 27 unsigned int irq_threshold_count;
27# endif
28#endif 28#endif
29} ____cacheline_aligned irq_cpustat_t; 29} ____cacheline_aligned irq_cpustat_t;
30 30
diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h
new file mode 100644
index 000000000000..0675a7c4c20e
--- /dev/null
+++ b/arch/x86/include/asm/hw_breakpoint.h
@@ -0,0 +1,73 @@
1#ifndef _I386_HW_BREAKPOINT_H
2#define _I386_HW_BREAKPOINT_H
3
4#ifdef __KERNEL__
5#define __ARCH_HW_BREAKPOINT_H
6
7/*
8 * The name should probably be something dealt in
9 * a higher level. While dealing with the user
10 * (display/resolving)
11 */
12struct arch_hw_breakpoint {
13 char *name; /* Contains name of the symbol to set bkpt */
14 unsigned long address;
15 u8 len;
16 u8 type;
17};
18
19#include <linux/kdebug.h>
20#include <linux/percpu.h>
21#include <linux/list.h>
22
23/* Available HW breakpoint length encodings */
24#define X86_BREAKPOINT_LEN_1 0x40
25#define X86_BREAKPOINT_LEN_2 0x44
26#define X86_BREAKPOINT_LEN_4 0x4c
27#define X86_BREAKPOINT_LEN_EXECUTE 0x40
28
29#ifdef CONFIG_X86_64
30#define X86_BREAKPOINT_LEN_8 0x48
31#endif
32
33/* Available HW breakpoint type encodings */
34
35/* trigger on instruction execute */
36#define X86_BREAKPOINT_EXECUTE 0x80
37/* trigger on memory write */
38#define X86_BREAKPOINT_WRITE 0x81
39/* trigger on memory read or write */
40#define X86_BREAKPOINT_RW 0x83
41
42/* Total number of available HW breakpoint registers */
43#define HBP_NUM 4
44
45struct perf_event;
46struct pmu;
47
48extern int arch_check_va_in_userspace(unsigned long va, u8 hbp_len);
49extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
50 struct task_struct *tsk);
51extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
52 unsigned long val, void *data);
53
54
55int arch_install_hw_breakpoint(struct perf_event *bp);
56void arch_uninstall_hw_breakpoint(struct perf_event *bp);
57void hw_breakpoint_pmu_read(struct perf_event *bp);
58void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
59
60extern void
61arch_fill_perf_breakpoint(struct perf_event *bp);
62
63unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type);
64int decode_dr7(unsigned long dr7, int bpnum, unsigned *len, unsigned *type);
65
66extern int arch_bp_generic_fields(int x86_len, int x86_type,
67 int *gen_len, int *gen_type);
68
69extern struct pmu perf_ops_bp;
70
71#endif /* __KERNEL__ */
72#endif /* _I386_HW_BREAKPOINT_H */
73
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index ba180d93b08c..6e124269fd4b 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -79,14 +79,32 @@ static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
79 int ioapic, int ioapic_pin, 79 int ioapic, int ioapic_pin,
80 int trigger, int polarity) 80 int trigger, int polarity)
81{ 81{
82 irq_attr->ioapic = ioapic; 82 irq_attr->ioapic = ioapic;
83 irq_attr->ioapic_pin = ioapic_pin; 83 irq_attr->ioapic_pin = ioapic_pin;
84 irq_attr->trigger = trigger; 84 irq_attr->trigger = trigger;
85 irq_attr->polarity = polarity; 85 irq_attr->polarity = polarity;
86} 86}
87 87
88extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, 88/*
89 struct io_apic_irq_attr *irq_attr); 89 * This is performance-critical, we want to do it O(1)
90 *
91 * Most irqs are mapped 1:1 with pins.
92 */
93struct irq_cfg {
94 struct irq_pin_list *irq_2_pin;
95 cpumask_var_t domain;
96 cpumask_var_t old_domain;
97 u8 vector;
98 u8 move_in_progress : 1;
99};
100
101extern struct irq_cfg *irq_cfg(unsigned int);
102extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *);
103extern void send_cleanup_vector(struct irq_cfg *);
104
105struct irq_desc;
106extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *);
107extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr);
90extern void setup_ioapic_dest(void); 108extern void setup_ioapic_dest(void);
91 109
92extern void enable_IO_APIC(void); 110extern void enable_IO_APIC(void);
diff --git a/arch/x86/include/asm/inat.h b/arch/x86/include/asm/inat.h
new file mode 100644
index 000000000000..205b063e3e32
--- /dev/null
+++ b/arch/x86/include/asm/inat.h
@@ -0,0 +1,220 @@
1#ifndef _ASM_X86_INAT_H
2#define _ASM_X86_INAT_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23#include <asm/inat_types.h>
24
25/*
26 * Internal bits. Don't use bitmasks directly, because these bits are
27 * unstable. You should use checking functions.
28 */
29
30#define INAT_OPCODE_TABLE_SIZE 256
31#define INAT_GROUP_TABLE_SIZE 8
32
33/* Legacy last prefixes */
34#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
35#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
36#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
37/* Other Legacy prefixes */
38#define INAT_PFX_LOCK 4 /* 0xF0 */
39#define INAT_PFX_CS 5 /* 0x2E */
40#define INAT_PFX_DS 6 /* 0x3E */
41#define INAT_PFX_ES 7 /* 0x26 */
42#define INAT_PFX_FS 8 /* 0x64 */
43#define INAT_PFX_GS 9 /* 0x65 */
44#define INAT_PFX_SS 10 /* 0x36 */
45#define INAT_PFX_ADDRSZ 11 /* 0x67 */
46/* x86-64 REX prefix */
47#define INAT_PFX_REX 12 /* 0x4X */
48/* AVX VEX prefixes */
49#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
50#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
51
52#define INAT_LSTPFX_MAX 3
53#define INAT_LGCPFX_MAX 11
54
55/* Immediate size */
56#define INAT_IMM_BYTE 1
57#define INAT_IMM_WORD 2
58#define INAT_IMM_DWORD 3
59#define INAT_IMM_QWORD 4
60#define INAT_IMM_PTR 5
61#define INAT_IMM_VWORD32 6
62#define INAT_IMM_VWORD 7
63
64/* Legacy prefix */
65#define INAT_PFX_OFFS 0
66#define INAT_PFX_BITS 4
67#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
68#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
69/* Escape opcodes */
70#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
71#define INAT_ESC_BITS 2
72#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
73#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
74/* Group opcodes (1-16) */
75#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
76#define INAT_GRP_BITS 5
77#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
78#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
79/* Immediates */
80#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
81#define INAT_IMM_BITS 3
82#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
83/* Flags */
84#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
85#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
86#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
87#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
88#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
89#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
90#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
91#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
92/* Attribute making macros for attribute tables */
93#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
94#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
95#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
96#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
97
98/* Attribute search APIs */
99extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
100extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
101 insn_byte_t last_pfx,
102 insn_attr_t esc_attr);
103extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
104 insn_byte_t last_pfx,
105 insn_attr_t esc_attr);
106extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
107 insn_byte_t vex_m,
108 insn_byte_t vex_pp);
109
110/* Attribute checking functions */
111static inline int inat_is_legacy_prefix(insn_attr_t attr)
112{
113 attr &= INAT_PFX_MASK;
114 return attr && attr <= INAT_LGCPFX_MAX;
115}
116
117static inline int inat_is_address_size_prefix(insn_attr_t attr)
118{
119 return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
120}
121
122static inline int inat_is_operand_size_prefix(insn_attr_t attr)
123{
124 return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
125}
126
127static inline int inat_is_rex_prefix(insn_attr_t attr)
128{
129 return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
130}
131
132static inline int inat_last_prefix_id(insn_attr_t attr)
133{
134 if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
135 return 0;
136 else
137 return attr & INAT_PFX_MASK;
138}
139
140static inline int inat_is_vex_prefix(insn_attr_t attr)
141{
142 attr &= INAT_PFX_MASK;
143 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
144}
145
146static inline int inat_is_vex3_prefix(insn_attr_t attr)
147{
148 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
149}
150
151static inline int inat_is_escape(insn_attr_t attr)
152{
153 return attr & INAT_ESC_MASK;
154}
155
156static inline int inat_escape_id(insn_attr_t attr)
157{
158 return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
159}
160
161static inline int inat_is_group(insn_attr_t attr)
162{
163 return attr & INAT_GRP_MASK;
164}
165
166static inline int inat_group_id(insn_attr_t attr)
167{
168 return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
169}
170
171static inline int inat_group_common_attribute(insn_attr_t attr)
172{
173 return attr & ~INAT_GRP_MASK;
174}
175
176static inline int inat_has_immediate(insn_attr_t attr)
177{
178 return attr & INAT_IMM_MASK;
179}
180
181static inline int inat_immediate_size(insn_attr_t attr)
182{
183 return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
184}
185
186static inline int inat_has_modrm(insn_attr_t attr)
187{
188 return attr & INAT_MODRM;
189}
190
191static inline int inat_is_force64(insn_attr_t attr)
192{
193 return attr & INAT_FORCE64;
194}
195
196static inline int inat_has_second_immediate(insn_attr_t attr)
197{
198 return attr & INAT_SCNDIMM;
199}
200
201static inline int inat_has_moffset(insn_attr_t attr)
202{
203 return attr & INAT_MOFFSET;
204}
205
206static inline int inat_has_variant(insn_attr_t attr)
207{
208 return attr & INAT_VARIANT;
209}
210
211static inline int inat_accept_vex(insn_attr_t attr)
212{
213 return attr & INAT_VEXOK;
214}
215
216static inline int inat_must_vex(insn_attr_t attr)
217{
218 return attr & INAT_VEXONLY;
219}
220#endif
diff --git a/arch/x86/include/asm/inat_types.h b/arch/x86/include/asm/inat_types.h
new file mode 100644
index 000000000000..cb3c20ce39cf
--- /dev/null
+++ b/arch/x86/include/asm/inat_types.h
@@ -0,0 +1,29 @@
1#ifndef _ASM_X86_INAT_TYPES_H
2#define _ASM_X86_INAT_TYPES_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23
24/* Instruction attributes */
25typedef unsigned int insn_attr_t;
26typedef unsigned char insn_byte_t;
27typedef signed int insn_value_t;
28
29#endif
diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h
new file mode 100644
index 000000000000..96c2e0ad04ca
--- /dev/null
+++ b/arch/x86/include/asm/insn.h
@@ -0,0 +1,184 @@
1#ifndef _ASM_X86_INSN_H
2#define _ASM_X86_INSN_H
3/*
4 * x86 instruction analysis
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Copyright (C) IBM Corporation, 2009
21 */
22
23/* insn_attr_t is defined in inat.h */
24#include <asm/inat.h>
25
26struct insn_field {
27 union {
28 insn_value_t value;
29 insn_byte_t bytes[4];
30 };
31 /* !0 if we've run insn_get_xxx() for this field */
32 unsigned char got;
33 unsigned char nbytes;
34};
35
36struct insn {
37 struct insn_field prefixes; /*
38 * Prefixes
39 * prefixes.bytes[3]: last prefix
40 */
41 struct insn_field rex_prefix; /* REX prefix */
42 struct insn_field vex_prefix; /* VEX prefix */
43 struct insn_field opcode; /*
44 * opcode.bytes[0]: opcode1
45 * opcode.bytes[1]: opcode2
46 * opcode.bytes[2]: opcode3
47 */
48 struct insn_field modrm;
49 struct insn_field sib;
50 struct insn_field displacement;
51 union {
52 struct insn_field immediate;
53 struct insn_field moffset1; /* for 64bit MOV */
54 struct insn_field immediate1; /* for 64bit imm or off16/32 */
55 };
56 union {
57 struct insn_field moffset2; /* for 64bit MOV */
58 struct insn_field immediate2; /* for 64bit imm or seg16 */
59 };
60
61 insn_attr_t attr;
62 unsigned char opnd_bytes;
63 unsigned char addr_bytes;
64 unsigned char length;
65 unsigned char x86_64;
66
67 const insn_byte_t *kaddr; /* kernel address of insn to analyze */
68 const insn_byte_t *next_byte;
69};
70
71#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
72#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
73#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
74
75#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
76#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
77#define X86_SIB_BASE(sib) ((sib) & 0x07)
78
79#define X86_REX_W(rex) ((rex) & 8)
80#define X86_REX_R(rex) ((rex) & 4)
81#define X86_REX_X(rex) ((rex) & 2)
82#define X86_REX_B(rex) ((rex) & 1)
83
84/* VEX bit flags */
85#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
86#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
87#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
88#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
89#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
90/* VEX bit fields */
91#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
92#define X86_VEX2_M 1 /* VEX2.M always 1 */
93#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
94#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
95#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
96
97/* The last prefix is needed for two-byte and three-byte opcodes */
98static inline insn_byte_t insn_last_prefix(struct insn *insn)
99{
100 return insn->prefixes.bytes[3];
101}
102
103extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
104extern void insn_get_prefixes(struct insn *insn);
105extern void insn_get_opcode(struct insn *insn);
106extern void insn_get_modrm(struct insn *insn);
107extern void insn_get_sib(struct insn *insn);
108extern void insn_get_displacement(struct insn *insn);
109extern void insn_get_immediate(struct insn *insn);
110extern void insn_get_length(struct insn *insn);
111
112/* Attribute will be determined after getting ModRM (for opcode groups) */
113static inline void insn_get_attribute(struct insn *insn)
114{
115 insn_get_modrm(insn);
116}
117
118/* Instruction uses RIP-relative addressing */
119extern int insn_rip_relative(struct insn *insn);
120
121/* Init insn for kernel text */
122static inline void kernel_insn_init(struct insn *insn, const void *kaddr)
123{
124#ifdef CONFIG_X86_64
125 insn_init(insn, kaddr, 1);
126#else /* CONFIG_X86_32 */
127 insn_init(insn, kaddr, 0);
128#endif
129}
130
131static inline int insn_is_avx(struct insn *insn)
132{
133 if (!insn->prefixes.got)
134 insn_get_prefixes(insn);
135 return (insn->vex_prefix.value != 0);
136}
137
138static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
139{
140 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
141 return X86_VEX2_M;
142 else
143 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
144}
145
146static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
147{
148 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
149 return X86_VEX_P(insn->vex_prefix.bytes[1]);
150 else
151 return X86_VEX_P(insn->vex_prefix.bytes[2]);
152}
153
154/* Offset of each field from kaddr */
155static inline int insn_offset_rex_prefix(struct insn *insn)
156{
157 return insn->prefixes.nbytes;
158}
159static inline int insn_offset_vex_prefix(struct insn *insn)
160{
161 return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
162}
163static inline int insn_offset_opcode(struct insn *insn)
164{
165 return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
166}
167static inline int insn_offset_modrm(struct insn *insn)
168{
169 return insn_offset_opcode(insn) + insn->opcode.nbytes;
170}
171static inline int insn_offset_sib(struct insn *insn)
172{
173 return insn_offset_modrm(insn) + insn->modrm.nbytes;
174}
175static inline int insn_offset_displacement(struct insn *insn)
176{
177 return insn_offset_sib(insn) + insn->sib.nbytes;
178}
179static inline int insn_offset_immediate(struct insn *insn)
180{
181 return insn_offset_displacement(insn) + insn->displacement.nbytes;
182}
183
184#endif /* _ASM_X86_INSN_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index ddda6cbed6f4..ffd700ff5dcb 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -34,6 +34,7 @@ static inline int irq_canonicalize(int irq)
34#ifdef CONFIG_HOTPLUG_CPU 34#ifdef CONFIG_HOTPLUG_CPU
35#include <linux/cpumask.h> 35#include <linux/cpumask.h>
36extern void fixup_irqs(void); 36extern void fixup_irqs(void);
37extern void irq_force_complete_move(int);
37#endif 38#endif
38 39
39extern void (*generic_interrupt_extension)(void); 40extern void (*generic_interrupt_extension)(void);
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index f1363b72364f..858baa061cfc 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -108,6 +108,8 @@ struct mce_log {
108#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) 108#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9)
109#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) 109#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0)
110 110
111extern struct atomic_notifier_head x86_mce_decoder_chain;
112
111#ifdef __KERNEL__ 113#ifdef __KERNEL__
112 114
113#include <linux/percpu.h> 115#include <linux/percpu.h>
@@ -118,9 +120,11 @@ extern int mce_disabled;
118extern int mce_p5_enabled; 120extern int mce_p5_enabled;
119 121
120#ifdef CONFIG_X86_MCE 122#ifdef CONFIG_X86_MCE
121void mcheck_init(struct cpuinfo_x86 *c); 123int mcheck_init(void);
124void mcheck_cpu_init(struct cpuinfo_x86 *c);
122#else 125#else
123static inline void mcheck_init(struct cpuinfo_x86 *c) {} 126static inline int mcheck_init(void) { return 0; }
127static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}
124#endif 128#endif
125 129
126#ifdef CONFIG_X86_ANCIENT_MCE 130#ifdef CONFIG_X86_ANCIENT_MCE
@@ -214,5 +218,11 @@ void intel_init_thermal(struct cpuinfo_x86 *c);
214 218
215void mce_log_therm_throt_event(__u64 status); 219void mce_log_therm_throt_event(__u64 status);
216 220
221#ifdef CONFIG_X86_THERMAL_VECTOR
222extern void mcheck_intel_therm_init(void);
223#else
224static inline void mcheck_intel_therm_init(void) { }
225#endif
226
217#endif /* __KERNEL__ */ 227#endif /* __KERNEL__ */
218#endif /* _ASM_X86_MCE_H */ 228#endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 79c94500c0bb..61d90b1331c3 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -163,14 +163,16 @@ typedef struct physid_mask physid_mask_t;
163#define physids_shift_left(d, s, n) \ 163#define physids_shift_left(d, s, n) \
164 bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS) 164 bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
165 165
166#define physids_coerce(map) ((map).mask[0]) 166static inline unsigned long physids_coerce(physid_mask_t *map)
167{
168 return map->mask[0];
169}
167 170
168#define physids_promote(physids) \ 171static inline void physids_promote(unsigned long physids, physid_mask_t *map)
169 ({ \ 172{
170 physid_mask_t __physid_mask = PHYSID_MASK_NONE; \ 173 physids_clear(*map);
171 __physid_mask.mask[0] = physids; \ 174 map->mask[0] = physids;
172 __physid_mask; \ 175}
173 })
174 176
175/* Note: will create very large stack frames if physid_mask_t is big */ 177/* Note: will create very large stack frames if physid_mask_t is big */
176#define physid_mask_of_physid(physid) \ 178#define physid_mask_of_physid(physid) \
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 7e2b6ba962ff..5bef931f8b14 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -247,8 +247,8 @@ do { \
247#ifdef CONFIG_SMP 247#ifdef CONFIG_SMP
248int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); 248int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
249int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); 249int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
250void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); 250void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
251void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); 251void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
252int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); 252int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
253int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); 253int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
254int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); 254int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
@@ -264,12 +264,12 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
264 wrmsr(msr_no, l, h); 264 wrmsr(msr_no, l, h);
265 return 0; 265 return 0;
266} 266}
267static inline void rdmsr_on_cpus(const cpumask_t *m, u32 msr_no, 267static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
268 struct msr *msrs) 268 struct msr *msrs)
269{ 269{
270 rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h)); 270 rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
271} 271}
272static inline void wrmsr_on_cpus(const cpumask_t *m, u32 msr_no, 272static inline void wrmsr_on_cpus(const struct cpumask *m, u32 msr_no,
273 struct msr *msrs) 273 struct msr *msrs)
274{ 274{
275 wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h); 275 wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index ad7ce3fd5065..8d9f8548a870 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -28,9 +28,20 @@
28 */ 28 */
29#define ARCH_PERFMON_EVENT_MASK 0xffff 29#define ARCH_PERFMON_EVENT_MASK 0xffff
30 30
31/*
32 * filter mask to validate fixed counter events.
33 * the following filters disqualify for fixed counters:
34 * - inv
35 * - edge
36 * - cnt-mask
37 * The other filters are supported by fixed counters.
38 * The any-thread option is supported starting with v3.
39 */
40#define ARCH_PERFMON_EVENT_FILTER_MASK 0xff840000
41
31#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c 42#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
32#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) 43#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
33#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0 44#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
34#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \ 45#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
35 (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX)) 46 (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
36 47
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index c9786480f0fe..6f8ec1c37e0a 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -30,6 +30,7 @@ struct mm_struct;
30#include <linux/math64.h> 30#include <linux/math64.h>
31#include <linux/init.h> 31#include <linux/init.h>
32 32
33#define HBP_NUM 4
33/* 34/*
34 * Default implementation of macro that returns current 35 * Default implementation of macro that returns current
35 * instruction pointer ("program counter"). 36 * instruction pointer ("program counter").
@@ -422,6 +423,8 @@ extern unsigned int xstate_size;
422extern void free_thread_xstate(struct task_struct *); 423extern void free_thread_xstate(struct task_struct *);
423extern struct kmem_cache *task_xstate_cachep; 424extern struct kmem_cache *task_xstate_cachep;
424 425
426struct perf_event;
427
425struct thread_struct { 428struct thread_struct {
426 /* Cached TLS descriptors: */ 429 /* Cached TLS descriptors: */
427 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; 430 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
@@ -443,13 +446,10 @@ struct thread_struct {
443 unsigned long fs; 446 unsigned long fs;
444#endif 447#endif
445 unsigned long gs; 448 unsigned long gs;
446 /* Hardware debugging registers: */ 449 /* Save middle states of ptrace breakpoints */
447 unsigned long debugreg0; 450 struct perf_event *ptrace_bps[HBP_NUM];
448 unsigned long debugreg1; 451 /* Debug status used for traps, single steps, etc... */
449 unsigned long debugreg2; 452 unsigned long debugreg6;
450 unsigned long debugreg3;
451 unsigned long debugreg6;
452 unsigned long debugreg7;
453 /* Fault info: */ 453 /* Fault info: */
454 unsigned long cr2; 454 unsigned long cr2;
455 unsigned long trap_no; 455 unsigned long trap_no;
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 0f0d908349aa..3d11fd0f44c5 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -7,6 +7,7 @@
7 7
8#ifdef __KERNEL__ 8#ifdef __KERNEL__
9#include <asm/segment.h> 9#include <asm/segment.h>
10#include <asm/page_types.h>
10#endif 11#endif
11 12
12#ifndef __ASSEMBLY__ 13#ifndef __ASSEMBLY__
@@ -216,6 +217,67 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
216 return regs->sp; 217 return regs->sp;
217} 218}
218 219
220/* Query offset/name of register from its name/offset */
221extern int regs_query_register_offset(const char *name);
222extern const char *regs_query_register_name(unsigned int offset);
223#define MAX_REG_OFFSET (offsetof(struct pt_regs, ss))
224
225/**
226 * regs_get_register() - get register value from its offset
227 * @regs: pt_regs from which register value is gotten.
228 * @offset: offset number of the register.
229 *
230 * regs_get_register returns the value of a register. The @offset is the
231 * offset of the register in struct pt_regs address which specified by @regs.
232 * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
233 */
234static inline unsigned long regs_get_register(struct pt_regs *regs,
235 unsigned int offset)
236{
237 if (unlikely(offset > MAX_REG_OFFSET))
238 return 0;
239 return *(unsigned long *)((unsigned long)regs + offset);
240}
241
242/**
243 * regs_within_kernel_stack() - check the address in the stack
244 * @regs: pt_regs which contains kernel stack pointer.
245 * @addr: address which is checked.
246 *
247 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
248 * If @addr is within the kernel stack, it returns true. If not, returns false.
249 */
250static inline int regs_within_kernel_stack(struct pt_regs *regs,
251 unsigned long addr)
252{
253 return ((addr & ~(THREAD_SIZE - 1)) ==
254 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
255}
256
257/**
258 * regs_get_kernel_stack_nth() - get Nth entry of the stack
259 * @regs: pt_regs which contains kernel stack pointer.
260 * @n: stack entry number.
261 *
262 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
263 * is specified by @regs. If the @n th entry is NOT in the kernel stack,
264 * this returns 0.
265 */
266static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
267 unsigned int n)
268{
269 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
270 addr += n;
271 if (regs_within_kernel_stack(regs, (unsigned long)addr))
272 return *addr;
273 else
274 return 0;
275}
276
277/* Get Nth argument at function call */
278extern unsigned long regs_get_argument_nth(struct pt_regs *regs,
279 unsigned int n);
280
219/* 281/*
220 * These are defined as per linux/ptrace.h, which see. 282 * These are defined as per linux/ptrace.h, which see.
221 */ 283 */
diff --git a/arch/x86/include/asm/string_32.h b/arch/x86/include/asm/string_32.h
index ae907e617181..3d3e8353ee5c 100644
--- a/arch/x86/include/asm/string_32.h
+++ b/arch/x86/include/asm/string_32.h
@@ -177,10 +177,15 @@ static inline void *__memcpy3d(void *to, const void *from, size_t len)
177 */ 177 */
178 178
179#ifndef CONFIG_KMEMCHECK 179#ifndef CONFIG_KMEMCHECK
180
181#if (__GNUC__ >= 4)
182#define memcpy(t, f, n) __builtin_memcpy(t, f, n)
183#else
180#define memcpy(t, f, n) \ 184#define memcpy(t, f, n) \
181 (__builtin_constant_p((n)) \ 185 (__builtin_constant_p((n)) \
182 ? __constant_memcpy((t), (f), (n)) \ 186 ? __constant_memcpy((t), (f), (n)) \
183 : __memcpy((t), (f), (n))) 187 : __memcpy((t), (f), (n)))
188#endif
184#else 189#else
185/* 190/*
186 * kmemcheck becomes very happy if we use the REP instructions unconditionally, 191 * kmemcheck becomes very happy if we use the REP instructions unconditionally,
@@ -316,11 +321,15 @@ void *__constant_c_and_count_memset(void *s, unsigned long pattern,
316 : __memset_generic((s), (c), (count))) 321 : __memset_generic((s), (c), (count)))
317 322
318#define __HAVE_ARCH_MEMSET 323#define __HAVE_ARCH_MEMSET
324#if (__GNUC__ >= 4)
325#define memset(s, c, count) __builtin_memset(s, c, count)
326#else
319#define memset(s, c, count) \ 327#define memset(s, c, count) \
320 (__builtin_constant_p(c) \ 328 (__builtin_constant_p(c) \
321 ? __constant_c_x_memset((s), (0x01010101UL * (unsigned char)(c)), \ 329 ? __constant_c_x_memset((s), (0x01010101UL * (unsigned char)(c)), \
322 (count)) \ 330 (count)) \
323 : __memset((s), (c), (count))) 331 : __memset((s), (c), (count)))
332#endif
324 333
325/* 334/*
326 * find the first occurrence of byte 'c', or 1 past the area if none 335 * find the first occurrence of byte 'c', or 1 past the area if none
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 72a6dcd1299b..9af9decb38c3 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -51,11 +51,6 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
51asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t); 51asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t);
52asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *); 52asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *);
53 53
54#ifdef CONFIG_SYSCTL_SYSCALL
55struct sysctl_ia32;
56asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *);
57#endif
58
59asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32); 54asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
60asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32); 55asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);
61 56
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index f08f97374892..022a84386de8 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -128,8 +128,6 @@ do { \
128 "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ 128 "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \
129 "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ 129 "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \
130 "call __switch_to\n\t" \ 130 "call __switch_to\n\t" \
131 ".globl thread_return\n" \
132 "thread_return:\n\t" \
133 "movq "__percpu_arg([current_task])",%%rsi\n\t" \ 131 "movq "__percpu_arg([current_task])",%%rsi\n\t" \
134 __switch_canary \ 132 __switch_canary \
135 "movq %P[thread_info](%%rsi),%%r8\n\t" \ 133 "movq %P[thread_info](%%rsi),%%r8\n\t" \
@@ -157,19 +155,22 @@ extern void native_load_gs_index(unsigned);
157 * Load a segment. Fall back on loading the zero 155 * Load a segment. Fall back on loading the zero
158 * segment if something goes wrong.. 156 * segment if something goes wrong..
159 */ 157 */
160#define loadsegment(seg, value) \ 158#define loadsegment(seg, value) \
161 asm volatile("\n" \ 159do { \
162 "1:\t" \ 160 unsigned short __val = (value); \
163 "movl %k0,%%" #seg "\n" \ 161 \
164 "2:\n" \ 162 asm volatile(" \n" \
165 ".section .fixup,\"ax\"\n" \ 163 "1: movl %k0,%%" #seg " \n" \
166 "3:\t" \ 164 \
167 "movl %k1, %%" #seg "\n\t" \ 165 ".section .fixup,\"ax\" \n" \
168 "jmp 2b\n" \ 166 "2: xorl %k0,%k0 \n" \
169 ".previous\n" \ 167 " jmp 1b \n" \
170 _ASM_EXTABLE(1b,3b) \ 168 ".previous \n" \
171 : :"r" (value), "r" (0) : "memory") 169 \
172 170 _ASM_EXTABLE(1b, 2b) \
171 \
172 : "+r" (__val) : : "memory"); \
173} while (0)
173 174
174/* 175/*
175 * Save a segment register away 176 * Save a segment register away
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index d2c6c930b491..abd3e0ea762a 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -570,7 +570,6 @@ extern struct movsl_mask {
570#ifdef CONFIG_X86_32 570#ifdef CONFIG_X86_32
571# include "uaccess_32.h" 571# include "uaccess_32.h"
572#else 572#else
573# define ARCH_HAS_SEARCH_EXTABLE
574# include "uaccess_64.h" 573# include "uaccess_64.h"
575#endif 574#endif
576 575
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 632fb44b4cb5..0c9825e97f36 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -187,9 +187,34 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from,
187 187
188unsigned long __must_check copy_to_user(void __user *to, 188unsigned long __must_check copy_to_user(void __user *to,
189 const void *from, unsigned long n); 189 const void *from, unsigned long n);
190unsigned long __must_check copy_from_user(void *to, 190unsigned long __must_check _copy_from_user(void *to,
191 const void __user *from, 191 const void __user *from,
192 unsigned long n); 192 unsigned long n);
193
194
195extern void copy_from_user_overflow(void)
196#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
197 __compiletime_error("copy_from_user() buffer size is not provably correct")
198#else
199 __compiletime_warning("copy_from_user() buffer size is not provably correct")
200#endif
201;
202
203static inline unsigned long __must_check copy_from_user(void *to,
204 const void __user *from,
205 unsigned long n)
206{
207 int sz = __compiletime_object_size(to);
208 int ret = -EFAULT;
209
210 if (likely(sz == -1 || sz >= n))
211 ret = _copy_from_user(to, from, n);
212 else
213 copy_from_user_overflow();
214
215 return ret;
216}
217
193long __must_check strncpy_from_user(char *dst, const char __user *src, 218long __must_check strncpy_from_user(char *dst, const char __user *src,
194 long count); 219 long count);
195long __must_check __strncpy_from_user(char *dst, 220long __must_check __strncpy_from_user(char *dst,
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index db24b215fc50..46324c6a4f6e 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -19,12 +19,37 @@ __must_check unsigned long
19copy_user_generic(void *to, const void *from, unsigned len); 19copy_user_generic(void *to, const void *from, unsigned len);
20 20
21__must_check unsigned long 21__must_check unsigned long
22copy_to_user(void __user *to, const void *from, unsigned len); 22_copy_to_user(void __user *to, const void *from, unsigned len);
23__must_check unsigned long 23__must_check unsigned long
24copy_from_user(void *to, const void __user *from, unsigned len); 24_copy_from_user(void *to, const void __user *from, unsigned len);
25__must_check unsigned long 25__must_check unsigned long
26copy_in_user(void __user *to, const void __user *from, unsigned len); 26copy_in_user(void __user *to, const void __user *from, unsigned len);
27 27
28static inline unsigned long __must_check copy_from_user(void *to,
29 const void __user *from,
30 unsigned long n)
31{
32 int sz = __compiletime_object_size(to);
33 int ret = -EFAULT;
34
35 might_fault();
36 if (likely(sz == -1 || sz >= n))
37 ret = _copy_from_user(to, from, n);
38#ifdef CONFIG_DEBUG_VM
39 else
40 WARN(1, "Buffer overflow detected!\n");
41#endif
42 return ret;
43}
44
45static __always_inline __must_check
46int copy_to_user(void __user *dst, const void *src, unsigned size)
47{
48 might_fault();
49
50 return _copy_to_user(dst, src, size);
51}
52
28static __always_inline __must_check 53static __always_inline __must_check
29int __copy_from_user(void *dst, const void __user *src, unsigned size) 54int __copy_from_user(void *dst, const void __user *src, unsigned size)
30{ 55{
@@ -176,8 +201,11 @@ __must_check long strlen_user(const char __user *str);
176__must_check unsigned long clear_user(void __user *mem, unsigned long len); 201__must_check unsigned long clear_user(void __user *mem, unsigned long len);
177__must_check unsigned long __clear_user(void __user *mem, unsigned long len); 202__must_check unsigned long __clear_user(void __user *mem, unsigned long len);
178 203
179__must_check long __copy_from_user_inatomic(void *dst, const void __user *src, 204static __must_check __always_inline int
180 unsigned size); 205__copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
206{
207 return copy_user_generic(dst, (__force const void *)src, size);
208}
181 209
182static __must_check __always_inline int 210static __must_check __always_inline int
183__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) 211__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
diff --git a/arch/x86/include/asm/uv/uv_irq.h b/arch/x86/include/asm/uv/uv_irq.h
index 9613c8c0b647..d6b17c760622 100644
--- a/arch/x86/include/asm/uv/uv_irq.h
+++ b/arch/x86/include/asm/uv/uv_irq.h
@@ -25,12 +25,14 @@ struct uv_IO_APIC_route_entry {
25 dest : 32; 25 dest : 32;
26}; 26};
27 27
28extern struct irq_chip uv_irq_chip; 28enum {
29 29 UV_AFFINITY_ALL,
30extern int arch_enable_uv_irq(char *, unsigned int, int, int, unsigned long); 30 UV_AFFINITY_NODE,
31extern void arch_disable_uv_irq(int, unsigned long); 31 UV_AFFINITY_CPU
32};
32 33
33extern int uv_setup_irq(char *, int, int, unsigned long); 34extern int uv_irq_2_mmr_info(int, unsigned long *, int *);
34extern void uv_teardown_irq(unsigned int, int, unsigned long); 35extern int uv_setup_irq(char *, int, int, unsigned long, int);
36extern void uv_teardown_irq(unsigned int);
35 37
36#endif /* _ASM_X86_UV_UV_IRQ_H */ 38#endif /* _ASM_X86_UV_UV_IRQ_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d8e5d0cdd678..4f2e66e29ecc 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -40,7 +40,7 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
40obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o 40obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o
41obj-y += bootflag.o e820.o 41obj-y += bootflag.o e820.o
42obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o 42obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
43obj-y += alternative.o i8253.o pci-nommu.o 43obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
44obj-y += tsc.o io_delay.o rtc.o 44obj-y += tsc.o io_delay.o rtc.o
45 45
46obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o 46obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index da7b7b9f8bd8..565c1bfc507d 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -2,7 +2,7 @@
2# Makefile for local APIC drivers and for the IO-APIC code 2# Makefile for local APIC drivers and for the IO-APIC code
3# 3#
4 4
5obj-$(CONFIG_X86_LOCAL_APIC) += apic.o probe_$(BITS).o ipi.o nmi.o 5obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_noop.o probe_$(BITS).o ipi.o nmi.o
6obj-$(CONFIG_X86_IO_APIC) += io_apic.o 6obj-$(CONFIG_X86_IO_APIC) += io_apic.o
7obj-$(CONFIG_SMP) += ipi.o 7obj-$(CONFIG_SMP) += ipi.o
8 8
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 894aa97f0717..ad8c75b9e453 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -241,28 +241,13 @@ static int modern_apic(void)
241} 241}
242 242
243/* 243/*
244 * bare function to substitute write operation 244 * right after this call apic become NOOP driven
245 * and it's _that_ fast :) 245 * so apic->write/read doesn't do anything
246 */
247static void native_apic_write_dummy(u32 reg, u32 v)
248{
249 WARN_ON_ONCE((cpu_has_apic || !disable_apic));
250}
251
252static u32 native_apic_read_dummy(u32 reg)
253{
254 WARN_ON_ONCE((cpu_has_apic && !disable_apic));
255 return 0;
256}
257
258/*
259 * right after this call apic->write/read doesn't do anything
260 * note that there is no restore operation it works one way
261 */ 246 */
262void apic_disable(void) 247void apic_disable(void)
263{ 248{
264 apic->read = native_apic_read_dummy; 249 pr_info("APIC: switched to apic NOOP\n");
265 apic->write = native_apic_write_dummy; 250 apic = &apic_noop;
266} 251}
267 252
268void native_apic_wait_icr_idle(void) 253void native_apic_wait_icr_idle(void)
@@ -459,7 +444,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
459 v = apic_read(APIC_LVTT); 444 v = apic_read(APIC_LVTT);
460 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); 445 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
461 apic_write(APIC_LVTT, v); 446 apic_write(APIC_LVTT, v);
462 apic_write(APIC_TMICT, 0xffffffff); 447 apic_write(APIC_TMICT, 0);
463 break; 448 break;
464 case CLOCK_EVT_MODE_RESUME: 449 case CLOCK_EVT_MODE_RESUME:
465 /* Nothing to do here */ 450 /* Nothing to do here */
@@ -1392,14 +1377,11 @@ void __init enable_IR_x2apic(void)
1392 unsigned long flags; 1377 unsigned long flags;
1393 struct IO_APIC_route_entry **ioapic_entries = NULL; 1378 struct IO_APIC_route_entry **ioapic_entries = NULL;
1394 int ret, x2apic_enabled = 0; 1379 int ret, x2apic_enabled = 0;
1395 int dmar_table_init_ret = 0; 1380 int dmar_table_init_ret;
1396 1381
1397#ifdef CONFIG_INTR_REMAP
1398 dmar_table_init_ret = dmar_table_init(); 1382 dmar_table_init_ret = dmar_table_init();
1399 if (dmar_table_init_ret) 1383 if (dmar_table_init_ret && !x2apic_supported())
1400 pr_debug("dmar_table_init() failed with %d:\n", 1384 return;
1401 dmar_table_init_ret);
1402#endif
1403 1385
1404 ioapic_entries = alloc_ioapic_entries(); 1386 ioapic_entries = alloc_ioapic_entries();
1405 if (!ioapic_entries) { 1387 if (!ioapic_entries) {
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
new file mode 100644
index 000000000000..d9acc3bee0f4
--- /dev/null
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -0,0 +1,200 @@
1/*
2 * NOOP APIC driver.
3 *
4 * Does almost nothing and should be substituted by a real apic driver via
5 * probe routine.
6 *
7 * Though in case if apic is disabled (for some reason) we try
8 * to not uglify the caller's code and allow to call (some) apic routines
9 * like self-ipi, etc...
10 */
11
12#include <linux/threads.h>
13#include <linux/cpumask.h>
14#include <linux/module.h>
15#include <linux/string.h>
16#include <linux/kernel.h>
17#include <linux/ctype.h>
18#include <linux/init.h>
19#include <linux/errno.h>
20#include <asm/fixmap.h>
21#include <asm/mpspec.h>
22#include <asm/apicdef.h>
23#include <asm/apic.h>
24#include <asm/setup.h>
25
26#include <linux/smp.h>
27#include <asm/ipi.h>
28
29#include <linux/interrupt.h>
30#include <asm/acpi.h>
31#include <asm/e820.h>
32
33static void noop_init_apic_ldr(void) { }
34static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { }
35static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { }
36static void noop_send_IPI_allbutself(int vector) { }
37static void noop_send_IPI_all(int vector) { }
38static void noop_send_IPI_self(int vector) { }
39static void noop_apic_wait_icr_idle(void) { }
40static void noop_apic_icr_write(u32 low, u32 id) { }
41
42static int noop_wakeup_secondary_cpu(int apicid, unsigned long start_eip)
43{
44 return -1;
45}
46
47static u32 noop_safe_apic_wait_icr_idle(void)
48{
49 return 0;
50}
51
52static u64 noop_apic_icr_read(void)
53{
54 return 0;
55}
56
57static int noop_cpu_to_logical_apicid(int cpu)
58{
59 return 0;
60}
61
62static int noop_phys_pkg_id(int cpuid_apic, int index_msb)
63{
64 return 0;
65}
66
67static unsigned int noop_get_apic_id(unsigned long x)
68{
69 return 0;
70}
71
72static int noop_probe(void)
73{
74 /*
75 * NOOP apic should not ever be
76 * enabled via probe routine
77 */
78 return 0;
79}
80
81static int noop_apic_id_registered(void)
82{
83 /*
84 * if we would be really "pedantic"
85 * we should pass read_apic_id() here
86 * but since NOOP suppose APIC ID = 0
87 * lets save a few cycles
88 */
89 return physid_isset(0, phys_cpu_present_map);
90}
91
92static const struct cpumask *noop_target_cpus(void)
93{
94 /* only BSP here */
95 return cpumask_of(0);
96}
97
98static unsigned long noop_check_apicid_used(physid_mask_t *map, int apicid)
99{
100 return physid_isset(apicid, *map);
101}
102
103static unsigned long noop_check_apicid_present(int bit)
104{
105 return physid_isset(bit, phys_cpu_present_map);
106}
107
108static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask)
109{
110 if (cpu != 0)
111 pr_warning("APIC: Vector allocated for non-BSP cpu\n");
112 cpumask_clear(retmask);
113 cpumask_set_cpu(cpu, retmask);
114}
115
116int noop_apicid_to_node(int logical_apicid)
117{
118 /* we're always on node 0 */
119 return 0;
120}
121
122static u32 noop_apic_read(u32 reg)
123{
124 WARN_ON_ONCE((cpu_has_apic && !disable_apic));
125 return 0;
126}
127
128static void noop_apic_write(u32 reg, u32 v)
129{
130 WARN_ON_ONCE((cpu_has_apic || !disable_apic));
131}
132
133struct apic apic_noop = {
134 .name = "noop",
135 .probe = noop_probe,
136 .acpi_madt_oem_check = NULL,
137
138 .apic_id_registered = noop_apic_id_registered,
139
140 .irq_delivery_mode = dest_LowestPrio,
141 /* logical delivery broadcast to all CPUs: */
142 .irq_dest_mode = 1,
143
144 .target_cpus = noop_target_cpus,
145 .disable_esr = 0,
146 .dest_logical = APIC_DEST_LOGICAL,
147 .check_apicid_used = noop_check_apicid_used,
148 .check_apicid_present = noop_check_apicid_present,
149
150 .vector_allocation_domain = noop_vector_allocation_domain,
151 .init_apic_ldr = noop_init_apic_ldr,
152
153 .ioapic_phys_id_map = default_ioapic_phys_id_map,
154 .setup_apic_routing = NULL,
155 .multi_timer_check = NULL,
156 .apicid_to_node = noop_apicid_to_node,
157
158 .cpu_to_logical_apicid = noop_cpu_to_logical_apicid,
159 .cpu_present_to_apicid = default_cpu_present_to_apicid,
160 .apicid_to_cpu_present = physid_set_mask_of_physid,
161
162 .setup_portio_remap = NULL,
163 .check_phys_apicid_present = default_check_phys_apicid_present,
164 .enable_apic_mode = NULL,
165
166 .phys_pkg_id = noop_phys_pkg_id,
167
168 .mps_oem_check = NULL,
169
170 .get_apic_id = noop_get_apic_id,
171 .set_apic_id = NULL,
172 .apic_id_mask = 0x0F << 24,
173
174 .cpu_mask_to_apicid = default_cpu_mask_to_apicid,
175 .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
176
177 .send_IPI_mask = noop_send_IPI_mask,
178 .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself,
179 .send_IPI_allbutself = noop_send_IPI_allbutself,
180 .send_IPI_all = noop_send_IPI_all,
181 .send_IPI_self = noop_send_IPI_self,
182
183 .wakeup_secondary_cpu = noop_wakeup_secondary_cpu,
184
185 /* should be safe */
186 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
187 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
188
189 .wait_for_init_deassert = NULL,
190
191 .smp_callin_clear_local_apic = NULL,
192 .inquire_remote_apic = NULL,
193
194 .read = noop_apic_read,
195 .write = noop_apic_write,
196 .icr_read = noop_apic_icr_read,
197 .icr_write = noop_apic_icr_write,
198 .wait_icr_idle = noop_apic_wait_icr_idle,
199 .safe_wait_icr_idle = noop_safe_apic_wait_icr_idle,
200};
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index 77a06413b6b2..38dcecfa5818 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -35,7 +35,7 @@ static const struct cpumask *bigsmp_target_cpus(void)
35#endif 35#endif
36} 36}
37 37
38static unsigned long bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) 38static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
39{ 39{
40 return 0; 40 return 0;
41} 41}
@@ -93,11 +93,6 @@ static int bigsmp_cpu_present_to_apicid(int mps_cpu)
93 return BAD_APICID; 93 return BAD_APICID;
94} 94}
95 95
96static physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid)
97{
98 return physid_mask_of_physid(phys_apicid);
99}
100
101/* Mapping from cpu number to logical apicid */ 96/* Mapping from cpu number to logical apicid */
102static inline int bigsmp_cpu_to_logical_apicid(int cpu) 97static inline int bigsmp_cpu_to_logical_apicid(int cpu)
103{ 98{
@@ -106,10 +101,10 @@ static inline int bigsmp_cpu_to_logical_apicid(int cpu)
106 return cpu_physical_id(cpu); 101 return cpu_physical_id(cpu);
107} 102}
108 103
109static physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) 104static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
110{ 105{
111 /* For clustered we don't have a good way to do this yet - hack */ 106 /* For clustered we don't have a good way to do this yet - hack */
112 return physids_promote(0xFFL); 107 physids_promote(0xFFL, retmap);
113} 108}
114 109
115static int bigsmp_check_phys_apicid_present(int phys_apicid) 110static int bigsmp_check_phys_apicid_present(int phys_apicid)
@@ -230,7 +225,7 @@ struct apic apic_bigsmp = {
230 .apicid_to_node = bigsmp_apicid_to_node, 225 .apicid_to_node = bigsmp_apicid_to_node,
231 .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid, 226 .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid,
232 .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid, 227 .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid,
233 .apicid_to_cpu_present = bigsmp_apicid_to_cpu_present, 228 .apicid_to_cpu_present = physid_set_mask_of_physid,
234 .setup_portio_remap = NULL, 229 .setup_portio_remap = NULL,
235 .check_phys_apicid_present = bigsmp_check_phys_apicid_present, 230 .check_phys_apicid_present = bigsmp_check_phys_apicid_present,
236 .enable_apic_mode = NULL, 231 .enable_apic_mode = NULL,
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 89174f847b49..e85f8fb7f8e7 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -466,11 +466,11 @@ static const struct cpumask *es7000_target_cpus(void)
466 return cpumask_of(smp_processor_id()); 466 return cpumask_of(smp_processor_id());
467} 467}
468 468
469static unsigned long 469static unsigned long es7000_check_apicid_used(physid_mask_t *map, int apicid)
470es7000_check_apicid_used(physid_mask_t bitmap, int apicid)
471{ 470{
472 return 0; 471 return 0;
473} 472}
473
474static unsigned long es7000_check_apicid_present(int bit) 474static unsigned long es7000_check_apicid_present(int bit)
475{ 475{
476 return physid_isset(bit, phys_cpu_present_map); 476 return physid_isset(bit, phys_cpu_present_map);
@@ -539,14 +539,10 @@ static int es7000_cpu_present_to_apicid(int mps_cpu)
539 539
540static int cpu_id; 540static int cpu_id;
541 541
542static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) 542static void es7000_apicid_to_cpu_present(int phys_apicid, physid_mask_t *retmap)
543{ 543{
544 physid_mask_t mask; 544 physid_set_mask_of_physid(cpu_id, retmap);
545
546 mask = physid_mask_of_physid(cpu_id);
547 ++cpu_id; 545 ++cpu_id;
548
549 return mask;
550} 546}
551 547
552/* Mapping from cpu number to logical apicid */ 548/* Mapping from cpu number to logical apicid */
@@ -561,10 +557,10 @@ static int es7000_cpu_to_logical_apicid(int cpu)
561#endif 557#endif
562} 558}
563 559
564static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) 560static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
565{ 561{
566 /* For clustered we don't have a good way to do this yet - hack */ 562 /* For clustered we don't have a good way to do this yet - hack */
567 return physids_promote(0xff); 563 physids_promote(0xFFL, retmap);
568} 564}
569 565
570static int es7000_check_phys_apicid_present(int cpu_physical_apicid) 566static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index dc69f28489f5..c0b4468683f9 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -60,8 +60,6 @@
60#include <asm/irq_remapping.h> 60#include <asm/irq_remapping.h>
61#include <asm/hpet.h> 61#include <asm/hpet.h>
62#include <asm/hw_irq.h> 62#include <asm/hw_irq.h>
63#include <asm/uv/uv_hub.h>
64#include <asm/uv/uv_irq.h>
65 63
66#include <asm/apic.h> 64#include <asm/apic.h>
67 65
@@ -140,20 +138,6 @@ static struct irq_pin_list *get_one_free_irq_2_pin(int node)
140 return pin; 138 return pin;
141} 139}
142 140
143/*
144 * This is performance-critical, we want to do it O(1)
145 *
146 * Most irqs are mapped 1:1 with pins.
147 */
148struct irq_cfg {
149 struct irq_pin_list *irq_2_pin;
150 cpumask_var_t domain;
151 cpumask_var_t old_domain;
152 unsigned move_cleanup_count;
153 u8 vector;
154 u8 move_in_progress : 1;
155};
156
157/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ 141/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
158#ifdef CONFIG_SPARSE_IRQ 142#ifdef CONFIG_SPARSE_IRQ
159static struct irq_cfg irq_cfgx[] = { 143static struct irq_cfg irq_cfgx[] = {
@@ -209,7 +193,7 @@ int __init arch_early_irq_init(void)
209} 193}
210 194
211#ifdef CONFIG_SPARSE_IRQ 195#ifdef CONFIG_SPARSE_IRQ
212static struct irq_cfg *irq_cfg(unsigned int irq) 196struct irq_cfg *irq_cfg(unsigned int irq)
213{ 197{
214 struct irq_cfg *cfg = NULL; 198 struct irq_cfg *cfg = NULL;
215 struct irq_desc *desc; 199 struct irq_desc *desc;
@@ -361,7 +345,7 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
361/* end for move_irq_desc */ 345/* end for move_irq_desc */
362 346
363#else 347#else
364static struct irq_cfg *irq_cfg(unsigned int irq) 348struct irq_cfg *irq_cfg(unsigned int irq)
365{ 349{
366 return irq < nr_irqs ? irq_cfgx + irq : NULL; 350 return irq < nr_irqs ? irq_cfgx + irq : NULL;
367} 351}
@@ -555,23 +539,41 @@ static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
555 add_pin_to_irq_node(cfg, node, newapic, newpin); 539 add_pin_to_irq_node(cfg, node, newapic, newpin);
556} 540}
557 541
542static void __io_apic_modify_irq(struct irq_pin_list *entry,
543 int mask_and, int mask_or,
544 void (*final)(struct irq_pin_list *entry))
545{
546 unsigned int reg, pin;
547
548 pin = entry->pin;
549 reg = io_apic_read(entry->apic, 0x10 + pin * 2);
550 reg &= mask_and;
551 reg |= mask_or;
552 io_apic_modify(entry->apic, 0x10 + pin * 2, reg);
553 if (final)
554 final(entry);
555}
556
558static void io_apic_modify_irq(struct irq_cfg *cfg, 557static void io_apic_modify_irq(struct irq_cfg *cfg,
559 int mask_and, int mask_or, 558 int mask_and, int mask_or,
560 void (*final)(struct irq_pin_list *entry)) 559 void (*final)(struct irq_pin_list *entry))
561{ 560{
562 int pin;
563 struct irq_pin_list *entry; 561 struct irq_pin_list *entry;
564 562
565 for_each_irq_pin(entry, cfg->irq_2_pin) { 563 for_each_irq_pin(entry, cfg->irq_2_pin)
566 unsigned int reg; 564 __io_apic_modify_irq(entry, mask_and, mask_or, final);
567 pin = entry->pin; 565}
568 reg = io_apic_read(entry->apic, 0x10 + pin * 2); 566
569 reg &= mask_and; 567static void __mask_and_edge_IO_APIC_irq(struct irq_pin_list *entry)
570 reg |= mask_or; 568{
571 io_apic_modify(entry->apic, 0x10 + pin * 2, reg); 569 __io_apic_modify_irq(entry, ~IO_APIC_REDIR_LEVEL_TRIGGER,
572 if (final) 570 IO_APIC_REDIR_MASKED, NULL);
573 final(entry); 571}
574 } 572
573static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
574{
575 __io_apic_modify_irq(entry, ~IO_APIC_REDIR_MASKED,
576 IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
575} 577}
576 578
577static void __unmask_IO_APIC_irq(struct irq_cfg *cfg) 579static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
@@ -595,18 +597,6 @@ static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
595 io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); 597 io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
596} 598}
597 599
598static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg)
599{
600 io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER,
601 IO_APIC_REDIR_MASKED, NULL);
602}
603
604static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg)
605{
606 io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED,
607 IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
608}
609
610static void mask_IO_APIC_irq_desc(struct irq_desc *desc) 600static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
611{ 601{
612 struct irq_cfg *cfg = desc->chip_data; 602 struct irq_cfg *cfg = desc->chip_data;
@@ -1177,7 +1167,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
1177 int cpu, err; 1167 int cpu, err;
1178 cpumask_var_t tmp_mask; 1168 cpumask_var_t tmp_mask;
1179 1169
1180 if ((cfg->move_in_progress) || cfg->move_cleanup_count) 1170 if (cfg->move_in_progress)
1181 return -EBUSY; 1171 return -EBUSY;
1182 1172
1183 if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC)) 1173 if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
@@ -1237,8 +1227,7 @@ next:
1237 return err; 1227 return err;
1238} 1228}
1239 1229
1240static int 1230int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
1241assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
1242{ 1231{
1243 int err; 1232 int err;
1244 unsigned long flags; 1233 unsigned long flags;
@@ -1599,9 +1588,6 @@ __apicdebuginit(void) print_IO_APIC(void)
1599 struct irq_desc *desc; 1588 struct irq_desc *desc;
1600 unsigned int irq; 1589 unsigned int irq;
1601 1590
1602 if (apic_verbosity == APIC_QUIET)
1603 return;
1604
1605 printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); 1591 printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
1606 for (i = 0; i < nr_ioapics; i++) 1592 for (i = 0; i < nr_ioapics; i++)
1607 printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", 1593 printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
@@ -1708,9 +1694,6 @@ __apicdebuginit(void) print_APIC_field(int base)
1708{ 1694{
1709 int i; 1695 int i;
1710 1696
1711 if (apic_verbosity == APIC_QUIET)
1712 return;
1713
1714 printk(KERN_DEBUG); 1697 printk(KERN_DEBUG);
1715 1698
1716 for (i = 0; i < 8; i++) 1699 for (i = 0; i < 8; i++)
@@ -1724,9 +1707,6 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
1724 unsigned int i, v, ver, maxlvt; 1707 unsigned int i, v, ver, maxlvt;
1725 u64 icr; 1708 u64 icr;
1726 1709
1727 if (apic_verbosity == APIC_QUIET)
1728 return;
1729
1730 printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", 1710 printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
1731 smp_processor_id(), hard_smp_processor_id()); 1711 smp_processor_id(), hard_smp_processor_id());
1732 v = apic_read(APIC_ID); 1712 v = apic_read(APIC_ID);
@@ -1824,13 +1804,19 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
1824 printk("\n"); 1804 printk("\n");
1825} 1805}
1826 1806
1827__apicdebuginit(void) print_all_local_APICs(void) 1807__apicdebuginit(void) print_local_APICs(int maxcpu)
1828{ 1808{
1829 int cpu; 1809 int cpu;
1830 1810
1811 if (!maxcpu)
1812 return;
1813
1831 preempt_disable(); 1814 preempt_disable();
1832 for_each_online_cpu(cpu) 1815 for_each_online_cpu(cpu) {
1816 if (cpu >= maxcpu)
1817 break;
1833 smp_call_function_single(cpu, print_local_APIC, NULL, 1); 1818 smp_call_function_single(cpu, print_local_APIC, NULL, 1);
1819 }
1834 preempt_enable(); 1820 preempt_enable();
1835} 1821}
1836 1822
@@ -1839,7 +1825,7 @@ __apicdebuginit(void) print_PIC(void)
1839 unsigned int v; 1825 unsigned int v;
1840 unsigned long flags; 1826 unsigned long flags;
1841 1827
1842 if (apic_verbosity == APIC_QUIET || !nr_legacy_irqs) 1828 if (!nr_legacy_irqs)
1843 return; 1829 return;
1844 1830
1845 printk(KERN_DEBUG "\nprinting PIC contents\n"); 1831 printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1866,21 +1852,41 @@ __apicdebuginit(void) print_PIC(void)
1866 printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); 1852 printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
1867} 1853}
1868 1854
1869__apicdebuginit(int) print_all_ICs(void) 1855static int __initdata show_lapic = 1;
1856static __init int setup_show_lapic(char *arg)
1870{ 1857{
1858 int num = -1;
1859
1860 if (strcmp(arg, "all") == 0) {
1861 show_lapic = CONFIG_NR_CPUS;
1862 } else {
1863 get_option(&arg, &num);
1864 if (num >= 0)
1865 show_lapic = num;
1866 }
1867
1868 return 1;
1869}
1870__setup("show_lapic=", setup_show_lapic);
1871
1872__apicdebuginit(int) print_ICs(void)
1873{
1874 if (apic_verbosity == APIC_QUIET)
1875 return 0;
1876
1871 print_PIC(); 1877 print_PIC();
1872 1878
1873 /* don't print out if apic is not there */ 1879 /* don't print out if apic is not there */
1874 if (!cpu_has_apic && !apic_from_smp_config()) 1880 if (!cpu_has_apic && !apic_from_smp_config())
1875 return 0; 1881 return 0;
1876 1882
1877 print_all_local_APICs(); 1883 print_local_APICs(show_lapic);
1878 print_IO_APIC(); 1884 print_IO_APIC();
1879 1885
1880 return 0; 1886 return 0;
1881} 1887}
1882 1888
1883fs_initcall(print_all_ICs); 1889fs_initcall(print_ICs);
1884 1890
1885 1891
1886/* Where if anywhere is the i8259 connect in external int mode */ 1892/* Where if anywhere is the i8259 connect in external int mode */
@@ -2031,7 +2037,7 @@ void __init setup_ioapic_ids_from_mpc(void)
2031 * This is broken; anything with a real cpu count has to 2037 * This is broken; anything with a real cpu count has to
2032 * circumvent this idiocy regardless. 2038 * circumvent this idiocy regardless.
2033 */ 2039 */
2034 phys_id_present_map = apic->ioapic_phys_id_map(phys_cpu_present_map); 2040 apic->ioapic_phys_id_map(&phys_cpu_present_map, &phys_id_present_map);
2035 2041
2036 /* 2042 /*
2037 * Set the IOAPIC ID to the value stored in the MPC table. 2043 * Set the IOAPIC ID to the value stored in the MPC table.
@@ -2058,7 +2064,7 @@ void __init setup_ioapic_ids_from_mpc(void)
2058 * system must have a unique ID or we get lots of nice 2064 * system must have a unique ID or we get lots of nice
2059 * 'stuck on smp_invalidate_needed IPI wait' messages. 2065 * 'stuck on smp_invalidate_needed IPI wait' messages.
2060 */ 2066 */
2061 if (apic->check_apicid_used(phys_id_present_map, 2067 if (apic->check_apicid_used(&phys_id_present_map,
2062 mp_ioapics[apic_id].apicid)) { 2068 mp_ioapics[apic_id].apicid)) {
2063 printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", 2069 printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
2064 apic_id, mp_ioapics[apic_id].apicid); 2070 apic_id, mp_ioapics[apic_id].apicid);
@@ -2073,7 +2079,7 @@ void __init setup_ioapic_ids_from_mpc(void)
2073 mp_ioapics[apic_id].apicid = i; 2079 mp_ioapics[apic_id].apicid = i;
2074 } else { 2080 } else {
2075 physid_mask_t tmp; 2081 physid_mask_t tmp;
2076 tmp = apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid); 2082 apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid, &tmp);
2077 apic_printk(APIC_VERBOSE, "Setting %d in the " 2083 apic_printk(APIC_VERBOSE, "Setting %d in the "
2078 "phys_id_present_map\n", 2084 "phys_id_present_map\n",
2079 mp_ioapics[apic_id].apicid); 2085 mp_ioapics[apic_id].apicid);
@@ -2228,20 +2234,16 @@ static int ioapic_retrigger_irq(unsigned int irq)
2228 */ 2234 */
2229 2235
2230#ifdef CONFIG_SMP 2236#ifdef CONFIG_SMP
2231static void send_cleanup_vector(struct irq_cfg *cfg) 2237void send_cleanup_vector(struct irq_cfg *cfg)
2232{ 2238{
2233 cpumask_var_t cleanup_mask; 2239 cpumask_var_t cleanup_mask;
2234 2240
2235 if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) { 2241 if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
2236 unsigned int i; 2242 unsigned int i;
2237 cfg->move_cleanup_count = 0;
2238 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
2239 cfg->move_cleanup_count++;
2240 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) 2243 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
2241 apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR); 2244 apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
2242 } else { 2245 } else {
2243 cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask); 2246 cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
2244 cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
2245 apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); 2247 apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
2246 free_cpumask_var(cleanup_mask); 2248 free_cpumask_var(cleanup_mask);
2247 } 2249 }
@@ -2272,15 +2274,12 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
2272 } 2274 }
2273} 2275}
2274 2276
2275static int
2276assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
2277
2278/* 2277/*
2279 * Either sets desc->affinity to a valid value, and returns 2278 * Either sets desc->affinity to a valid value, and returns
2280 * ->cpu_mask_to_apicid of that, or returns BAD_APICID and 2279 * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
2281 * leaves desc->affinity untouched. 2280 * leaves desc->affinity untouched.
2282 */ 2281 */
2283static unsigned int 2282unsigned int
2284set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) 2283set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
2285{ 2284{
2286 struct irq_cfg *cfg; 2285 struct irq_cfg *cfg;
@@ -2433,8 +2432,6 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
2433 2432
2434 cfg = irq_cfg(irq); 2433 cfg = irq_cfg(irq);
2435 spin_lock(&desc->lock); 2434 spin_lock(&desc->lock);
2436 if (!cfg->move_cleanup_count)
2437 goto unlock;
2438 2435
2439 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) 2436 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
2440 goto unlock; 2437 goto unlock;
@@ -2452,7 +2449,6 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
2452 goto unlock; 2449 goto unlock;
2453 } 2450 }
2454 __get_cpu_var(vector_irq)[vector] = -1; 2451 __get_cpu_var(vector_irq)[vector] = -1;
2455 cfg->move_cleanup_count--;
2456unlock: 2452unlock:
2457 spin_unlock(&desc->lock); 2453 spin_unlock(&desc->lock);
2458 } 2454 }
@@ -2460,21 +2456,33 @@ unlock:
2460 irq_exit(); 2456 irq_exit();
2461} 2457}
2462 2458
2463static void irq_complete_move(struct irq_desc **descp) 2459static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
2464{ 2460{
2465 struct irq_desc *desc = *descp; 2461 struct irq_desc *desc = *descp;
2466 struct irq_cfg *cfg = desc->chip_data; 2462 struct irq_cfg *cfg = desc->chip_data;
2467 unsigned vector, me; 2463 unsigned me;
2468 2464
2469 if (likely(!cfg->move_in_progress)) 2465 if (likely(!cfg->move_in_progress))
2470 return; 2466 return;
2471 2467
2472 vector = ~get_irq_regs()->orig_ax;
2473 me = smp_processor_id(); 2468 me = smp_processor_id();
2474 2469
2475 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) 2470 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
2476 send_cleanup_vector(cfg); 2471 send_cleanup_vector(cfg);
2477} 2472}
2473
2474static void irq_complete_move(struct irq_desc **descp)
2475{
2476 __irq_complete_move(descp, ~get_irq_regs()->orig_ax);
2477}
2478
2479void irq_force_complete_move(int irq)
2480{
2481 struct irq_desc *desc = irq_to_desc(irq);
2482 struct irq_cfg *cfg = desc->chip_data;
2483
2484 __irq_complete_move(&desc, cfg->vector);
2485}
2478#else 2486#else
2479static inline void irq_complete_move(struct irq_desc **descp) {} 2487static inline void irq_complete_move(struct irq_desc **descp) {}
2480#endif 2488#endif
@@ -2490,6 +2498,59 @@ static void ack_apic_edge(unsigned int irq)
2490 2498
2491atomic_t irq_mis_count; 2499atomic_t irq_mis_count;
2492 2500
2501/*
2502 * IO-APIC versions below 0x20 don't support EOI register.
2503 * For the record, here is the information about various versions:
2504 * 0Xh 82489DX
2505 * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
2506 * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
2507 * 30h-FFh Reserved
2508 *
2509 * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
2510 * version as 0x2. This is an error with documentation and these ICH chips
2511 * use io-apic's of version 0x20.
2512 *
2513 * For IO-APIC's with EOI register, we use that to do an explicit EOI.
2514 * Otherwise, we simulate the EOI message manually by changing the trigger
2515 * mode to edge and then back to level, with RTE being masked during this.
2516*/
2517static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
2518{
2519 struct irq_pin_list *entry;
2520
2521 for_each_irq_pin(entry, cfg->irq_2_pin) {
2522 if (mp_ioapics[entry->apic].apicver >= 0x20) {
2523 /*
2524 * Intr-remapping uses pin number as the virtual vector
2525 * in the RTE. Actual vector is programmed in
2526 * intr-remapping table entry. Hence for the io-apic
2527 * EOI we use the pin number.
2528 */
2529 if (irq_remapped(irq))
2530 io_apic_eoi(entry->apic, entry->pin);
2531 else
2532 io_apic_eoi(entry->apic, cfg->vector);
2533 } else {
2534 __mask_and_edge_IO_APIC_irq(entry);
2535 __unmask_and_level_IO_APIC_irq(entry);
2536 }
2537 }
2538}
2539
2540static void eoi_ioapic_irq(struct irq_desc *desc)
2541{
2542 struct irq_cfg *cfg;
2543 unsigned long flags;
2544 unsigned int irq;
2545
2546 irq = desc->irq;
2547 cfg = desc->chip_data;
2548
2549 spin_lock_irqsave(&ioapic_lock, flags);
2550 __eoi_ioapic_irq(irq, cfg);
2551 spin_unlock_irqrestore(&ioapic_lock, flags);
2552}
2553
2493static void ack_apic_level(unsigned int irq) 2554static void ack_apic_level(unsigned int irq)
2494{ 2555{
2495 struct irq_desc *desc = irq_to_desc(irq); 2556 struct irq_desc *desc = irq_to_desc(irq);
@@ -2525,6 +2586,19 @@ static void ack_apic_level(unsigned int irq)
2525 * level-triggered interrupt. We mask the source for the time of the 2586 * level-triggered interrupt. We mask the source for the time of the
2526 * operation to prevent an edge-triggered interrupt escaping meanwhile. 2587 * operation to prevent an edge-triggered interrupt escaping meanwhile.
2527 * The idea is from Manfred Spraul. --macro 2588 * The idea is from Manfred Spraul. --macro
2589 *
2590 * Also in the case when cpu goes offline, fixup_irqs() will forward
2591 * any unhandled interrupt on the offlined cpu to the new cpu
2592 * destination that is handling the corresponding interrupt. This
2593 * interrupt forwarding is done via IPI's. Hence, in this case also
2594 * level-triggered io-apic interrupt will be seen as an edge
2595 * interrupt in the IRR. And we can't rely on the cpu's EOI
2596 * to be broadcasted to the IO-APIC's which will clear the remoteIRR
2597 * corresponding to the level-triggered interrupt. Hence on IO-APIC's
2598 * supporting EOI register, we do an explicit EOI to clear the
2599 * remote IRR and on IO-APIC's which don't have an EOI register,
2600 * we use the above logic (mask+edge followed by unmask+level) from
2601 * Manfred Spraul to clear the remote IRR.
2528 */ 2602 */
2529 cfg = desc->chip_data; 2603 cfg = desc->chip_data;
2530 i = cfg->vector; 2604 i = cfg->vector;
@@ -2536,6 +2610,19 @@ static void ack_apic_level(unsigned int irq)
2536 */ 2610 */
2537 ack_APIC_irq(); 2611 ack_APIC_irq();
2538 2612
2613 /*
2614 * Tail end of clearing remote IRR bit (either by delivering the EOI
2615 * message via io-apic EOI register write or simulating it using
2616 * mask+edge followed by unnask+level logic) manually when the
2617 * level triggered interrupt is seen as the edge triggered interrupt
2618 * at the cpu.
2619 */
2620 if (!(v & (1 << (i & 0x1f)))) {
2621 atomic_inc(&irq_mis_count);
2622
2623 eoi_ioapic_irq(desc);
2624 }
2625
2539 /* Now we can move and renable the irq */ 2626 /* Now we can move and renable the irq */
2540 if (unlikely(do_unmask_irq)) { 2627 if (unlikely(do_unmask_irq)) {
2541 /* Only migrate the irq if the ack has been received. 2628 /* Only migrate the irq if the ack has been received.
@@ -2569,41 +2656,9 @@ static void ack_apic_level(unsigned int irq)
2569 move_masked_irq(irq); 2656 move_masked_irq(irq);
2570 unmask_IO_APIC_irq_desc(desc); 2657 unmask_IO_APIC_irq_desc(desc);
2571 } 2658 }
2572
2573 /* Tail end of version 0x11 I/O APIC bug workaround */
2574 if (!(v & (1 << (i & 0x1f)))) {
2575 atomic_inc(&irq_mis_count);
2576 spin_lock(&ioapic_lock);
2577 __mask_and_edge_IO_APIC_irq(cfg);
2578 __unmask_and_level_IO_APIC_irq(cfg);
2579 spin_unlock(&ioapic_lock);
2580 }
2581} 2659}
2582 2660
2583#ifdef CONFIG_INTR_REMAP 2661#ifdef CONFIG_INTR_REMAP
2584static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
2585{
2586 struct irq_pin_list *entry;
2587
2588 for_each_irq_pin(entry, cfg->irq_2_pin)
2589 io_apic_eoi(entry->apic, entry->pin);
2590}
2591
2592static void
2593eoi_ioapic_irq(struct irq_desc *desc)
2594{
2595 struct irq_cfg *cfg;
2596 unsigned long flags;
2597 unsigned int irq;
2598
2599 irq = desc->irq;
2600 cfg = desc->chip_data;
2601
2602 spin_lock_irqsave(&ioapic_lock, flags);
2603 __eoi_ioapic_irq(irq, cfg);
2604 spin_unlock_irqrestore(&ioapic_lock, flags);
2605}
2606
2607static void ir_ack_apic_edge(unsigned int irq) 2662static void ir_ack_apic_edge(unsigned int irq)
2608{ 2663{
2609 ack_APIC_irq(); 2664 ack_APIC_irq();
@@ -3157,6 +3212,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node)
3157 continue; 3212 continue;
3158 3213
3159 desc_new = move_irq_desc(desc_new, node); 3214 desc_new = move_irq_desc(desc_new, node);
3215 cfg_new = desc_new->chip_data;
3160 3216
3161 if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) 3217 if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
3162 irq = new; 3218 irq = new;
@@ -3708,75 +3764,6 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
3708} 3764}
3709#endif /* CONFIG_HT_IRQ */ 3765#endif /* CONFIG_HT_IRQ */
3710 3766
3711#ifdef CONFIG_X86_UV
3712/*
3713 * Re-target the irq to the specified CPU and enable the specified MMR located
3714 * on the specified blade to allow the sending of MSIs to the specified CPU.
3715 */
3716int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
3717 unsigned long mmr_offset)
3718{
3719 const struct cpumask *eligible_cpu = cpumask_of(cpu);
3720 struct irq_cfg *cfg;
3721 int mmr_pnode;
3722 unsigned long mmr_value;
3723 struct uv_IO_APIC_route_entry *entry;
3724 unsigned long flags;
3725 int err;
3726
3727 BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
3728
3729 cfg = irq_cfg(irq);
3730
3731 err = assign_irq_vector(irq, cfg, eligible_cpu);
3732 if (err != 0)
3733 return err;
3734
3735 spin_lock_irqsave(&vector_lock, flags);
3736 set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
3737 irq_name);
3738 spin_unlock_irqrestore(&vector_lock, flags);
3739
3740 mmr_value = 0;
3741 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
3742 entry->vector = cfg->vector;
3743 entry->delivery_mode = apic->irq_delivery_mode;
3744 entry->dest_mode = apic->irq_dest_mode;
3745 entry->polarity = 0;
3746 entry->trigger = 0;
3747 entry->mask = 0;
3748 entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
3749
3750 mmr_pnode = uv_blade_to_pnode(mmr_blade);
3751 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
3752
3753 if (cfg->move_in_progress)
3754 send_cleanup_vector(cfg);
3755
3756 return irq;
3757}
3758
3759/*
3760 * Disable the specified MMR located on the specified blade so that MSIs are
3761 * longer allowed to be sent.
3762 */
3763void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
3764{
3765 unsigned long mmr_value;
3766 struct uv_IO_APIC_route_entry *entry;
3767 int mmr_pnode;
3768
3769 BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
3770
3771 mmr_value = 0;
3772 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
3773 entry->mask = 1;
3774
3775 mmr_pnode = uv_blade_to_pnode(mmr_blade);
3776 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
3777}
3778#endif /* CONFIG_X86_64 */
3779
3780int __init io_apic_get_redir_entries (int ioapic) 3767int __init io_apic_get_redir_entries (int ioapic)
3781{ 3768{
3782 union IO_APIC_reg_01 reg_01; 3769 union IO_APIC_reg_01 reg_01;
@@ -3944,7 +3931,7 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
3944 */ 3931 */
3945 3932
3946 if (physids_empty(apic_id_map)) 3933 if (physids_empty(apic_id_map))
3947 apic_id_map = apic->ioapic_phys_id_map(phys_cpu_present_map); 3934 apic->ioapic_phys_id_map(&phys_cpu_present_map, &apic_id_map);
3948 3935
3949 spin_lock_irqsave(&ioapic_lock, flags); 3936 spin_lock_irqsave(&ioapic_lock, flags);
3950 reg_00.raw = io_apic_read(ioapic, 0); 3937 reg_00.raw = io_apic_read(ioapic, 0);
@@ -3960,10 +3947,10 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
3960 * Every APIC in a system must have a unique ID or we get lots of nice 3947 * Every APIC in a system must have a unique ID or we get lots of nice
3961 * 'stuck on smp_invalidate_needed IPI wait' messages. 3948 * 'stuck on smp_invalidate_needed IPI wait' messages.
3962 */ 3949 */
3963 if (apic->check_apicid_used(apic_id_map, apic_id)) { 3950 if (apic->check_apicid_used(&apic_id_map, apic_id)) {
3964 3951
3965 for (i = 0; i < get_physical_broadcast(); i++) { 3952 for (i = 0; i < get_physical_broadcast(); i++) {
3966 if (!apic->check_apicid_used(apic_id_map, i)) 3953 if (!apic->check_apicid_used(&apic_id_map, i))
3967 break; 3954 break;
3968 } 3955 }
3969 3956
@@ -3976,7 +3963,7 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
3976 apic_id = i; 3963 apic_id = i;
3977 } 3964 }
3978 3965
3979 tmp = apic->apicid_to_cpu_present(apic_id); 3966 apic->apicid_to_cpu_present(apic_id, &tmp);
3980 physids_or(apic_id_map, apic_id_map, tmp); 3967 physids_or(apic_id_map, apic_id_map, tmp);
3981 3968
3982 if (reg_00.bits.ID != apic_id) { 3969 if (reg_00.bits.ID != apic_id) {
@@ -4106,7 +4093,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
4106 for (i = 0; i < nr_ioapics; i++) { 4093 for (i = 0; i < nr_ioapics; i++) {
4107 res[i].name = mem; 4094 res[i].name = mem;
4108 res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; 4095 res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
4109 sprintf(mem, "IOAPIC %u", i); 4096 snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
4110 mem += IOAPIC_RESOURCE_NAME_SIZE; 4097 mem += IOAPIC_RESOURCE_NAME_SIZE;
4111 } 4098 }
4112 4099
@@ -4140,18 +4127,17 @@ void __init ioapic_init_mappings(void)
4140#ifdef CONFIG_X86_32 4127#ifdef CONFIG_X86_32
4141fake_ioapic_page: 4128fake_ioapic_page:
4142#endif 4129#endif
4143 ioapic_phys = (unsigned long) 4130 ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
4144 alloc_bootmem_pages(PAGE_SIZE);
4145 ioapic_phys = __pa(ioapic_phys); 4131 ioapic_phys = __pa(ioapic_phys);
4146 } 4132 }
4147 set_fixmap_nocache(idx, ioapic_phys); 4133 set_fixmap_nocache(idx, ioapic_phys);
4148 apic_printk(APIC_VERBOSE, 4134 apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n",
4149 "mapped IOAPIC to %08lx (%08lx)\n", 4135 __fix_to_virt(idx) + (ioapic_phys & ~PAGE_MASK),
4150 __fix_to_virt(idx), ioapic_phys); 4136 ioapic_phys);
4151 idx++; 4137 idx++;
4152 4138
4153 ioapic_res->start = ioapic_phys; 4139 ioapic_res->start = ioapic_phys;
4154 ioapic_res->end = ioapic_phys + (4 * 1024) - 1; 4140 ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
4155 ioapic_res++; 4141 ioapic_res++;
4156 } 4142 }
4157} 4143}
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index 7ff61d6a188a..6389432a9dbf 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -39,7 +39,8 @@
39int unknown_nmi_panic; 39int unknown_nmi_panic;
40int nmi_watchdog_enabled; 40int nmi_watchdog_enabled;
41 41
42static cpumask_t backtrace_mask __read_mostly; 42/* For reliability, we're prepared to waste bits here. */
43static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
43 44
44/* nmi_active: 45/* nmi_active:
45 * >0: the lapic NMI watchdog is active, but can be disabled 46 * >0: the lapic NMI watchdog is active, but can be disabled
@@ -414,7 +415,7 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
414 } 415 }
415 416
416 /* We can be called before check_nmi_watchdog, hence NULL check. */ 417 /* We can be called before check_nmi_watchdog, hence NULL check. */
417 if (cpumask_test_cpu(cpu, &backtrace_mask)) { 418 if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
418 static DEFINE_SPINLOCK(lock); /* Serialise the printks */ 419 static DEFINE_SPINLOCK(lock); /* Serialise the printks */
419 420
420 spin_lock(&lock); 421 spin_lock(&lock);
@@ -422,7 +423,7 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
422 show_regs(regs); 423 show_regs(regs);
423 dump_stack(); 424 dump_stack();
424 spin_unlock(&lock); 425 spin_unlock(&lock);
425 cpumask_clear_cpu(cpu, &backtrace_mask); 426 cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
426 427
427 rc = 1; 428 rc = 1;
428 } 429 }
@@ -558,14 +559,14 @@ void arch_trigger_all_cpu_backtrace(void)
558{ 559{
559 int i; 560 int i;
560 561
561 cpumask_copy(&backtrace_mask, cpu_online_mask); 562 cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask);
562 563
563 printk(KERN_INFO "sending NMI to all CPUs:\n"); 564 printk(KERN_INFO "sending NMI to all CPUs:\n");
564 apic->send_IPI_all(NMI_VECTOR); 565 apic->send_IPI_all(NMI_VECTOR);
565 566
566 /* Wait for up to 10 seconds for all CPUs to do the backtrace */ 567 /* Wait for up to 10 seconds for all CPUs to do the backtrace */
567 for (i = 0; i < 10 * 1000; i++) { 568 for (i = 0; i < 10 * 1000; i++) {
568 if (cpumask_empty(&backtrace_mask)) 569 if (cpumask_empty(to_cpumask(backtrace_mask)))
569 break; 570 break;
570 mdelay(1); 571 mdelay(1);
571 } 572 }
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index efa00e2b8505..07cdbdcd7a92 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -334,10 +334,9 @@ static inline const struct cpumask *numaq_target_cpus(void)
334 return cpu_all_mask; 334 return cpu_all_mask;
335} 335}
336 336
337static inline unsigned long 337static unsigned long numaq_check_apicid_used(physid_mask_t *map, int apicid)
338numaq_check_apicid_used(physid_mask_t bitmap, int apicid)
339{ 338{
340 return physid_isset(apicid, bitmap); 339 return physid_isset(apicid, *map);
341} 340}
342 341
343static inline unsigned long numaq_check_apicid_present(int bit) 342static inline unsigned long numaq_check_apicid_present(int bit)
@@ -371,10 +370,10 @@ static inline int numaq_multi_timer_check(int apic, int irq)
371 return apic != 0 && irq == 0; 370 return apic != 0 && irq == 0;
372} 371}
373 372
374static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) 373static inline void numaq_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
375{ 374{
376 /* We don't have a good way to do this yet - hack */ 375 /* We don't have a good way to do this yet - hack */
377 return physids_promote(0xFUL); 376 return physids_promote(0xFUL, retmap);
378} 377}
379 378
380static inline int numaq_cpu_to_logical_apicid(int cpu) 379static inline int numaq_cpu_to_logical_apicid(int cpu)
@@ -402,12 +401,12 @@ static inline int numaq_apicid_to_node(int logical_apicid)
402 return logical_apicid >> 4; 401 return logical_apicid >> 4;
403} 402}
404 403
405static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) 404static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap)
406{ 405{
407 int node = numaq_apicid_to_node(logical_apicid); 406 int node = numaq_apicid_to_node(logical_apicid);
408 int cpu = __ffs(logical_apicid & 0xf); 407 int cpu = __ffs(logical_apicid & 0xf);
409 408
410 return physid_mask_of_physid(cpu + 4*node); 409 physid_set_mask_of_physid(cpu + 4*node, retmap);
411} 410}
412 411
413/* Where the IO area was mapped on multiquad, always 0 otherwise */ 412/* Where the IO area was mapped on multiquad, always 0 otherwise */
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 0c0182cc947d..1a6559f6768c 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -108,7 +108,7 @@ struct apic apic_default = {
108 .apicid_to_node = default_apicid_to_node, 108 .apicid_to_node = default_apicid_to_node,
109 .cpu_to_logical_apicid = default_cpu_to_logical_apicid, 109 .cpu_to_logical_apicid = default_cpu_to_logical_apicid,
110 .cpu_present_to_apicid = default_cpu_present_to_apicid, 110 .cpu_present_to_apicid = default_cpu_present_to_apicid,
111 .apicid_to_cpu_present = default_apicid_to_cpu_present, 111 .apicid_to_cpu_present = physid_set_mask_of_physid,
112 .setup_portio_remap = NULL, 112 .setup_portio_remap = NULL,
113 .check_phys_apicid_present = default_check_phys_apicid_present, 113 .check_phys_apicid_present = default_check_phys_apicid_present,
114 .enable_apic_mode = NULL, 114 .enable_apic_mode = NULL,
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index 645ecc4ff0be..9b419263d90d 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -183,7 +183,7 @@ static const struct cpumask *summit_target_cpus(void)
183 return cpumask_of(0); 183 return cpumask_of(0);
184} 184}
185 185
186static unsigned long summit_check_apicid_used(physid_mask_t bitmap, int apicid) 186static unsigned long summit_check_apicid_used(physid_mask_t *map, int apicid)
187{ 187{
188 return 0; 188 return 0;
189} 189}
@@ -261,15 +261,15 @@ static int summit_cpu_present_to_apicid(int mps_cpu)
261 return BAD_APICID; 261 return BAD_APICID;
262} 262}
263 263
264static physid_mask_t summit_ioapic_phys_id_map(physid_mask_t phys_id_map) 264static void summit_ioapic_phys_id_map(physid_mask_t *phys_id_map, physid_mask_t *retmap)
265{ 265{
266 /* For clustered we don't have a good way to do this yet - hack */ 266 /* For clustered we don't have a good way to do this yet - hack */
267 return physids_promote(0x0F); 267 physids_promote(0x0FL, retmap);
268} 268}
269 269
270static physid_mask_t summit_apicid_to_cpu_present(int apicid) 270static void summit_apicid_to_cpu_present(int apicid, physid_mask_t *retmap)
271{ 271{
272 return physid_mask_of_physid(0); 272 physid_set_mask_of_physid(0, retmap);
273} 273}
274 274
275static int summit_check_phys_apicid_present(int physical_apicid) 275static int summit_check_phys_apicid_present(int physical_apicid)
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 326c25477d3d..130c4b934877 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -409,6 +409,12 @@ static __init void map_mmioh_high(int max_pnode)
409 map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc); 409 map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc);
410} 410}
411 411
412static __init void map_low_mmrs(void)
413{
414 init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE);
415 init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE);
416}
417
412static __init void uv_rtc_init(void) 418static __init void uv_rtc_init(void)
413{ 419{
414 long status; 420 long status;
@@ -550,6 +556,8 @@ void __init uv_system_init(void)
550 unsigned long mmr_base, present, paddr; 556 unsigned long mmr_base, present, paddr;
551 unsigned short pnode_mask; 557 unsigned short pnode_mask;
552 558
559 map_low_mmrs();
560
553 m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG); 561 m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
554 m_val = m_n_config.s.m_skt; 562 m_val = m_n_config.s.m_skt;
555 n_val = m_n_config.s.n_skt; 563 n_val = m_n_config.s.n_skt;
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 151ace69a5aa..b5b6b23bce53 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -204,7 +204,6 @@
204#include <linux/module.h> 204#include <linux/module.h>
205 205
206#include <linux/poll.h> 206#include <linux/poll.h>
207#include <linux/smp_lock.h>
208#include <linux/types.h> 207#include <linux/types.h>
209#include <linux/stddef.h> 208#include <linux/stddef.h>
210#include <linux/timer.h> 209#include <linux/timer.h>
@@ -403,6 +402,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
403static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); 402static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
404static struct apm_user *user_list; 403static struct apm_user *user_list;
405static DEFINE_SPINLOCK(user_list_lock); 404static DEFINE_SPINLOCK(user_list_lock);
405static DEFINE_MUTEX(apm_mutex);
406 406
407/* 407/*
408 * Set up a segment that references the real mode segment 0x40 408 * Set up a segment that references the real mode segment 0x40
@@ -1531,7 +1531,7 @@ static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1531 return -EPERM; 1531 return -EPERM;
1532 switch (cmd) { 1532 switch (cmd) {
1533 case APM_IOC_STANDBY: 1533 case APM_IOC_STANDBY:
1534 lock_kernel(); 1534 mutex_lock(&apm_mutex);
1535 if (as->standbys_read > 0) { 1535 if (as->standbys_read > 0) {
1536 as->standbys_read--; 1536 as->standbys_read--;
1537 as->standbys_pending--; 1537 as->standbys_pending--;
@@ -1540,10 +1540,10 @@ static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1540 queue_event(APM_USER_STANDBY, as); 1540 queue_event(APM_USER_STANDBY, as);
1541 if (standbys_pending <= 0) 1541 if (standbys_pending <= 0)
1542 standby(); 1542 standby();
1543 unlock_kernel(); 1543 mutex_unlock(&apm_mutex);
1544 break; 1544 break;
1545 case APM_IOC_SUSPEND: 1545 case APM_IOC_SUSPEND:
1546 lock_kernel(); 1546 mutex_lock(&apm_mutex);
1547 if (as->suspends_read > 0) { 1547 if (as->suspends_read > 0) {
1548 as->suspends_read--; 1548 as->suspends_read--;
1549 as->suspends_pending--; 1549 as->suspends_pending--;
@@ -1552,13 +1552,14 @@ static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1552 queue_event(APM_USER_SUSPEND, as); 1552 queue_event(APM_USER_SUSPEND, as);
1553 if (suspends_pending <= 0) { 1553 if (suspends_pending <= 0) {
1554 ret = suspend(1); 1554 ret = suspend(1);
1555 mutex_unlock(&apm_mutex);
1555 } else { 1556 } else {
1556 as->suspend_wait = 1; 1557 as->suspend_wait = 1;
1558 mutex_unlock(&apm_mutex);
1557 wait_event_interruptible(apm_suspend_waitqueue, 1559 wait_event_interruptible(apm_suspend_waitqueue,
1558 as->suspend_wait == 0); 1560 as->suspend_wait == 0);
1559 ret = as->suspend_result; 1561 ret = as->suspend_result;
1560 } 1562 }
1561 unlock_kernel();
1562 return ret; 1563 return ret;
1563 default: 1564 default:
1564 return -ENOTTY; 1565 return -ENOTTY;
@@ -1608,12 +1609,10 @@ static int do_open(struct inode *inode, struct file *filp)
1608{ 1609{
1609 struct apm_user *as; 1610 struct apm_user *as;
1610 1611
1611 lock_kernel();
1612 as = kmalloc(sizeof(*as), GFP_KERNEL); 1612 as = kmalloc(sizeof(*as), GFP_KERNEL);
1613 if (as == NULL) { 1613 if (as == NULL) {
1614 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", 1614 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
1615 sizeof(*as)); 1615 sizeof(*as));
1616 unlock_kernel();
1617 return -ENOMEM; 1616 return -ENOMEM;
1618 } 1617 }
1619 as->magic = APM_BIOS_MAGIC; 1618 as->magic = APM_BIOS_MAGIC;
@@ -1635,7 +1634,6 @@ static int do_open(struct inode *inode, struct file *filp)
1635 user_list = as; 1634 user_list = as;
1636 spin_unlock(&user_list_lock); 1635 spin_unlock(&user_list_lock);
1637 filp->private_data = as; 1636 filp->private_data = as;
1638 unlock_kernel();
1639 return 0; 1637 return 0;
1640} 1638}
1641 1639
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 68537e957a9b..1d2cb383410e 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -5,6 +5,7 @@
5# Don't trace early stages of a secondary CPU boot 5# Don't trace early stages of a secondary CPU boot
6ifdef CONFIG_FUNCTION_TRACER 6ifdef CONFIG_FUNCTION_TRACER
7CFLAGS_REMOVE_common.o = -pg 7CFLAGS_REMOVE_common.o = -pg
8CFLAGS_REMOVE_perf_event.o = -pg
8endif 9endif
9 10
10# Make sure load_percpu_segment has no stackprotector 11# Make sure load_percpu_segment has no stackprotector
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c910a716a71c..7128b3799cec 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -535,7 +535,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
535 } 535 }
536 } 536 }
537 537
538 display_cacheinfo(c); 538 cpu_detect_cache_sizes(c);
539 539
540 /* Multi core CPU? */ 540 /* Multi core CPU? */
541 if (c->extended_cpuid_level >= 0x80000008) { 541 if (c->extended_cpuid_level >= 0x80000008) {
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index c95e831bb095..e58d978e0758 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -294,7 +294,7 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
294 set_cpu_cap(c, X86_FEATURE_REP_GOOD); 294 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
295 } 295 }
296 296
297 display_cacheinfo(c); 297 cpu_detect_cache_sizes(c);
298} 298}
299 299
300enum { 300enum {
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cc25c2b4a567..a4ec8b647544 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -61,7 +61,7 @@ void __init setup_cpu_local_masks(void)
61static void __cpuinit default_init(struct cpuinfo_x86 *c) 61static void __cpuinit default_init(struct cpuinfo_x86 *c)
62{ 62{
63#ifdef CONFIG_X86_64 63#ifdef CONFIG_X86_64
64 display_cacheinfo(c); 64 cpu_detect_cache_sizes(c);
65#else 65#else
66 /* Not much we can do here... */ 66 /* Not much we can do here... */
67 /* Check if at least it has cpuid */ 67 /* Check if at least it has cpuid */
@@ -383,7 +383,7 @@ static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
383 } 383 }
384} 384}
385 385
386void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) 386void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c)
387{ 387{
388 unsigned int n, dummy, ebx, ecx, edx, l2size; 388 unsigned int n, dummy, ebx, ecx, edx, l2size;
389 389
@@ -391,8 +391,6 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
391 391
392 if (n >= 0x80000005) { 392 if (n >= 0x80000005) {
393 cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); 393 cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
394 printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
395 edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
396 c->x86_cache_size = (ecx>>24) + (edx>>24); 394 c->x86_cache_size = (ecx>>24) + (edx>>24);
397#ifdef CONFIG_X86_64 395#ifdef CONFIG_X86_64
398 /* On K8 L1 TLB is inclusive, so don't count it */ 396 /* On K8 L1 TLB is inclusive, so don't count it */
@@ -422,9 +420,6 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
422#endif 420#endif
423 421
424 c->x86_cache_size = l2size; 422 c->x86_cache_size = l2size;
425
426 printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
427 l2size, ecx & 0xFF);
428} 423}
429 424
430void __cpuinit detect_ht(struct cpuinfo_x86 *c) 425void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -659,24 +654,31 @@ void __init early_cpu_init(void)
659 const struct cpu_dev *const *cdev; 654 const struct cpu_dev *const *cdev;
660 int count = 0; 655 int count = 0;
661 656
657#ifdef PROCESSOR_SELECT
662 printk(KERN_INFO "KERNEL supported cpus:\n"); 658 printk(KERN_INFO "KERNEL supported cpus:\n");
659#endif
660
663 for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { 661 for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
664 const struct cpu_dev *cpudev = *cdev; 662 const struct cpu_dev *cpudev = *cdev;
665 unsigned int j;
666 663
667 if (count >= X86_VENDOR_NUM) 664 if (count >= X86_VENDOR_NUM)
668 break; 665 break;
669 cpu_devs[count] = cpudev; 666 cpu_devs[count] = cpudev;
670 count++; 667 count++;
671 668
672 for (j = 0; j < 2; j++) { 669#ifdef PROCESSOR_SELECT
673 if (!cpudev->c_ident[j]) 670 {
674 continue; 671 unsigned int j;
675 printk(KERN_INFO " %s %s\n", cpudev->c_vendor, 672
676 cpudev->c_ident[j]); 673 for (j = 0; j < 2; j++) {
674 if (!cpudev->c_ident[j])
675 continue;
676 printk(KERN_INFO " %s %s\n", cpudev->c_vendor,
677 cpudev->c_ident[j]);
678 }
677 } 679 }
680#endif
678 } 681 }
679
680 early_identify_cpu(&boot_cpu_data); 682 early_identify_cpu(&boot_cpu_data);
681} 683}
682 684
@@ -837,10 +839,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
837 boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; 839 boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
838 } 840 }
839 841
840#ifdef CONFIG_X86_MCE
841 /* Init Machine Check Exception if available. */ 842 /* Init Machine Check Exception if available. */
842 mcheck_init(c); 843 mcheck_cpu_init(c);
843#endif
844 844
845 select_idle_routine(c); 845 select_idle_routine(c);
846 846
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 6de9a908e400..3624e8a0f71b 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -32,6 +32,6 @@ struct cpu_dev {
32extern const struct cpu_dev *const __x86_cpu_dev_start[], 32extern const struct cpu_dev *const __x86_cpu_dev_start[],
33 *const __x86_cpu_dev_end[]; 33 *const __x86_cpu_dev_end[];
34 34
35extern void display_cacheinfo(struct cpuinfo_x86 *c); 35extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
36 36
37#endif 37#endif
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index 19807b89f058..4fbd384fb645 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -373,7 +373,7 @@ static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
373 /* Handle the GX (Formally known as the GX2) */ 373 /* Handle the GX (Formally known as the GX2) */
374 374
375 if (c->x86 == 5 && c->x86_model == 5) 375 if (c->x86 == 5 && c->x86_model == 5)
376 display_cacheinfo(c); 376 cpu_detect_cache_sizes(c);
377 else 377 else
378 init_cyrix(c); 378 init_cyrix(c);
379} 379}
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 804c40e2bc3e..0df4c2b7107f 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -488,22 +488,6 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
488#endif 488#endif
489 } 489 }
490 490
491 if (trace)
492 printk(KERN_INFO "CPU: Trace cache: %dK uops", trace);
493 else if (l1i)
494 printk(KERN_INFO "CPU: L1 I cache: %dK", l1i);
495
496 if (l1d)
497 printk(KERN_CONT ", L1 D cache: %dK\n", l1d);
498 else
499 printk(KERN_CONT "\n");
500
501 if (l2)
502 printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
503
504 if (l3)
505 printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
506
507 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d)); 491 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
508 492
509 return l2; 493 return l2;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 721a77ca8115..0bcaa3875863 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -46,6 +46,9 @@
46 46
47#include "mce-internal.h" 47#include "mce-internal.h"
48 48
49#define CREATE_TRACE_POINTS
50#include <trace/events/mce.h>
51
49int mce_disabled __read_mostly; 52int mce_disabled __read_mostly;
50 53
51#define MISC_MCELOG_MINOR 227 54#define MISC_MCELOG_MINOR 227
@@ -85,18 +88,26 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
85static DEFINE_PER_CPU(struct mce, mces_seen); 88static DEFINE_PER_CPU(struct mce, mces_seen);
86static int cpu_missing; 89static int cpu_missing;
87 90
88static void default_decode_mce(struct mce *m) 91/*
92 * CPU/chipset specific EDAC code can register a notifier call here to print
93 * MCE errors in a human-readable form.
94 */
95ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain);
96EXPORT_SYMBOL_GPL(x86_mce_decoder_chain);
97
98static int default_decode_mce(struct notifier_block *nb, unsigned long val,
99 void *data)
89{ 100{
90 pr_emerg("No human readable MCE decoding support on this CPU type.\n"); 101 pr_emerg("No human readable MCE decoding support on this CPU type.\n");
91 pr_emerg("Run the message through 'mcelog --ascii' to decode.\n"); 102 pr_emerg("Run the message through 'mcelog --ascii' to decode.\n");
103
104 return NOTIFY_STOP;
92} 105}
93 106
94/* 107static struct notifier_block mce_dec_nb = {
95 * CPU/chipset specific EDAC code can register a callback here to print 108 .notifier_call = default_decode_mce,
96 * MCE errors in a human-readable form: 109 .priority = -1,
97 */ 110};
98void (*x86_mce_decode_callback)(struct mce *m) = default_decode_mce;
99EXPORT_SYMBOL(x86_mce_decode_callback);
100 111
101/* MCA banks polled by the period polling timer for corrected events */ 112/* MCA banks polled by the period polling timer for corrected events */
102DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { 113DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
@@ -141,6 +152,9 @@ void mce_log(struct mce *mce)
141{ 152{
142 unsigned next, entry; 153 unsigned next, entry;
143 154
155 /* Emit the trace record: */
156 trace_mce_record(mce);
157
144 mce->finished = 0; 158 mce->finished = 0;
145 wmb(); 159 wmb();
146 for (;;) { 160 for (;;) {
@@ -204,9 +218,9 @@ static void print_mce(struct mce *m)
204 218
205 /* 219 /*
206 * Print out human-readable details about the MCE error, 220 * Print out human-readable details about the MCE error,
207 * (if the CPU has an implementation for that): 221 * (if the CPU has an implementation for that)
208 */ 222 */
209 x86_mce_decode_callback(m); 223 atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
210} 224}
211 225
212static void print_mce_head(void) 226static void print_mce_head(void)
@@ -1122,7 +1136,7 @@ static int check_interval = 5 * 60; /* 5 minutes */
1122static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */ 1136static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */
1123static DEFINE_PER_CPU(struct timer_list, mce_timer); 1137static DEFINE_PER_CPU(struct timer_list, mce_timer);
1124 1138
1125static void mcheck_timer(unsigned long data) 1139static void mce_start_timer(unsigned long data)
1126{ 1140{
1127 struct timer_list *t = &per_cpu(mce_timer, data); 1141 struct timer_list *t = &per_cpu(mce_timer, data);
1128 int *n; 1142 int *n;
@@ -1187,7 +1201,7 @@ int mce_notify_irq(void)
1187} 1201}
1188EXPORT_SYMBOL_GPL(mce_notify_irq); 1202EXPORT_SYMBOL_GPL(mce_notify_irq);
1189 1203
1190static int mce_banks_init(void) 1204static int __cpuinit __mcheck_cpu_mce_banks_init(void)
1191{ 1205{
1192 int i; 1206 int i;
1193 1207
@@ -1206,7 +1220,7 @@ static int mce_banks_init(void)
1206/* 1220/*
1207 * Initialize Machine Checks for a CPU. 1221 * Initialize Machine Checks for a CPU.
1208 */ 1222 */
1209static int __cpuinit mce_cap_init(void) 1223static int __cpuinit __mcheck_cpu_cap_init(void)
1210{ 1224{
1211 unsigned b; 1225 unsigned b;
1212 u64 cap; 1226 u64 cap;
@@ -1228,7 +1242,7 @@ static int __cpuinit mce_cap_init(void)
1228 WARN_ON(banks != 0 && b != banks); 1242 WARN_ON(banks != 0 && b != banks);
1229 banks = b; 1243 banks = b;
1230 if (!mce_banks) { 1244 if (!mce_banks) {
1231 int err = mce_banks_init(); 1245 int err = __mcheck_cpu_mce_banks_init();
1232 1246
1233 if (err) 1247 if (err)
1234 return err; 1248 return err;
@@ -1244,7 +1258,7 @@ static int __cpuinit mce_cap_init(void)
1244 return 0; 1258 return 0;
1245} 1259}
1246 1260
1247static void mce_init(void) 1261static void __mcheck_cpu_init_generic(void)
1248{ 1262{
1249 mce_banks_t all_banks; 1263 mce_banks_t all_banks;
1250 u64 cap; 1264 u64 cap;
@@ -1273,7 +1287,7 @@ static void mce_init(void)
1273} 1287}
1274 1288
1275/* Add per CPU specific workarounds here */ 1289/* Add per CPU specific workarounds here */
1276static int __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c) 1290static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
1277{ 1291{
1278 if (c->x86_vendor == X86_VENDOR_UNKNOWN) { 1292 if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
1279 pr_info("MCE: unknown CPU type - not enabling MCE support.\n"); 1293 pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
@@ -1341,7 +1355,7 @@ static int __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
1341 return 0; 1355 return 0;
1342} 1356}
1343 1357
1344static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c) 1358static void __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
1345{ 1359{
1346 if (c->x86 != 5) 1360 if (c->x86 != 5)
1347 return; 1361 return;
@@ -1355,7 +1369,7 @@ static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
1355 } 1369 }
1356} 1370}
1357 1371
1358static void mce_cpu_features(struct cpuinfo_x86 *c) 1372static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
1359{ 1373{
1360 switch (c->x86_vendor) { 1374 switch (c->x86_vendor) {
1361 case X86_VENDOR_INTEL: 1375 case X86_VENDOR_INTEL:
@@ -1369,7 +1383,7 @@ static void mce_cpu_features(struct cpuinfo_x86 *c)
1369 } 1383 }
1370} 1384}
1371 1385
1372static void mce_init_timer(void) 1386static void __mcheck_cpu_init_timer(void)
1373{ 1387{
1374 struct timer_list *t = &__get_cpu_var(mce_timer); 1388 struct timer_list *t = &__get_cpu_var(mce_timer);
1375 int *n = &__get_cpu_var(mce_next_interval); 1389 int *n = &__get_cpu_var(mce_next_interval);
@@ -1380,7 +1394,7 @@ static void mce_init_timer(void)
1380 *n = check_interval * HZ; 1394 *n = check_interval * HZ;
1381 if (!*n) 1395 if (!*n)
1382 return; 1396 return;
1383 setup_timer(t, mcheck_timer, smp_processor_id()); 1397 setup_timer(t, mce_start_timer, smp_processor_id());
1384 t->expires = round_jiffies(jiffies + *n); 1398 t->expires = round_jiffies(jiffies + *n);
1385 add_timer_on(t, smp_processor_id()); 1399 add_timer_on(t, smp_processor_id());
1386} 1400}
@@ -1400,27 +1414,28 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) =
1400 * Called for each booted CPU to set up machine checks. 1414 * Called for each booted CPU to set up machine checks.
1401 * Must be called with preempt off: 1415 * Must be called with preempt off:
1402 */ 1416 */
1403void __cpuinit mcheck_init(struct cpuinfo_x86 *c) 1417void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
1404{ 1418{
1405 if (mce_disabled) 1419 if (mce_disabled)
1406 return; 1420 return;
1407 1421
1408 mce_ancient_init(c); 1422 __mcheck_cpu_ancient_init(c);
1409 1423
1410 if (!mce_available(c)) 1424 if (!mce_available(c))
1411 return; 1425 return;
1412 1426
1413 if (mce_cap_init() < 0 || mce_cpu_quirks(c) < 0) { 1427 if (__mcheck_cpu_cap_init() < 0 || __mcheck_cpu_apply_quirks(c) < 0) {
1414 mce_disabled = 1; 1428 mce_disabled = 1;
1415 return; 1429 return;
1416 } 1430 }
1417 1431
1418 machine_check_vector = do_machine_check; 1432 machine_check_vector = do_machine_check;
1419 1433
1420 mce_init(); 1434 __mcheck_cpu_init_generic();
1421 mce_cpu_features(c); 1435 __mcheck_cpu_init_vendor(c);
1422 mce_init_timer(); 1436 __mcheck_cpu_init_timer();
1423 INIT_WORK(&__get_cpu_var(mce_work), mce_process_work); 1437 INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
1438
1424} 1439}
1425 1440
1426/* 1441/*
@@ -1640,6 +1655,15 @@ static int __init mcheck_enable(char *str)
1640} 1655}
1641__setup("mce", mcheck_enable); 1656__setup("mce", mcheck_enable);
1642 1657
1658int __init mcheck_init(void)
1659{
1660 atomic_notifier_chain_register(&x86_mce_decoder_chain, &mce_dec_nb);
1661
1662 mcheck_intel_therm_init();
1663
1664 return 0;
1665}
1666
1643/* 1667/*
1644 * Sysfs support 1668 * Sysfs support
1645 */ 1669 */
@@ -1648,7 +1672,7 @@ __setup("mce", mcheck_enable);
1648 * Disable machine checks on suspend and shutdown. We can't really handle 1672 * Disable machine checks on suspend and shutdown. We can't really handle
1649 * them later. 1673 * them later.
1650 */ 1674 */
1651static int mce_disable(void) 1675static int mce_disable_error_reporting(void)
1652{ 1676{
1653 int i; 1677 int i;
1654 1678
@@ -1663,12 +1687,12 @@ static int mce_disable(void)
1663 1687
1664static int mce_suspend(struct sys_device *dev, pm_message_t state) 1688static int mce_suspend(struct sys_device *dev, pm_message_t state)
1665{ 1689{
1666 return mce_disable(); 1690 return mce_disable_error_reporting();
1667} 1691}
1668 1692
1669static int mce_shutdown(struct sys_device *dev) 1693static int mce_shutdown(struct sys_device *dev)
1670{ 1694{
1671 return mce_disable(); 1695 return mce_disable_error_reporting();
1672} 1696}
1673 1697
1674/* 1698/*
@@ -1678,8 +1702,8 @@ static int mce_shutdown(struct sys_device *dev)
1678 */ 1702 */
1679static int mce_resume(struct sys_device *dev) 1703static int mce_resume(struct sys_device *dev)
1680{ 1704{
1681 mce_init(); 1705 __mcheck_cpu_init_generic();
1682 mce_cpu_features(&current_cpu_data); 1706 __mcheck_cpu_init_vendor(&current_cpu_data);
1683 1707
1684 return 0; 1708 return 0;
1685} 1709}
@@ -1689,8 +1713,8 @@ static void mce_cpu_restart(void *data)
1689 del_timer_sync(&__get_cpu_var(mce_timer)); 1713 del_timer_sync(&__get_cpu_var(mce_timer));
1690 if (!mce_available(&current_cpu_data)) 1714 if (!mce_available(&current_cpu_data))
1691 return; 1715 return;
1692 mce_init(); 1716 __mcheck_cpu_init_generic();
1693 mce_init_timer(); 1717 __mcheck_cpu_init_timer();
1694} 1718}
1695 1719
1696/* Reinit MCEs after user configuration changes */ 1720/* Reinit MCEs after user configuration changes */
@@ -1716,7 +1740,7 @@ static void mce_enable_ce(void *all)
1716 cmci_reenable(); 1740 cmci_reenable();
1717 cmci_recheck(); 1741 cmci_recheck();
1718 if (all) 1742 if (all)
1719 mce_init_timer(); 1743 __mcheck_cpu_init_timer();
1720} 1744}
1721 1745
1722static struct sysdev_class mce_sysclass = { 1746static struct sysdev_class mce_sysclass = {
@@ -1929,13 +1953,14 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
1929} 1953}
1930 1954
1931/* Make sure there are no machine checks on offlined CPUs. */ 1955/* Make sure there are no machine checks on offlined CPUs. */
1932static void mce_disable_cpu(void *h) 1956static void __cpuinit mce_disable_cpu(void *h)
1933{ 1957{
1934 unsigned long action = *(unsigned long *)h; 1958 unsigned long action = *(unsigned long *)h;
1935 int i; 1959 int i;
1936 1960
1937 if (!mce_available(&current_cpu_data)) 1961 if (!mce_available(&current_cpu_data))
1938 return; 1962 return;
1963
1939 if (!(action & CPU_TASKS_FROZEN)) 1964 if (!(action & CPU_TASKS_FROZEN))
1940 cmci_clear(); 1965 cmci_clear();
1941 for (i = 0; i < banks; i++) { 1966 for (i = 0; i < banks; i++) {
@@ -1946,7 +1971,7 @@ static void mce_disable_cpu(void *h)
1946 } 1971 }
1947} 1972}
1948 1973
1949static void mce_reenable_cpu(void *h) 1974static void __cpuinit mce_reenable_cpu(void *h)
1950{ 1975{
1951 unsigned long action = *(unsigned long *)h; 1976 unsigned long action = *(unsigned long *)h;
1952 int i; 1977 int i;
@@ -2025,7 +2050,7 @@ static __init void mce_init_banks(void)
2025 } 2050 }
2026} 2051}
2027 2052
2028static __init int mce_init_device(void) 2053static __init int mcheck_init_device(void)
2029{ 2054{
2030 int err; 2055 int err;
2031 int i = 0; 2056 int i = 0;
@@ -2053,7 +2078,7 @@ static __init int mce_init_device(void)
2053 return err; 2078 return err;
2054} 2079}
2055 2080
2056device_initcall(mce_init_device); 2081device_initcall(mcheck_init_device);
2057 2082
2058/* 2083/*
2059 * Old style boot options parsing. Only for compatibility. 2084 * Old style boot options parsing. Only for compatibility.
@@ -2101,7 +2126,7 @@ static int fake_panic_set(void *data, u64 val)
2101DEFINE_SIMPLE_ATTRIBUTE(fake_panic_fops, fake_panic_get, 2126DEFINE_SIMPLE_ATTRIBUTE(fake_panic_fops, fake_panic_get,
2102 fake_panic_set, "%llu\n"); 2127 fake_panic_set, "%llu\n");
2103 2128
2104static int __init mce_debugfs_init(void) 2129static int __init mcheck_debugfs_init(void)
2105{ 2130{
2106 struct dentry *dmce, *ffake_panic; 2131 struct dentry *dmce, *ffake_panic;
2107 2132
@@ -2115,5 +2140,5 @@ static int __init mce_debugfs_init(void)
2115 2140
2116 return 0; 2141 return 0;
2117} 2142}
2118late_initcall(mce_debugfs_init); 2143late_initcall(mcheck_debugfs_init);
2119#endif 2144#endif
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index b3a1dba75330..4fef985fc221 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -49,6 +49,8 @@ static DEFINE_PER_CPU(struct thermal_state, thermal_state);
49 49
50static atomic_t therm_throt_en = ATOMIC_INIT(0); 50static atomic_t therm_throt_en = ATOMIC_INIT(0);
51 51
52static u32 lvtthmr_init __read_mostly;
53
52#ifdef CONFIG_SYSFS 54#ifdef CONFIG_SYSFS
53#define define_therm_throt_sysdev_one_ro(_name) \ 55#define define_therm_throt_sysdev_one_ro(_name) \
54 static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) 56 static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
@@ -254,6 +256,18 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
254 ack_APIC_irq(); 256 ack_APIC_irq();
255} 257}
256 258
259void __init mcheck_intel_therm_init(void)
260{
261 /*
262 * This function is only called on boot CPU. Save the init thermal
263 * LVT value on BSP and use that value to restore APs' thermal LVT
264 * entry BIOS programmed later
265 */
266 if (cpu_has(&boot_cpu_data, X86_FEATURE_ACPI) &&
267 cpu_has(&boot_cpu_data, X86_FEATURE_ACC))
268 lvtthmr_init = apic_read(APIC_LVTTHMR);
269}
270
257void intel_init_thermal(struct cpuinfo_x86 *c) 271void intel_init_thermal(struct cpuinfo_x86 *c)
258{ 272{
259 unsigned int cpu = smp_processor_id(); 273 unsigned int cpu = smp_processor_id();
@@ -270,7 +284,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
270 * since it might be delivered via SMI already: 284 * since it might be delivered via SMI already:
271 */ 285 */
272 rdmsr(MSR_IA32_MISC_ENABLE, l, h); 286 rdmsr(MSR_IA32_MISC_ENABLE, l, h);
273 h = apic_read(APIC_LVTTHMR); 287
288 /*
289 * The initial value of thermal LVT entries on all APs always reads
290 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
291 * sequence to them and LVT registers are reset to 0s except for
292 * the mask bits which are set to 1s when APs receive INIT IPI.
293 * Always restore the value that BIOS has programmed on AP based on
294 * BSP's info we saved since BIOS is always setting the same value
295 * for all threads/cores
296 */
297 apic_write(APIC_LVTTHMR, lvtthmr_init);
298
299 h = lvtthmr_init;
300
274 if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { 301 if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
275 printk(KERN_DEBUG 302 printk(KERN_DEBUG
276 "CPU%d: Thermal monitoring handled by SMI\n", cpu); 303 "CPU%d: Thermal monitoring handled by SMI\n", cpu);
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index b5801c311846..c1bbed1021d9 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -77,6 +77,18 @@ struct cpu_hw_events {
77 struct debug_store *ds; 77 struct debug_store *ds;
78}; 78};
79 79
80struct event_constraint {
81 unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
82 int code;
83};
84
85#define EVENT_CONSTRAINT(c, m) { .code = (c), .idxmsk[0] = (m) }
86#define EVENT_CONSTRAINT_END { .code = 0, .idxmsk[0] = 0 }
87
88#define for_each_event_constraint(e, c) \
89 for ((e) = (c); (e)->idxmsk[0]; (e)++)
90
91
80/* 92/*
81 * struct x86_pmu - generic x86 pmu 93 * struct x86_pmu - generic x86 pmu
82 */ 94 */
@@ -102,6 +114,8 @@ struct x86_pmu {
102 u64 intel_ctrl; 114 u64 intel_ctrl;
103 void (*enable_bts)(u64 config); 115 void (*enable_bts)(u64 config);
104 void (*disable_bts)(void); 116 void (*disable_bts)(void);
117 int (*get_event_idx)(struct cpu_hw_events *cpuc,
118 struct hw_perf_event *hwc);
105}; 119};
106 120
107static struct x86_pmu x86_pmu __read_mostly; 121static struct x86_pmu x86_pmu __read_mostly;
@@ -110,6 +124,8 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
110 .enabled = 1, 124 .enabled = 1,
111}; 125};
112 126
127static const struct event_constraint *event_constraints;
128
113/* 129/*
114 * Not sure about some of these 130 * Not sure about some of these
115 */ 131 */
@@ -155,6 +171,16 @@ static u64 p6_pmu_raw_event(u64 hw_event)
155 return hw_event & P6_EVNTSEL_MASK; 171 return hw_event & P6_EVNTSEL_MASK;
156} 172}
157 173
174static const struct event_constraint intel_p6_event_constraints[] =
175{
176 EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */
177 EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
178 EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */
179 EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
180 EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
181 EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
182 EVENT_CONSTRAINT_END
183};
158 184
159/* 185/*
160 * Intel PerfMon v3. Used on Core2 and later. 186 * Intel PerfMon v3. Used on Core2 and later.
@@ -170,6 +196,35 @@ static const u64 intel_perfmon_event_map[] =
170 [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, 196 [PERF_COUNT_HW_BUS_CYCLES] = 0x013c,
171}; 197};
172 198
199static const struct event_constraint intel_core_event_constraints[] =
200{
201 EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
202 EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
203 EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
204 EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
205 EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
206 EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
207 EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
208 EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
209 EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
210 EVENT_CONSTRAINT_END
211};
212
213static const struct event_constraint intel_nehalem_event_constraints[] =
214{
215 EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
216 EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
217 EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
218 EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */
219 EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */
220 EVENT_CONSTRAINT(0x4c, 0x3), /* LOAD_HIT_PRE */
221 EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
222 EVENT_CONSTRAINT(0x52, 0x3), /* L1D_CACHE_PREFETCH_LOCK_FB_HIT */
223 EVENT_CONSTRAINT(0x53, 0x3), /* L1D_CACHE_LOCK_FB_HIT */
224 EVENT_CONSTRAINT(0xc5, 0x3), /* CACHE_LOCK_CYCLES */
225 EVENT_CONSTRAINT_END
226};
227
173static u64 intel_pmu_event_map(int hw_event) 228static u64 intel_pmu_event_map(int hw_event)
174{ 229{
175 return intel_perfmon_event_map[hw_event]; 230 return intel_perfmon_event_map[hw_event];
@@ -190,7 +245,7 @@ static u64 __read_mostly hw_cache_event_ids
190 [PERF_COUNT_HW_CACHE_OP_MAX] 245 [PERF_COUNT_HW_CACHE_OP_MAX]
191 [PERF_COUNT_HW_CACHE_RESULT_MAX]; 246 [PERF_COUNT_HW_CACHE_RESULT_MAX];
192 247
193static const u64 nehalem_hw_cache_event_ids 248static __initconst u64 nehalem_hw_cache_event_ids
194 [PERF_COUNT_HW_CACHE_MAX] 249 [PERF_COUNT_HW_CACHE_MAX]
195 [PERF_COUNT_HW_CACHE_OP_MAX] 250 [PERF_COUNT_HW_CACHE_OP_MAX]
196 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 251 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -281,7 +336,7 @@ static const u64 nehalem_hw_cache_event_ids
281 }, 336 },
282}; 337};
283 338
284static const u64 core2_hw_cache_event_ids 339static __initconst u64 core2_hw_cache_event_ids
285 [PERF_COUNT_HW_CACHE_MAX] 340 [PERF_COUNT_HW_CACHE_MAX]
286 [PERF_COUNT_HW_CACHE_OP_MAX] 341 [PERF_COUNT_HW_CACHE_OP_MAX]
287 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 342 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -372,7 +427,7 @@ static const u64 core2_hw_cache_event_ids
372 }, 427 },
373}; 428};
374 429
375static const u64 atom_hw_cache_event_ids 430static __initconst u64 atom_hw_cache_event_ids
376 [PERF_COUNT_HW_CACHE_MAX] 431 [PERF_COUNT_HW_CACHE_MAX]
377 [PERF_COUNT_HW_CACHE_OP_MAX] 432 [PERF_COUNT_HW_CACHE_OP_MAX]
378 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 433 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -469,7 +524,7 @@ static u64 intel_pmu_raw_event(u64 hw_event)
469#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL 524#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL
470#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL 525#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL
471#define CORE_EVNTSEL_INV_MASK 0x00800000ULL 526#define CORE_EVNTSEL_INV_MASK 0x00800000ULL
472#define CORE_EVNTSEL_REG_MASK 0xFF000000ULL 527#define CORE_EVNTSEL_REG_MASK 0xFF000000ULL
473 528
474#define CORE_EVNTSEL_MASK \ 529#define CORE_EVNTSEL_MASK \
475 (CORE_EVNTSEL_EVENT_MASK | \ 530 (CORE_EVNTSEL_EVENT_MASK | \
@@ -481,7 +536,7 @@ static u64 intel_pmu_raw_event(u64 hw_event)
481 return hw_event & CORE_EVNTSEL_MASK; 536 return hw_event & CORE_EVNTSEL_MASK;
482} 537}
483 538
484static const u64 amd_hw_cache_event_ids 539static __initconst u64 amd_hw_cache_event_ids
485 [PERF_COUNT_HW_CACHE_MAX] 540 [PERF_COUNT_HW_CACHE_MAX]
486 [PERF_COUNT_HW_CACHE_OP_MAX] 541 [PERF_COUNT_HW_CACHE_OP_MAX]
487 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 542 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -932,6 +987,8 @@ static int __hw_perf_event_init(struct perf_event *event)
932 */ 987 */
933 hwc->config = ARCH_PERFMON_EVENTSEL_INT; 988 hwc->config = ARCH_PERFMON_EVENTSEL_INT;
934 989
990 hwc->idx = -1;
991
935 /* 992 /*
936 * Count user and OS events unless requested not to. 993 * Count user and OS events unless requested not to.
937 */ 994 */
@@ -1334,8 +1391,7 @@ static void amd_pmu_enable_event(struct hw_perf_event *hwc, int idx)
1334 x86_pmu_enable_event(hwc, idx); 1391 x86_pmu_enable_event(hwc, idx);
1335} 1392}
1336 1393
1337static int 1394static int fixed_mode_idx(struct hw_perf_event *hwc)
1338fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1339{ 1395{
1340 unsigned int hw_event; 1396 unsigned int hw_event;
1341 1397
@@ -1349,6 +1405,12 @@ fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1349 if (!x86_pmu.num_events_fixed) 1405 if (!x86_pmu.num_events_fixed)
1350 return -1; 1406 return -1;
1351 1407
1408 /*
1409 * fixed counters do not take all possible filters
1410 */
1411 if (hwc->config & ARCH_PERFMON_EVENT_FILTER_MASK)
1412 return -1;
1413
1352 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) 1414 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS)))
1353 return X86_PMC_IDX_FIXED_INSTRUCTIONS; 1415 return X86_PMC_IDX_FIXED_INSTRUCTIONS;
1354 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) 1416 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES)))
@@ -1360,22 +1422,57 @@ fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1360} 1422}
1361 1423
1362/* 1424/*
1363 * Find a PMC slot for the freshly enabled / scheduled in event: 1425 * generic counter allocator: get next free counter
1364 */ 1426 */
1365static int x86_pmu_enable(struct perf_event *event) 1427static int
1428gen_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1429{
1430 int idx;
1431
1432 idx = find_first_zero_bit(cpuc->used_mask, x86_pmu.num_events);
1433 return idx == x86_pmu.num_events ? -1 : idx;
1434}
1435
1436/*
1437 * intel-specific counter allocator: check event constraints
1438 */
1439static int
1440intel_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1441{
1442 const struct event_constraint *event_constraint;
1443 int i, code;
1444
1445 if (!event_constraints)
1446 goto skip;
1447
1448 code = hwc->config & CORE_EVNTSEL_EVENT_MASK;
1449
1450 for_each_event_constraint(event_constraint, event_constraints) {
1451 if (code == event_constraint->code) {
1452 for_each_bit(i, event_constraint->idxmsk, X86_PMC_IDX_MAX) {
1453 if (!test_and_set_bit(i, cpuc->used_mask))
1454 return i;
1455 }
1456 return -1;
1457 }
1458 }
1459skip:
1460 return gen_get_event_idx(cpuc, hwc);
1461}
1462
1463static int
1464x86_schedule_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1366{ 1465{
1367 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1368 struct hw_perf_event *hwc = &event->hw;
1369 int idx; 1466 int idx;
1370 1467
1371 idx = fixed_mode_idx(event, hwc); 1468 idx = fixed_mode_idx(hwc);
1372 if (idx == X86_PMC_IDX_FIXED_BTS) { 1469 if (idx == X86_PMC_IDX_FIXED_BTS) {
1373 /* BTS is already occupied. */ 1470 /* BTS is already occupied. */
1374 if (test_and_set_bit(idx, cpuc->used_mask)) 1471 if (test_and_set_bit(idx, cpuc->used_mask))
1375 return -EAGAIN; 1472 return -EAGAIN;
1376 1473
1377 hwc->config_base = 0; 1474 hwc->config_base = 0;
1378 hwc->event_base = 0; 1475 hwc->event_base = 0;
1379 hwc->idx = idx; 1476 hwc->idx = idx;
1380 } else if (idx >= 0) { 1477 } else if (idx >= 0) {
1381 /* 1478 /*
@@ -1396,20 +1493,35 @@ static int x86_pmu_enable(struct perf_event *event)
1396 } else { 1493 } else {
1397 idx = hwc->idx; 1494 idx = hwc->idx;
1398 /* Try to get the previous generic event again */ 1495 /* Try to get the previous generic event again */
1399 if (test_and_set_bit(idx, cpuc->used_mask)) { 1496 if (idx == -1 || test_and_set_bit(idx, cpuc->used_mask)) {
1400try_generic: 1497try_generic:
1401 idx = find_first_zero_bit(cpuc->used_mask, 1498 idx = x86_pmu.get_event_idx(cpuc, hwc);
1402 x86_pmu.num_events); 1499 if (idx == -1)
1403 if (idx == x86_pmu.num_events)
1404 return -EAGAIN; 1500 return -EAGAIN;
1405 1501
1406 set_bit(idx, cpuc->used_mask); 1502 set_bit(idx, cpuc->used_mask);
1407 hwc->idx = idx; 1503 hwc->idx = idx;
1408 } 1504 }
1409 hwc->config_base = x86_pmu.eventsel; 1505 hwc->config_base = x86_pmu.eventsel;
1410 hwc->event_base = x86_pmu.perfctr; 1506 hwc->event_base = x86_pmu.perfctr;
1411 } 1507 }
1412 1508
1509 return idx;
1510}
1511
1512/*
1513 * Find a PMC slot for the freshly enabled / scheduled in event:
1514 */
1515static int x86_pmu_enable(struct perf_event *event)
1516{
1517 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1518 struct hw_perf_event *hwc = &event->hw;
1519 int idx;
1520
1521 idx = x86_schedule_event(cpuc, hwc);
1522 if (idx < 0)
1523 return idx;
1524
1413 perf_events_lapic_init(); 1525 perf_events_lapic_init();
1414 1526
1415 x86_pmu.disable(hwc, idx); 1527 x86_pmu.disable(hwc, idx);
@@ -1852,7 +1964,7 @@ static __read_mostly struct notifier_block perf_event_nmi_notifier = {
1852 .priority = 1 1964 .priority = 1
1853}; 1965};
1854 1966
1855static struct x86_pmu p6_pmu = { 1967static __initconst struct x86_pmu p6_pmu = {
1856 .name = "p6", 1968 .name = "p6",
1857 .handle_irq = p6_pmu_handle_irq, 1969 .handle_irq = p6_pmu_handle_irq,
1858 .disable_all = p6_pmu_disable_all, 1970 .disable_all = p6_pmu_disable_all,
@@ -1877,9 +1989,10 @@ static struct x86_pmu p6_pmu = {
1877 */ 1989 */
1878 .event_bits = 32, 1990 .event_bits = 32,
1879 .event_mask = (1ULL << 32) - 1, 1991 .event_mask = (1ULL << 32) - 1,
1992 .get_event_idx = intel_get_event_idx,
1880}; 1993};
1881 1994
1882static struct x86_pmu intel_pmu = { 1995static __initconst struct x86_pmu intel_pmu = {
1883 .name = "Intel", 1996 .name = "Intel",
1884 .handle_irq = intel_pmu_handle_irq, 1997 .handle_irq = intel_pmu_handle_irq,
1885 .disable_all = intel_pmu_disable_all, 1998 .disable_all = intel_pmu_disable_all,
@@ -1900,9 +2013,10 @@ static struct x86_pmu intel_pmu = {
1900 .max_period = (1ULL << 31) - 1, 2013 .max_period = (1ULL << 31) - 1,
1901 .enable_bts = intel_pmu_enable_bts, 2014 .enable_bts = intel_pmu_enable_bts,
1902 .disable_bts = intel_pmu_disable_bts, 2015 .disable_bts = intel_pmu_disable_bts,
2016 .get_event_idx = intel_get_event_idx,
1903}; 2017};
1904 2018
1905static struct x86_pmu amd_pmu = { 2019static __initconst struct x86_pmu amd_pmu = {
1906 .name = "AMD", 2020 .name = "AMD",
1907 .handle_irq = amd_pmu_handle_irq, 2021 .handle_irq = amd_pmu_handle_irq,
1908 .disable_all = amd_pmu_disable_all, 2022 .disable_all = amd_pmu_disable_all,
@@ -1920,9 +2034,10 @@ static struct x86_pmu amd_pmu = {
1920 .apic = 1, 2034 .apic = 1,
1921 /* use highest bit to detect overflow */ 2035 /* use highest bit to detect overflow */
1922 .max_period = (1ULL << 47) - 1, 2036 .max_period = (1ULL << 47) - 1,
2037 .get_event_idx = gen_get_event_idx,
1923}; 2038};
1924 2039
1925static int p6_pmu_init(void) 2040static __init int p6_pmu_init(void)
1926{ 2041{
1927 switch (boot_cpu_data.x86_model) { 2042 switch (boot_cpu_data.x86_model) {
1928 case 1: 2043 case 1:
@@ -1932,10 +2047,12 @@ static int p6_pmu_init(void)
1932 case 7: 2047 case 7:
1933 case 8: 2048 case 8:
1934 case 11: /* Pentium III */ 2049 case 11: /* Pentium III */
2050 event_constraints = intel_p6_event_constraints;
1935 break; 2051 break;
1936 case 9: 2052 case 9:
1937 case 13: 2053 case 13:
1938 /* Pentium M */ 2054 /* Pentium M */
2055 event_constraints = intel_p6_event_constraints;
1939 break; 2056 break;
1940 default: 2057 default:
1941 pr_cont("unsupported p6 CPU model %d ", 2058 pr_cont("unsupported p6 CPU model %d ",
@@ -1954,7 +2071,7 @@ static int p6_pmu_init(void)
1954 return 0; 2071 return 0;
1955} 2072}
1956 2073
1957static int intel_pmu_init(void) 2074static __init int intel_pmu_init(void)
1958{ 2075{
1959 union cpuid10_edx edx; 2076 union cpuid10_edx edx;
1960 union cpuid10_eax eax; 2077 union cpuid10_eax eax;
@@ -2007,12 +2124,14 @@ static int intel_pmu_init(void)
2007 sizeof(hw_cache_event_ids)); 2124 sizeof(hw_cache_event_ids));
2008 2125
2009 pr_cont("Core2 events, "); 2126 pr_cont("Core2 events, ");
2127 event_constraints = intel_core_event_constraints;
2010 break; 2128 break;
2011 default: 2129 default:
2012 case 26: 2130 case 26:
2013 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, 2131 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
2014 sizeof(hw_cache_event_ids)); 2132 sizeof(hw_cache_event_ids));
2015 2133
2134 event_constraints = intel_nehalem_event_constraints;
2016 pr_cont("Nehalem/Corei7 events, "); 2135 pr_cont("Nehalem/Corei7 events, ");
2017 break; 2136 break;
2018 case 28: 2137 case 28:
@@ -2025,7 +2144,7 @@ static int intel_pmu_init(void)
2025 return 0; 2144 return 0;
2026} 2145}
2027 2146
2028static int amd_pmu_init(void) 2147static __init int amd_pmu_init(void)
2029{ 2148{
2030 /* Performance-monitoring supported from K7 and later: */ 2149 /* Performance-monitoring supported from K7 and later: */
2031 if (boot_cpu_data.x86 < 6) 2150 if (boot_cpu_data.x86 < 6)
@@ -2105,11 +2224,47 @@ static const struct pmu pmu = {
2105 .unthrottle = x86_pmu_unthrottle, 2224 .unthrottle = x86_pmu_unthrottle,
2106}; 2225};
2107 2226
2227static int
2228validate_event(struct cpu_hw_events *cpuc, struct perf_event *event)
2229{
2230 struct hw_perf_event fake_event = event->hw;
2231
2232 if (event->pmu && event->pmu != &pmu)
2233 return 0;
2234
2235 return x86_schedule_event(cpuc, &fake_event) >= 0;
2236}
2237
2238static int validate_group(struct perf_event *event)
2239{
2240 struct perf_event *sibling, *leader = event->group_leader;
2241 struct cpu_hw_events fake_pmu;
2242
2243 memset(&fake_pmu, 0, sizeof(fake_pmu));
2244
2245 if (!validate_event(&fake_pmu, leader))
2246 return -ENOSPC;
2247
2248 list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
2249 if (!validate_event(&fake_pmu, sibling))
2250 return -ENOSPC;
2251 }
2252
2253 if (!validate_event(&fake_pmu, event))
2254 return -ENOSPC;
2255
2256 return 0;
2257}
2258
2108const struct pmu *hw_perf_event_init(struct perf_event *event) 2259const struct pmu *hw_perf_event_init(struct perf_event *event)
2109{ 2260{
2110 int err; 2261 int err;
2111 2262
2112 err = __hw_perf_event_init(event); 2263 err = __hw_perf_event_init(event);
2264 if (!err) {
2265 if (event->group_leader != event)
2266 err = validate_group(event);
2267 }
2113 if (err) { 2268 if (err) {
2114 if (event->destroy) 2269 if (event->destroy)
2115 event->destroy(event); 2270 event->destroy(event);
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index fab786f60ed6..898df9719afb 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -712,7 +712,7 @@ static void probe_nmi_watchdog(void)
712 switch (boot_cpu_data.x86_vendor) { 712 switch (boot_cpu_data.x86_vendor) {
713 case X86_VENDOR_AMD: 713 case X86_VENDOR_AMD:
714 if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 && 714 if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
715 boot_cpu_data.x86 != 16) 715 boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17)
716 return; 716 return;
717 wd_ops = &k7_wd_ops; 717 wd_ops = &k7_wd_ops;
718 break; 718 break;
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index bb62b3e5caad..28000743bbb0 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -26,7 +26,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
26 26
27 early_init_transmeta(c); 27 early_init_transmeta(c);
28 28
29 display_cacheinfo(c); 29 cpu_detect_cache_sizes(c);
30 30
31 /* Print CMS and CPU revision */ 31 /* Print CMS and CPU revision */
32 max = cpuid_eax(0x80860000); 32 max = cpuid_eax(0x80860000);
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 6a52d4b36a30..7ef24a796992 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -116,21 +116,16 @@ static int cpuid_open(struct inode *inode, struct file *file)
116{ 116{
117 unsigned int cpu; 117 unsigned int cpu;
118 struct cpuinfo_x86 *c; 118 struct cpuinfo_x86 *c;
119 int ret = 0;
120
121 lock_kernel();
122 119
123 cpu = iminor(file->f_path.dentry->d_inode); 120 cpu = iminor(file->f_path.dentry->d_inode);
124 if (cpu >= nr_cpu_ids || !cpu_online(cpu)) { 121 if (cpu >= nr_cpu_ids || !cpu_online(cpu))
125 ret = -ENXIO; /* No such CPU */ 122 return -ENXIO; /* No such CPU */
126 goto out; 123
127 }
128 c = &cpu_data(cpu); 124 c = &cpu_data(cpu);
129 if (c->cpuid_level < 0) 125 if (c->cpuid_level < 0)
130 ret = -EIO; /* CPUID not supported */ 126 return -EIO; /* CPUID not supported */
131out: 127
132 unlock_kernel(); 128 return 0;
133 return ret;
134} 129}
135 130
136/* 131/*
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 2d8a371d4339..b8ce165dde5d 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -268,11 +268,12 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
268 268
269 show_registers(regs); 269 show_registers(regs);
270#ifdef CONFIG_X86_32 270#ifdef CONFIG_X86_32
271 sp = (unsigned long) (&regs->sp); 271 if (user_mode_vm(regs)) {
272 savesegment(ss, ss);
273 if (user_mode(regs)) {
274 sp = regs->sp; 272 sp = regs->sp;
275 ss = regs->ss & 0xffff; 273 ss = regs->ss & 0xffff;
274 } else {
275 sp = kernel_stack_pointer(regs);
276 savesegment(ss, ss);
276 } 277 }
277 printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); 278 printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
278 print_symbol("%s", regs->ip); 279 print_symbol("%s", regs->ip);
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index f7dd2a7c3bf4..e0ed4c7abb62 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -10,9 +10,9 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/ptrace.h> 11#include <linux/ptrace.h>
12#include <linux/kexec.h> 12#include <linux/kexec.h>
13#include <linux/sysfs.h>
13#include <linux/bug.h> 14#include <linux/bug.h>
14#include <linux/nmi.h> 15#include <linux/nmi.h>
15#include <linux/sysfs.h>
16 16
17#include <asm/stacktrace.h> 17#include <asm/stacktrace.h>
18 18
@@ -35,6 +35,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
35 35
36 if (!stack) { 36 if (!stack) {
37 unsigned long dummy; 37 unsigned long dummy;
38
38 stack = &dummy; 39 stack = &dummy;
39 if (task && task != current) 40 if (task && task != current)
40 stack = (unsigned long *)task->thread.sp; 41 stack = (unsigned long *)task->thread.sp;
@@ -57,8 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
57 58
58 context = (struct thread_info *) 59 context = (struct thread_info *)
59 ((unsigned long)stack & (~(THREAD_SIZE - 1))); 60 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
60 bp = print_context_stack(context, stack, bp, ops, 61 bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph);
61 data, NULL, &graph);
62 62
63 stack = (unsigned long *)context->previous_esp; 63 stack = (unsigned long *)context->previous_esp;
64 if (!stack) 64 if (!stack)
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(dump_trace);
72 72
73void 73void
74show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, 74show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
75 unsigned long *sp, unsigned long bp, char *log_lvl) 75 unsigned long *sp, unsigned long bp, char *log_lvl)
76{ 76{
77 unsigned long *stack; 77 unsigned long *stack;
78 int i; 78 int i;
@@ -156,4 +156,3 @@ int is_valid_bugaddr(unsigned long ip)
156 156
157 return ud2 == 0x0b0f; 157 return ud2 == 0x0b0f;
158} 158}
159
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index a071e6be177e..8e740934bd1f 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -10,26 +10,28 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/ptrace.h> 11#include <linux/ptrace.h>
12#include <linux/kexec.h> 12#include <linux/kexec.h>
13#include <linux/sysfs.h>
13#include <linux/bug.h> 14#include <linux/bug.h>
14#include <linux/nmi.h> 15#include <linux/nmi.h>
15#include <linux/sysfs.h>
16 16
17#include <asm/stacktrace.h> 17#include <asm/stacktrace.h>
18 18
19#include "dumpstack.h" 19#include "dumpstack.h"
20 20
21#define N_EXCEPTION_STACKS_END \
22 (N_EXCEPTION_STACKS + DEBUG_STKSZ/EXCEPTION_STKSZ - 2)
21 23
22static char x86_stack_ids[][8] = { 24static char x86_stack_ids[][8] = {
23 [DEBUG_STACK - 1] = "#DB", 25 [ DEBUG_STACK-1 ] = "#DB",
24 [NMI_STACK - 1] = "NMI", 26 [ NMI_STACK-1 ] = "NMI",
25 [DOUBLEFAULT_STACK - 1] = "#DF", 27 [ DOUBLEFAULT_STACK-1 ] = "#DF",
26 [STACKFAULT_STACK - 1] = "#SS", 28 [ STACKFAULT_STACK-1 ] = "#SS",
27 [MCE_STACK - 1] = "#MC", 29 [ MCE_STACK-1 ] = "#MC",
28#if DEBUG_STKSZ > EXCEPTION_STKSZ 30#if DEBUG_STKSZ > EXCEPTION_STKSZ
29 [N_EXCEPTION_STACKS ... 31 [ N_EXCEPTION_STACKS ...
30 N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" 32 N_EXCEPTION_STACKS_END ] = "#DB[?]"
31#endif 33#endif
32 }; 34};
33 35
34int x86_is_stack_id(int id, char *name) 36int x86_is_stack_id(int id, char *name)
35{ 37{
@@ -37,7 +39,7 @@ int x86_is_stack_id(int id, char *name)
37} 39}
38 40
39static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, 41static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
40 unsigned *usedp, char **idp) 42 unsigned *usedp, char **idp)
41{ 43{
42 unsigned k; 44 unsigned k;
43 45
@@ -202,21 +204,24 @@ EXPORT_SYMBOL(dump_trace);
202 204
203void 205void
204show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, 206show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
205 unsigned long *sp, unsigned long bp, char *log_lvl) 207 unsigned long *sp, unsigned long bp, char *log_lvl)
206{ 208{
209 unsigned long *irq_stack_end;
210 unsigned long *irq_stack;
207 unsigned long *stack; 211 unsigned long *stack;
212 int cpu;
208 int i; 213 int i;
209 const int cpu = smp_processor_id(); 214
210 unsigned long *irq_stack_end = 215 preempt_disable();
211 (unsigned long *)(per_cpu(irq_stack_ptr, cpu)); 216 cpu = smp_processor_id();
212 unsigned long *irq_stack = 217
213 (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE); 218 irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
219 irq_stack = (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE);
214 220
215 /* 221 /*
216 * debugging aid: "show_stack(NULL, NULL);" prints the 222 * Debugging aid: "show_stack(NULL, NULL);" prints the
217 * back trace for this cpu. 223 * back trace for this cpu:
218 */ 224 */
219
220 if (sp == NULL) { 225 if (sp == NULL) {
221 if (task) 226 if (task)
222 sp = (unsigned long *)task->thread.sp; 227 sp = (unsigned long *)task->thread.sp;
@@ -240,6 +245,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
240 printk(" %016lx", *stack++); 245 printk(" %016lx", *stack++);
241 touch_nmi_watchdog(); 246 touch_nmi_watchdog();
242 } 247 }
248 preempt_enable();
249
243 printk("\n"); 250 printk("\n");
244 show_trace_log_lvl(task, regs, sp, bp, log_lvl); 251 show_trace_log_lvl(task, regs, sp, bp, log_lvl);
245} 252}
@@ -303,4 +310,3 @@ int is_valid_bugaddr(unsigned long ip)
303 310
304 return ud2 == 0x0b0f; 311 return ud2 == 0x0b0f;
305} 312}
306
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 7d52e9da5e0c..50b9c220e121 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -334,6 +334,10 @@ ENTRY(ret_from_fork)
334END(ret_from_fork) 334END(ret_from_fork)
335 335
336/* 336/*
337 * Interrupt exit functions should be protected against kprobes
338 */
339 .pushsection .kprobes.text, "ax"
340/*
337 * Return to user mode is not as complex as all this looks, 341 * Return to user mode is not as complex as all this looks,
338 * but we want the default path for a system call return to 342 * but we want the default path for a system call return to
339 * go as quickly as possible which is why some of this is 343 * go as quickly as possible which is why some of this is
@@ -383,6 +387,10 @@ need_resched:
383END(resume_kernel) 387END(resume_kernel)
384#endif 388#endif
385 CFI_ENDPROC 389 CFI_ENDPROC
390/*
391 * End of kprobes section
392 */
393 .popsection
386 394
387/* SYSENTER_RETURN points to after the "sysenter" instruction in 395/* SYSENTER_RETURN points to after the "sysenter" instruction in
388 the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */ 396 the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
@@ -513,6 +521,10 @@ sysexit_audit:
513 PTGS_TO_GS_EX 521 PTGS_TO_GS_EX
514ENDPROC(ia32_sysenter_target) 522ENDPROC(ia32_sysenter_target)
515 523
524/*
525 * syscall stub including irq exit should be protected against kprobes
526 */
527 .pushsection .kprobes.text, "ax"
516 # system call handler stub 528 # system call handler stub
517ENTRY(system_call) 529ENTRY(system_call)
518 RING0_INT_FRAME # can't unwind into user space anyway 530 RING0_INT_FRAME # can't unwind into user space anyway
@@ -705,6 +717,10 @@ syscall_badsys:
705 jmp resume_userspace 717 jmp resume_userspace
706END(syscall_badsys) 718END(syscall_badsys)
707 CFI_ENDPROC 719 CFI_ENDPROC
720/*
721 * End of kprobes section
722 */
723 .popsection
708 724
709/* 725/*
710 * System calls that need a pt_regs pointer. 726 * System calls that need a pt_regs pointer.
@@ -814,6 +830,10 @@ common_interrupt:
814ENDPROC(common_interrupt) 830ENDPROC(common_interrupt)
815 CFI_ENDPROC 831 CFI_ENDPROC
816 832
833/*
834 * Irq entries should be protected against kprobes
835 */
836 .pushsection .kprobes.text, "ax"
817#define BUILD_INTERRUPT3(name, nr, fn) \ 837#define BUILD_INTERRUPT3(name, nr, fn) \
818ENTRY(name) \ 838ENTRY(name) \
819 RING0_INT_FRAME; \ 839 RING0_INT_FRAME; \
@@ -980,6 +1000,10 @@ ENTRY(spurious_interrupt_bug)
980 jmp error_code 1000 jmp error_code
981 CFI_ENDPROC 1001 CFI_ENDPROC
982END(spurious_interrupt_bug) 1002END(spurious_interrupt_bug)
1003/*
1004 * End of kprobes section
1005 */
1006 .popsection
983 1007
984ENTRY(kernel_thread_helper) 1008ENTRY(kernel_thread_helper)
985 pushl $0 # fake return address for unwinder 1009 pushl $0 # fake return address for unwinder
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index bd5bbddddf91..4deb8fc849dd 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -803,6 +803,10 @@ END(interrupt)
803 call \func 803 call \func
804 .endm 804 .endm
805 805
806/*
807 * Interrupt entry/exit should be protected against kprobes
808 */
809 .pushsection .kprobes.text, "ax"
806 /* 810 /*
807 * The interrupt stubs push (~vector+0x80) onto the stack and 811 * The interrupt stubs push (~vector+0x80) onto the stack and
808 * then jump to common_interrupt. 812 * then jump to common_interrupt.
@@ -941,6 +945,10 @@ ENTRY(retint_kernel)
941 945
942 CFI_ENDPROC 946 CFI_ENDPROC
943END(common_interrupt) 947END(common_interrupt)
948/*
949 * End of kprobes section
950 */
951 .popsection
944 952
945/* 953/*
946 * APIC interrupts. 954 * APIC interrupts.
@@ -1491,12 +1499,17 @@ error_kernelspace:
1491 leaq irq_return(%rip),%rcx 1499 leaq irq_return(%rip),%rcx
1492 cmpq %rcx,RIP+8(%rsp) 1500 cmpq %rcx,RIP+8(%rsp)
1493 je error_swapgs 1501 je error_swapgs
1494 movl %ecx,%ecx /* zero extend */ 1502 movl %ecx,%eax /* zero extend */
1495 cmpq %rcx,RIP+8(%rsp) 1503 cmpq %rax,RIP+8(%rsp)
1496 je error_swapgs 1504 je bstep_iret
1497 cmpq $gs_change,RIP+8(%rsp) 1505 cmpq $gs_change,RIP+8(%rsp)
1498 je error_swapgs 1506 je error_swapgs
1499 jmp error_sti 1507 jmp error_sti
1508
1509bstep_iret:
1510 /* Fix truncated RIP */
1511 movq %rcx,RIP+8(%rsp)
1512 jmp error_swapgs
1500END(error_entry) 1513END(error_entry)
1501 1514
1502 1515
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 780cd928fcd5..22db86a37643 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -212,8 +212,8 @@ ENTRY(secondary_startup_64)
212 */ 212 */
213 lgdt early_gdt_descr(%rip) 213 lgdt early_gdt_descr(%rip)
214 214
215 /* set up data segments. actually 0 would do too */ 215 /* set up data segments */
216 movl $__KERNEL_DS,%eax 216 xorl %eax,%eax
217 movl %eax,%ds 217 movl %eax,%ds
218 movl %eax,%ss 218 movl %eax,%ss
219 movl %eax,%es 219 movl %eax,%es
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
new file mode 100644
index 000000000000..d42f65ac4927
--- /dev/null
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -0,0 +1,555 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2007 Alan Stern
17 * Copyright (C) 2009 IBM Corporation
18 * Copyright (C) 2009 Frederic Weisbecker <fweisbec@gmail.com>
19 *
20 * Authors: Alan Stern <stern@rowland.harvard.edu>
21 * K.Prasad <prasad@linux.vnet.ibm.com>
22 * Frederic Weisbecker <fweisbec@gmail.com>
23 */
24
25/*
26 * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
27 * using the CPU's debug registers.
28 */
29
30#include <linux/perf_event.h>
31#include <linux/hw_breakpoint.h>
32#include <linux/irqflags.h>
33#include <linux/notifier.h>
34#include <linux/kallsyms.h>
35#include <linux/kprobes.h>
36#include <linux/percpu.h>
37#include <linux/kdebug.h>
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/sched.h>
41#include <linux/init.h>
42#include <linux/smp.h>
43
44#include <asm/hw_breakpoint.h>
45#include <asm/processor.h>
46#include <asm/debugreg.h>
47
48/* Per cpu debug control register value */
49DEFINE_PER_CPU(unsigned long, cpu_dr7);
50EXPORT_PER_CPU_SYMBOL(cpu_dr7);
51
52/* Per cpu debug address registers values */
53static DEFINE_PER_CPU(unsigned long, cpu_debugreg[HBP_NUM]);
54
55/*
56 * Stores the breakpoints currently in use on each breakpoint address
57 * register for each cpus
58 */
59static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);
60
61
62static inline unsigned long
63__encode_dr7(int drnum, unsigned int len, unsigned int type)
64{
65 unsigned long bp_info;
66
67 bp_info = (len | type) & 0xf;
68 bp_info <<= (DR_CONTROL_SHIFT + drnum * DR_CONTROL_SIZE);
69 bp_info |= (DR_GLOBAL_ENABLE << (drnum * DR_ENABLE_SIZE));
70
71 return bp_info;
72}
73
74/*
75 * Encode the length, type, Exact, and Enable bits for a particular breakpoint
76 * as stored in debug register 7.
77 */
78unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type)
79{
80 return __encode_dr7(drnum, len, type) | DR_GLOBAL_SLOWDOWN;
81}
82
83/*
84 * Decode the length and type bits for a particular breakpoint as
85 * stored in debug register 7. Return the "enabled" status.
86 */
87int decode_dr7(unsigned long dr7, int bpnum, unsigned *len, unsigned *type)
88{
89 int bp_info = dr7 >> (DR_CONTROL_SHIFT + bpnum * DR_CONTROL_SIZE);
90
91 *len = (bp_info & 0xc) | 0x40;
92 *type = (bp_info & 0x3) | 0x80;
93
94 return (dr7 >> (bpnum * DR_ENABLE_SIZE)) & 0x3;
95}
96
97/*
98 * Install a perf counter breakpoint.
99 *
100 * We seek a free debug address register and use it for this
101 * breakpoint. Eventually we enable it in the debug control register.
102 *
103 * Atomic: we hold the counter->ctx->lock and we only handle variables
104 * and registers local to this cpu.
105 */
106int arch_install_hw_breakpoint(struct perf_event *bp)
107{
108 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
109 unsigned long *dr7;
110 int i;
111
112 for (i = 0; i < HBP_NUM; i++) {
113 struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
114
115 if (!*slot) {
116 *slot = bp;
117 break;
118 }
119 }
120
121 if (WARN_ONCE(i == HBP_NUM, "Can't find any breakpoint slot"))
122 return -EBUSY;
123
124 set_debugreg(info->address, i);
125 __get_cpu_var(cpu_debugreg[i]) = info->address;
126
127 dr7 = &__get_cpu_var(cpu_dr7);
128 *dr7 |= encode_dr7(i, info->len, info->type);
129
130 set_debugreg(*dr7, 7);
131
132 return 0;
133}
134
135/*
136 * Uninstall the breakpoint contained in the given counter.
137 *
138 * First we search the debug address register it uses and then we disable
139 * it.
140 *
141 * Atomic: we hold the counter->ctx->lock and we only handle variables
142 * and registers local to this cpu.
143 */
144void arch_uninstall_hw_breakpoint(struct perf_event *bp)
145{
146 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
147 unsigned long *dr7;
148 int i;
149
150 for (i = 0; i < HBP_NUM; i++) {
151 struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
152
153 if (*slot == bp) {
154 *slot = NULL;
155 break;
156 }
157 }
158
159 if (WARN_ONCE(i == HBP_NUM, "Can't find any breakpoint slot"))
160 return;
161
162 dr7 = &__get_cpu_var(cpu_dr7);
163 *dr7 &= ~__encode_dr7(i, info->len, info->type);
164
165 set_debugreg(*dr7, 7);
166}
167
168static int get_hbp_len(u8 hbp_len)
169{
170 unsigned int len_in_bytes = 0;
171
172 switch (hbp_len) {
173 case X86_BREAKPOINT_LEN_1:
174 len_in_bytes = 1;
175 break;
176 case X86_BREAKPOINT_LEN_2:
177 len_in_bytes = 2;
178 break;
179 case X86_BREAKPOINT_LEN_4:
180 len_in_bytes = 4;
181 break;
182#ifdef CONFIG_X86_64
183 case X86_BREAKPOINT_LEN_8:
184 len_in_bytes = 8;
185 break;
186#endif
187 }
188 return len_in_bytes;
189}
190
191/*
192 * Check for virtual address in user space.
193 */
194int arch_check_va_in_userspace(unsigned long va, u8 hbp_len)
195{
196 unsigned int len;
197
198 len = get_hbp_len(hbp_len);
199
200 return (va <= TASK_SIZE - len);
201}
202
203/*
204 * Check for virtual address in kernel space.
205 */
206static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
207{
208 unsigned int len;
209
210 len = get_hbp_len(hbp_len);
211
212 return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
213}
214
215/*
216 * Store a breakpoint's encoded address, length, and type.
217 */
218static int arch_store_info(struct perf_event *bp)
219{
220 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
221 /*
222 * For kernel-addresses, either the address or symbol name can be
223 * specified.
224 */
225 if (info->name)
226 info->address = (unsigned long)
227 kallsyms_lookup_name(info->name);
228 if (info->address)
229 return 0;
230
231 return -EINVAL;
232}
233
234int arch_bp_generic_fields(int x86_len, int x86_type,
235 int *gen_len, int *gen_type)
236{
237 /* Len */
238 switch (x86_len) {
239 case X86_BREAKPOINT_LEN_1:
240 *gen_len = HW_BREAKPOINT_LEN_1;
241 break;
242 case X86_BREAKPOINT_LEN_2:
243 *gen_len = HW_BREAKPOINT_LEN_2;
244 break;
245 case X86_BREAKPOINT_LEN_4:
246 *gen_len = HW_BREAKPOINT_LEN_4;
247 break;
248#ifdef CONFIG_X86_64
249 case X86_BREAKPOINT_LEN_8:
250 *gen_len = HW_BREAKPOINT_LEN_8;
251 break;
252#endif
253 default:
254 return -EINVAL;
255 }
256
257 /* Type */
258 switch (x86_type) {
259 case X86_BREAKPOINT_EXECUTE:
260 *gen_type = HW_BREAKPOINT_X;
261 break;
262 case X86_BREAKPOINT_WRITE:
263 *gen_type = HW_BREAKPOINT_W;
264 break;
265 case X86_BREAKPOINT_RW:
266 *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
267 break;
268 default:
269 return -EINVAL;
270 }
271
272 return 0;
273}
274
275
276static int arch_build_bp_info(struct perf_event *bp)
277{
278 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
279
280 info->address = bp->attr.bp_addr;
281
282 /* Len */
283 switch (bp->attr.bp_len) {
284 case HW_BREAKPOINT_LEN_1:
285 info->len = X86_BREAKPOINT_LEN_1;
286 break;
287 case HW_BREAKPOINT_LEN_2:
288 info->len = X86_BREAKPOINT_LEN_2;
289 break;
290 case HW_BREAKPOINT_LEN_4:
291 info->len = X86_BREAKPOINT_LEN_4;
292 break;
293#ifdef CONFIG_X86_64
294 case HW_BREAKPOINT_LEN_8:
295 info->len = X86_BREAKPOINT_LEN_8;
296 break;
297#endif
298 default:
299 return -EINVAL;
300 }
301
302 /* Type */
303 switch (bp->attr.bp_type) {
304 case HW_BREAKPOINT_W:
305 info->type = X86_BREAKPOINT_WRITE;
306 break;
307 case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
308 info->type = X86_BREAKPOINT_RW;
309 break;
310 case HW_BREAKPOINT_X:
311 info->type = X86_BREAKPOINT_EXECUTE;
312 break;
313 default:
314 return -EINVAL;
315 }
316
317 return 0;
318}
319/*
320 * Validate the arch-specific HW Breakpoint register settings
321 */
322int arch_validate_hwbkpt_settings(struct perf_event *bp,
323 struct task_struct *tsk)
324{
325 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
326 unsigned int align;
327 int ret;
328
329
330 ret = arch_build_bp_info(bp);
331 if (ret)
332 return ret;
333
334 ret = -EINVAL;
335
336 if (info->type == X86_BREAKPOINT_EXECUTE)
337 /*
338 * Ptrace-refactoring code
339 * For now, we'll allow instruction breakpoint only for user-space
340 * addresses
341 */
342 if ((!arch_check_va_in_userspace(info->address, info->len)) &&
343 info->len != X86_BREAKPOINT_EXECUTE)
344 return ret;
345
346 switch (info->len) {
347 case X86_BREAKPOINT_LEN_1:
348 align = 0;
349 break;
350 case X86_BREAKPOINT_LEN_2:
351 align = 1;
352 break;
353 case X86_BREAKPOINT_LEN_4:
354 align = 3;
355 break;
356#ifdef CONFIG_X86_64
357 case X86_BREAKPOINT_LEN_8:
358 align = 7;
359 break;
360#endif
361 default:
362 return ret;
363 }
364
365 if (bp->callback)
366 ret = arch_store_info(bp);
367
368 if (ret < 0)
369 return ret;
370 /*
371 * Check that the low-order bits of the address are appropriate
372 * for the alignment implied by len.
373 */
374 if (info->address & align)
375 return -EINVAL;
376
377 /* Check that the virtual address is in the proper range */
378 if (tsk) {
379 if (!arch_check_va_in_userspace(info->address, info->len))
380 return -EFAULT;
381 } else {
382 if (!arch_check_va_in_kernelspace(info->address, info->len))
383 return -EFAULT;
384 }
385
386 return 0;
387}
388
389/*
390 * Dump the debug register contents to the user.
391 * We can't dump our per cpu values because it
392 * may contain cpu wide breakpoint, something that
393 * doesn't belong to the current task.
394 *
395 * TODO: include non-ptrace user breakpoints (perf)
396 */
397void aout_dump_debugregs(struct user *dump)
398{
399 int i;
400 int dr7 = 0;
401 struct perf_event *bp;
402 struct arch_hw_breakpoint *info;
403 struct thread_struct *thread = &current->thread;
404
405 for (i = 0; i < HBP_NUM; i++) {
406 bp = thread->ptrace_bps[i];
407
408 if (bp && !bp->attr.disabled) {
409 dump->u_debugreg[i] = bp->attr.bp_addr;
410 info = counter_arch_bp(bp);
411 dr7 |= encode_dr7(i, info->len, info->type);
412 } else {
413 dump->u_debugreg[i] = 0;
414 }
415 }
416
417 dump->u_debugreg[4] = 0;
418 dump->u_debugreg[5] = 0;
419 dump->u_debugreg[6] = current->thread.debugreg6;
420
421 dump->u_debugreg[7] = dr7;
422}
423EXPORT_SYMBOL_GPL(aout_dump_debugregs);
424
425/*
426 * Release the user breakpoints used by ptrace
427 */
428void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
429{
430 int i;
431 struct thread_struct *t = &tsk->thread;
432
433 for (i = 0; i < HBP_NUM; i++) {
434 unregister_hw_breakpoint(t->ptrace_bps[i]);
435 t->ptrace_bps[i] = NULL;
436 }
437}
438
439void hw_breakpoint_restore(void)
440{
441 set_debugreg(__get_cpu_var(cpu_debugreg[0]), 0);
442 set_debugreg(__get_cpu_var(cpu_debugreg[1]), 1);
443 set_debugreg(__get_cpu_var(cpu_debugreg[2]), 2);
444 set_debugreg(__get_cpu_var(cpu_debugreg[3]), 3);
445 set_debugreg(current->thread.debugreg6, 6);
446 set_debugreg(__get_cpu_var(cpu_dr7), 7);
447}
448EXPORT_SYMBOL_GPL(hw_breakpoint_restore);
449
450/*
451 * Handle debug exception notifications.
452 *
453 * Return value is either NOTIFY_STOP or NOTIFY_DONE as explained below.
454 *
455 * NOTIFY_DONE returned if one of the following conditions is true.
456 * i) When the causative address is from user-space and the exception
457 * is a valid one, i.e. not triggered as a result of lazy debug register
458 * switching
459 * ii) When there are more bits than trap<n> set in DR6 register (such
460 * as BD, BS or BT) indicating that more than one debug condition is
461 * met and requires some more action in do_debug().
462 *
463 * NOTIFY_STOP returned for all other cases
464 *
465 */
466static int __kprobes hw_breakpoint_handler(struct die_args *args)
467{
468 int i, cpu, rc = NOTIFY_STOP;
469 struct perf_event *bp;
470 unsigned long dr7, dr6;
471 unsigned long *dr6_p;
472
473 /* The DR6 value is pointed by args->err */
474 dr6_p = (unsigned long *)ERR_PTR(args->err);
475 dr6 = *dr6_p;
476
477 /* Do an early return if no trap bits are set in DR6 */
478 if ((dr6 & DR_TRAP_BITS) == 0)
479 return NOTIFY_DONE;
480
481 get_debugreg(dr7, 7);
482 /* Disable breakpoints during exception handling */
483 set_debugreg(0UL, 7);
484 /*
485 * Assert that local interrupts are disabled
486 * Reset the DRn bits in the virtualized register value.
487 * The ptrace trigger routine will add in whatever is needed.
488 */
489 current->thread.debugreg6 &= ~DR_TRAP_BITS;
490 cpu = get_cpu();
491
492 /* Handle all the breakpoints that were triggered */
493 for (i = 0; i < HBP_NUM; ++i) {
494 if (likely(!(dr6 & (DR_TRAP0 << i))))
495 continue;
496
497 /*
498 * The counter may be concurrently released but that can only
499 * occur from a call_rcu() path. We can then safely fetch
500 * the breakpoint, use its callback, touch its counter
501 * while we are in an rcu_read_lock() path.
502 */
503 rcu_read_lock();
504
505 bp = per_cpu(bp_per_reg[i], cpu);
506 if (bp)
507 rc = NOTIFY_DONE;
508 /*
509 * Reset the 'i'th TRAP bit in dr6 to denote completion of
510 * exception handling
511 */
512 (*dr6_p) &= ~(DR_TRAP0 << i);
513 /*
514 * bp can be NULL due to lazy debug register switching
515 * or due to concurrent perf counter removing.
516 */
517 if (!bp) {
518 rcu_read_unlock();
519 break;
520 }
521
522 (bp->callback)(bp, args->regs);
523
524 rcu_read_unlock();
525 }
526 if (dr6 & (~DR_TRAP_BITS))
527 rc = NOTIFY_DONE;
528
529 set_debugreg(dr7, 7);
530 put_cpu();
531
532 return rc;
533}
534
535/*
536 * Handle debug exception notifications.
537 */
538int __kprobes hw_breakpoint_exceptions_notify(
539 struct notifier_block *unused, unsigned long val, void *data)
540{
541 if (val != DIE_DEBUG)
542 return NOTIFY_DONE;
543
544 return hw_breakpoint_handler(data);
545}
546
547void hw_breakpoint_pmu_read(struct perf_event *bp)
548{
549 /* TODO */
550}
551
552void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
553{
554 /* TODO */
555}
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 04bbd5278568..fee6cc2b2079 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -92,17 +92,17 @@ static int show_other_interrupts(struct seq_file *p, int prec)
92 seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); 92 seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
93 seq_printf(p, " TLB shootdowns\n"); 93 seq_printf(p, " TLB shootdowns\n");
94#endif 94#endif
95#ifdef CONFIG_X86_MCE 95#ifdef CONFIG_X86_THERMAL_VECTOR
96 seq_printf(p, "%*s: ", prec, "TRM"); 96 seq_printf(p, "%*s: ", prec, "TRM");
97 for_each_online_cpu(j) 97 for_each_online_cpu(j)
98 seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); 98 seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
99 seq_printf(p, " Thermal event interrupts\n"); 99 seq_printf(p, " Thermal event interrupts\n");
100# ifdef CONFIG_X86_MCE_THRESHOLD 100#endif
101#ifdef CONFIG_X86_MCE_THRESHOLD
101 seq_printf(p, "%*s: ", prec, "THR"); 102 seq_printf(p, "%*s: ", prec, "THR");
102 for_each_online_cpu(j) 103 for_each_online_cpu(j)
103 seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); 104 seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
104 seq_printf(p, " Threshold APIC interrupts\n"); 105 seq_printf(p, " Threshold APIC interrupts\n");
105# endif
106#endif 106#endif
107#ifdef CONFIG_X86_MCE 107#ifdef CONFIG_X86_MCE
108 seq_printf(p, "%*s: ", prec, "MCE"); 108 seq_printf(p, "%*s: ", prec, "MCE");
@@ -194,11 +194,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
194 sum += irq_stats(cpu)->irq_call_count; 194 sum += irq_stats(cpu)->irq_call_count;
195 sum += irq_stats(cpu)->irq_tlb_count; 195 sum += irq_stats(cpu)->irq_tlb_count;
196#endif 196#endif
197#ifdef CONFIG_X86_MCE 197#ifdef CONFIG_X86_THERMAL_VECTOR
198 sum += irq_stats(cpu)->irq_thermal_count; 198 sum += irq_stats(cpu)->irq_thermal_count;
199# ifdef CONFIG_X86_MCE_THRESHOLD 199#endif
200#ifdef CONFIG_X86_MCE_THRESHOLD
200 sum += irq_stats(cpu)->irq_threshold_count; 201 sum += irq_stats(cpu)->irq_threshold_count;
201# endif
202#endif 202#endif
203#ifdef CONFIG_X86_MCE 203#ifdef CONFIG_X86_MCE
204 sum += per_cpu(mce_exception_count, cpu); 204 sum += per_cpu(mce_exception_count, cpu);
@@ -274,3 +274,93 @@ void smp_generic_interrupt(struct pt_regs *regs)
274} 274}
275 275
276EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); 276EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
277
278#ifdef CONFIG_HOTPLUG_CPU
279/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
280void fixup_irqs(void)
281{
282 unsigned int irq, vector;
283 static int warned;
284 struct irq_desc *desc;
285
286 for_each_irq_desc(irq, desc) {
287 int break_affinity = 0;
288 int set_affinity = 1;
289 const struct cpumask *affinity;
290
291 if (!desc)
292 continue;
293 if (irq == 2)
294 continue;
295
296 /* interrupt's are disabled at this point */
297 spin_lock(&desc->lock);
298
299 affinity = desc->affinity;
300 if (!irq_has_action(irq) ||
301 cpumask_equal(affinity, cpu_online_mask)) {
302 spin_unlock(&desc->lock);
303 continue;
304 }
305
306 /*
307 * Complete the irq move. This cpu is going down and for
308 * non intr-remapping case, we can't wait till this interrupt
309 * arrives at this cpu before completing the irq move.
310 */
311 irq_force_complete_move(irq);
312
313 if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
314 break_affinity = 1;
315 affinity = cpu_all_mask;
316 }
317
318 if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask)
319 desc->chip->mask(irq);
320
321 if (desc->chip->set_affinity)
322 desc->chip->set_affinity(irq, affinity);
323 else if (!(warned++))
324 set_affinity = 0;
325
326 if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask)
327 desc->chip->unmask(irq);
328
329 spin_unlock(&desc->lock);
330
331 if (break_affinity && set_affinity)
332 printk("Broke affinity for irq %i\n", irq);
333 else if (!set_affinity)
334 printk("Cannot set affinity for irq %i\n", irq);
335 }
336
337 /*
338 * We can remove mdelay() and then send spuriuous interrupts to
339 * new cpu targets for all the irqs that were handled previously by
340 * this cpu. While it works, I have seen spurious interrupt messages
341 * (nothing wrong but still...).
342 *
343 * So for now, retain mdelay(1) and check the IRR and then send those
344 * interrupts to new targets as this cpu is already offlined...
345 */
346 mdelay(1);
347
348 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
349 unsigned int irr;
350
351 if (__get_cpu_var(vector_irq)[vector] < 0)
352 continue;
353
354 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
355 if (irr & (1 << (vector % 32))) {
356 irq = __get_cpu_var(vector_irq)[vector];
357
358 desc = irq_to_desc(irq);
359 spin_lock(&desc->lock);
360 if (desc->chip->retrigger)
361 desc->chip->retrigger(irq);
362 spin_unlock(&desc->lock);
363 }
364 }
365}
366#endif
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 7d35d0fe2329..10709f29d166 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -211,48 +211,3 @@ bool handle_irq(unsigned irq, struct pt_regs *regs)
211 211
212 return true; 212 return true;
213} 213}
214
215#ifdef CONFIG_HOTPLUG_CPU
216
217/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
218void fixup_irqs(void)
219{
220 unsigned int irq;
221 struct irq_desc *desc;
222
223 for_each_irq_desc(irq, desc) {
224 const struct cpumask *affinity;
225
226 if (!desc)
227 continue;
228 if (irq == 2)
229 continue;
230
231 affinity = desc->affinity;
232 if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
233 printk("Breaking affinity for irq %i\n", irq);
234 affinity = cpu_all_mask;
235 }
236 if (desc->chip->set_affinity)
237 desc->chip->set_affinity(irq, affinity);
238 else if (desc->action)
239 printk_once("Cannot set affinity for irq %i\n", irq);
240 }
241
242#if 0
243 barrier();
244 /* Ingo Molnar says: "after the IO-APIC masks have been redirected
245 [note the nop - the interrupt-enable boundary on x86 is two
246 instructions from sti] - to flush out pending hardirqs and
247 IPIs. After this point nothing is supposed to reach this CPU." */
248 __asm__ __volatile__("sti; nop; cli");
249 barrier();
250#else
251 /* That doesn't seem sufficient. Give it 1ms. */
252 local_irq_enable();
253 mdelay(1);
254 local_irq_disable();
255#endif
256}
257#endif
258
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 977d8b43a0dd..acf8fbf8fbda 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -62,64 +62,6 @@ bool handle_irq(unsigned irq, struct pt_regs *regs)
62 return true; 62 return true;
63} 63}
64 64
65#ifdef CONFIG_HOTPLUG_CPU
66/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
67void fixup_irqs(void)
68{
69 unsigned int irq;
70 static int warned;
71 struct irq_desc *desc;
72
73 for_each_irq_desc(irq, desc) {
74 int break_affinity = 0;
75 int set_affinity = 1;
76 const struct cpumask *affinity;
77
78 if (!desc)
79 continue;
80 if (irq == 2)
81 continue;
82
83 /* interrupt's are disabled at this point */
84 spin_lock(&desc->lock);
85
86 affinity = desc->affinity;
87 if (!irq_has_action(irq) ||
88 cpumask_equal(affinity, cpu_online_mask)) {
89 spin_unlock(&desc->lock);
90 continue;
91 }
92
93 if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
94 break_affinity = 1;
95 affinity = cpu_all_mask;
96 }
97
98 if (desc->chip->mask)
99 desc->chip->mask(irq);
100
101 if (desc->chip->set_affinity)
102 desc->chip->set_affinity(irq, affinity);
103 else if (!(warned++))
104 set_affinity = 0;
105
106 if (desc->chip->unmask)
107 desc->chip->unmask(irq);
108
109 spin_unlock(&desc->lock);
110
111 if (break_affinity && set_affinity)
112 printk("Broke affinity for irq %i\n", irq);
113 else if (!set_affinity)
114 printk("Cannot set affinity for irq %i\n", irq);
115 }
116
117 /* That doesn't seem sufficient. Give it 1ms. */
118 local_irq_enable();
119 mdelay(1);
120 local_irq_disable();
121}
122#endif
123 65
124extern void call_softirq(void); 66extern void call_softirq(void);
125 67
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 8d82a77a3f3b..20a5b3689463 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -43,6 +43,7 @@
43#include <linux/smp.h> 43#include <linux/smp.h>
44#include <linux/nmi.h> 44#include <linux/nmi.h>
45 45
46#include <asm/debugreg.h>
46#include <asm/apicdef.h> 47#include <asm/apicdef.h>
47#include <asm/system.h> 48#include <asm/system.h>
48 49
@@ -88,7 +89,6 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
88 gdb_regs[GDB_SS] = __KERNEL_DS; 89 gdb_regs[GDB_SS] = __KERNEL_DS;
89 gdb_regs[GDB_FS] = 0xFFFF; 90 gdb_regs[GDB_FS] = 0xFFFF;
90 gdb_regs[GDB_GS] = 0xFFFF; 91 gdb_regs[GDB_GS] = 0xFFFF;
91 gdb_regs[GDB_SP] = (int)&regs->sp;
92#else 92#else
93 gdb_regs[GDB_R8] = regs->r8; 93 gdb_regs[GDB_R8] = regs->r8;
94 gdb_regs[GDB_R9] = regs->r9; 94 gdb_regs[GDB_R9] = regs->r9;
@@ -101,8 +101,8 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
101 gdb_regs32[GDB_PS] = regs->flags; 101 gdb_regs32[GDB_PS] = regs->flags;
102 gdb_regs32[GDB_CS] = regs->cs; 102 gdb_regs32[GDB_CS] = regs->cs;
103 gdb_regs32[GDB_SS] = regs->ss; 103 gdb_regs32[GDB_SS] = regs->ss;
104 gdb_regs[GDB_SP] = regs->sp;
105#endif 104#endif
105 gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
106} 106}
107 107
108/** 108/**
@@ -434,6 +434,11 @@ single_step_cont(struct pt_regs *regs, struct die_args *args)
434 "resuming...\n"); 434 "resuming...\n");
435 kgdb_arch_handle_exception(args->trapnr, args->signr, 435 kgdb_arch_handle_exception(args->trapnr, args->signr,
436 args->err, "c", "", regs); 436 args->err, "c", "", regs);
437 /*
438 * Reset the BS bit in dr6 (pointed by args->err) to
439 * denote completion of processing
440 */
441 (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
437 442
438 return NOTIFY_STOP; 443 return NOTIFY_STOP;
439} 444}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 7b5169d2b000..1f3186ce213c 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -48,31 +48,22 @@
48#include <linux/preempt.h> 48#include <linux/preempt.h>
49#include <linux/module.h> 49#include <linux/module.h>
50#include <linux/kdebug.h> 50#include <linux/kdebug.h>
51#include <linux/kallsyms.h>
51 52
52#include <asm/cacheflush.h> 53#include <asm/cacheflush.h>
53#include <asm/desc.h> 54#include <asm/desc.h>
54#include <asm/pgtable.h> 55#include <asm/pgtable.h>
55#include <asm/uaccess.h> 56#include <asm/uaccess.h>
56#include <asm/alternative.h> 57#include <asm/alternative.h>
58#include <asm/insn.h>
59#include <asm/debugreg.h>
57 60
58void jprobe_return_end(void); 61void jprobe_return_end(void);
59 62
60DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 63DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
61DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 64DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
62 65
63#ifdef CONFIG_X86_64 66#define stack_addr(regs) ((unsigned long *)kernel_stack_pointer(regs))
64#define stack_addr(regs) ((unsigned long *)regs->sp)
65#else
66/*
67 * "&regs->sp" looks wrong, but it's correct for x86_32. x86_32 CPUs
68 * don't save the ss and esp registers if the CPU is already in kernel
69 * mode when it traps. So for kprobes, regs->sp and regs->ss are not
70 * the [nonexistent] saved stack pointer and ss register, but rather
71 * the top 8 bytes of the pre-int3 stack. So &regs->sp happens to
72 * point to the top of the pre-int3 stack.
73 */
74#define stack_addr(regs) ((unsigned long *)&regs->sp)
75#endif
76 67
77#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ 68#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
78 (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ 69 (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
@@ -106,50 +97,6 @@ static const u32 twobyte_is_boostable[256 / 32] = {
106 /* ----------------------------------------------- */ 97 /* ----------------------------------------------- */
107 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 98 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
108}; 99};
109static const u32 onebyte_has_modrm[256 / 32] = {
110 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
111 /* ----------------------------------------------- */
112 W(0x00, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 00 */
113 W(0x10, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) , /* 10 */
114 W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 20 */
115 W(0x30, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) , /* 30 */
116 W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */
117 W(0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 50 */
118 W(0x60, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0) | /* 60 */
119 W(0x70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 70 */
120 W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
121 W(0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 90 */
122 W(0xa0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* a0 */
123 W(0xb0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* b0 */
124 W(0xc0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) | /* c0 */
125 W(0xd0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
126 W(0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* e0 */
127 W(0xf0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) /* f0 */
128 /* ----------------------------------------------- */
129 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
130};
131static const u32 twobyte_has_modrm[256 / 32] = {
132 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
133 /* ----------------------------------------------- */
134 W(0x00, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1) | /* 0f */
135 W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0) , /* 1f */
136 W(0x20, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 2f */
137 W(0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 3f */
138 W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 4f */
139 W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 5f */
140 W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 6f */
141 W(0x70, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1) , /* 7f */
142 W(0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 8f */
143 W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 9f */
144 W(0xa0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1) | /* af */
145 W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1) , /* bf */
146 W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) | /* cf */
147 W(0xd0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* df */
148 W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* ef */
149 W(0xf0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* ff */
150 /* ----------------------------------------------- */
151 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
152};
153#undef W 100#undef W
154 101
155struct kretprobe_blackpoint kretprobe_blacklist[] = { 102struct kretprobe_blackpoint kretprobe_blacklist[] = {
@@ -244,6 +191,75 @@ retry:
244 } 191 }
245} 192}
246 193
194/* Recover the probed instruction at addr for further analysis. */
195static int recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
196{
197 struct kprobe *kp;
198 kp = get_kprobe((void *)addr);
199 if (!kp)
200 return -EINVAL;
201
202 /*
203 * Basically, kp->ainsn.insn has an original instruction.
204 * However, RIP-relative instruction can not do single-stepping
205 * at different place, fix_riprel() tweaks the displacement of
206 * that instruction. In that case, we can't recover the instruction
207 * from the kp->ainsn.insn.
208 *
209 * On the other hand, kp->opcode has a copy of the first byte of
210 * the probed instruction, which is overwritten by int3. And
211 * the instruction at kp->addr is not modified by kprobes except
212 * for the first byte, we can recover the original instruction
213 * from it and kp->opcode.
214 */
215 memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
216 buf[0] = kp->opcode;
217 return 0;
218}
219
220/* Dummy buffers for kallsyms_lookup */
221static char __dummy_buf[KSYM_NAME_LEN];
222
223/* Check if paddr is at an instruction boundary */
224static int __kprobes can_probe(unsigned long paddr)
225{
226 int ret;
227 unsigned long addr, offset = 0;
228 struct insn insn;
229 kprobe_opcode_t buf[MAX_INSN_SIZE];
230
231 if (!kallsyms_lookup(paddr, NULL, &offset, NULL, __dummy_buf))
232 return 0;
233
234 /* Decode instructions */
235 addr = paddr - offset;
236 while (addr < paddr) {
237 kernel_insn_init(&insn, (void *)addr);
238 insn_get_opcode(&insn);
239
240 /*
241 * Check if the instruction has been modified by another
242 * kprobe, in which case we replace the breakpoint by the
243 * original instruction in our buffer.
244 */
245 if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) {
246 ret = recover_probed_instruction(buf, addr);
247 if (ret)
248 /*
249 * Another debugging subsystem might insert
250 * this breakpoint. In that case, we can't
251 * recover it.
252 */
253 return 0;
254 kernel_insn_init(&insn, buf);
255 }
256 insn_get_length(&insn);
257 addr += insn.length;
258 }
259
260 return (addr == paddr);
261}
262
247/* 263/*
248 * Returns non-zero if opcode modifies the interrupt flag. 264 * Returns non-zero if opcode modifies the interrupt flag.
249 */ 265 */
@@ -277,68 +293,30 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
277static void __kprobes fix_riprel(struct kprobe *p) 293static void __kprobes fix_riprel(struct kprobe *p)
278{ 294{
279#ifdef CONFIG_X86_64 295#ifdef CONFIG_X86_64
280 u8 *insn = p->ainsn.insn; 296 struct insn insn;
281 s64 disp; 297 kernel_insn_init(&insn, p->ainsn.insn);
282 int need_modrm;
283
284 /* Skip legacy instruction prefixes. */
285 while (1) {
286 switch (*insn) {
287 case 0x66:
288 case 0x67:
289 case 0x2e:
290 case 0x3e:
291 case 0x26:
292 case 0x64:
293 case 0x65:
294 case 0x36:
295 case 0xf0:
296 case 0xf3:
297 case 0xf2:
298 ++insn;
299 continue;
300 }
301 break;
302 }
303 298
304 /* Skip REX instruction prefix. */ 299 if (insn_rip_relative(&insn)) {
305 if (is_REX_prefix(insn)) 300 s64 newdisp;
306 ++insn; 301 u8 *disp;
307 302 insn_get_displacement(&insn);
308 if (*insn == 0x0f) { 303 /*
309 /* Two-byte opcode. */ 304 * The copied instruction uses the %rip-relative addressing
310 ++insn; 305 * mode. Adjust the displacement for the difference between
311 need_modrm = test_bit(*insn, 306 * the original location of this instruction and the location
312 (unsigned long *)twobyte_has_modrm); 307 * of the copy that will actually be run. The tricky bit here
313 } else 308 * is making sure that the sign extension happens correctly in
314 /* One-byte opcode. */ 309 * this calculation, since we need a signed 32-bit result to
315 need_modrm = test_bit(*insn, 310 * be sign-extended to 64 bits when it's added to the %rip
316 (unsigned long *)onebyte_has_modrm); 311 * value and yield the same 64-bit result that the sign-
317 312 * extension of the original signed 32-bit displacement would
318 if (need_modrm) { 313 * have given.
319 u8 modrm = *++insn; 314 */
320 if ((modrm & 0xc7) == 0x05) { 315 newdisp = (u8 *) p->addr + (s64) insn.displacement.value -
321 /* %rip+disp32 addressing mode */ 316 (u8 *) p->ainsn.insn;
322 /* Displacement follows ModRM byte. */ 317 BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check. */
323 ++insn; 318 disp = (u8 *) p->ainsn.insn + insn_offset_displacement(&insn);
324 /* 319 *(s32 *) disp = (s32) newdisp;
325 * The copied instruction uses the %rip-relative
326 * addressing mode. Adjust the displacement for the
327 * difference between the original location of this
328 * instruction and the location of the copy that will
329 * actually be run. The tricky bit here is making sure
330 * that the sign extension happens correctly in this
331 * calculation, since we need a signed 32-bit result to
332 * be sign-extended to 64 bits when it's added to the
333 * %rip value and yield the same 64-bit result that the
334 * sign-extension of the original signed 32-bit
335 * displacement would have given.
336 */
337 disp = (u8 *) p->addr + *((s32 *) insn) -
338 (u8 *) p->ainsn.insn;
339 BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
340 *(s32 *)insn = (s32) disp;
341 }
342 } 320 }
343#endif 321#endif
344} 322}
@@ -359,6 +337,8 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p)
359 337
360int __kprobes arch_prepare_kprobe(struct kprobe *p) 338int __kprobes arch_prepare_kprobe(struct kprobe *p)
361{ 339{
340 if (!can_probe((unsigned long)p->addr))
341 return -EILSEQ;
362 /* insn: must be on special executable page on x86. */ 342 /* insn: must be on special executable page on x86. */
363 p->ainsn.insn = get_insn_slot(); 343 p->ainsn.insn = get_insn_slot();
364 if (!p->ainsn.insn) 344 if (!p->ainsn.insn)
@@ -472,17 +452,6 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
472{ 452{
473 switch (kcb->kprobe_status) { 453 switch (kcb->kprobe_status) {
474 case KPROBE_HIT_SSDONE: 454 case KPROBE_HIT_SSDONE:
475#ifdef CONFIG_X86_64
476 /* TODO: Provide re-entrancy from post_kprobes_handler() and
477 * avoid exception stack corruption while single-stepping on
478 * the instruction of the new probe.
479 */
480 arch_disarm_kprobe(p);
481 regs->ip = (unsigned long)p->addr;
482 reset_current_kprobe();
483 preempt_enable_no_resched();
484 break;
485#endif
486 case KPROBE_HIT_ACTIVE: 455 case KPROBE_HIT_ACTIVE:
487 save_previous_kprobe(kcb); 456 save_previous_kprobe(kcb);
488 set_current_kprobe(p, regs, kcb); 457 set_current_kprobe(p, regs, kcb);
@@ -491,18 +460,16 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
491 kcb->kprobe_status = KPROBE_REENTER; 460 kcb->kprobe_status = KPROBE_REENTER;
492 break; 461 break;
493 case KPROBE_HIT_SS: 462 case KPROBE_HIT_SS:
494 if (p == kprobe_running()) { 463 /* A probe has been hit in the codepath leading up to, or just
495 regs->flags &= ~X86_EFLAGS_TF; 464 * after, single-stepping of a probed instruction. This entire
496 regs->flags |= kcb->kprobe_saved_flags; 465 * codepath should strictly reside in .kprobes.text section.
497 return 0; 466 * Raise a BUG or we'll continue in an endless reentering loop
498 } else { 467 * and eventually a stack overflow.
499 /* A probe has been hit in the codepath leading up 468 */
500 * to, or just after, single-stepping of a probed 469 printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
501 * instruction. This entire codepath should strictly 470 p->addr);
502 * reside in .kprobes.text section. Raise a warning 471 dump_kprobe(p);
503 * to highlight this peculiar case. 472 BUG();
504 */
505 }
506 default: 473 default:
507 /* impossible cases */ 474 /* impossible cases */
508 WARN_ON(1); 475 WARN_ON(1);
@@ -967,8 +934,14 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
967 ret = NOTIFY_STOP; 934 ret = NOTIFY_STOP;
968 break; 935 break;
969 case DIE_DEBUG: 936 case DIE_DEBUG:
970 if (post_kprobe_handler(args->regs)) 937 if (post_kprobe_handler(args->regs)) {
938 /*
939 * Reset the BS bit in dr6 (pointed by args->err) to
940 * denote completion of processing
941 */
942 (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
971 ret = NOTIFY_STOP; 943 ret = NOTIFY_STOP;
944 }
972 break; 945 break;
973 case DIE_GPF: 946 case DIE_GPF:
974 /* 947 /*
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index c1c429d00130..c843f8406da2 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -25,6 +25,7 @@
25#include <asm/desc.h> 25#include <asm/desc.h>
26#include <asm/system.h> 26#include <asm/system.h>
27#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
28#include <asm/debugreg.h>
28 29
29static void set_idt(void *newidt, __u16 limit) 30static void set_idt(void *newidt, __u16 limit)
30{ 31{
@@ -202,6 +203,7 @@ void machine_kexec(struct kimage *image)
202 203
203 /* Interrupts aren't acceptable while we reboot */ 204 /* Interrupts aren't acceptable while we reboot */
204 local_irq_disable(); 205 local_irq_disable();
206 hw_breakpoint_disable();
205 207
206 if (image->preserve_context) { 208 if (image->preserve_context) {
207#ifdef CONFIG_X86_IO_APIC 209#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 84c3bf209e98..4a8bb82248ae 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -18,6 +18,7 @@
18#include <asm/pgtable.h> 18#include <asm/pgtable.h>
19#include <asm/tlbflush.h> 19#include <asm/tlbflush.h>
20#include <asm/mmu_context.h> 20#include <asm/mmu_context.h>
21#include <asm/debugreg.h>
21 22
22static int init_one_level2_page(struct kimage *image, pgd_t *pgd, 23static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
23 unsigned long addr) 24 unsigned long addr)
@@ -282,6 +283,7 @@ void machine_kexec(struct kimage *image)
282 283
283 /* Interrupts aren't acceptable while we reboot */ 284 /* Interrupts aren't acceptable while we reboot */
284 local_irq_disable(); 285 local_irq_disable();
286 hw_breakpoint_disable();
285 287
286 if (image->preserve_context) { 288 if (image->preserve_context) {
287#ifdef CONFIG_X86_IO_APIC 289#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 378e9a8f1bf8..2bcad3926edb 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -73,7 +73,6 @@
73#include <linux/platform_device.h> 73#include <linux/platform_device.h>
74#include <linux/miscdevice.h> 74#include <linux/miscdevice.h>
75#include <linux/capability.h> 75#include <linux/capability.h>
76#include <linux/smp_lock.h>
77#include <linux/kernel.h> 76#include <linux/kernel.h>
78#include <linux/module.h> 77#include <linux/module.h>
79#include <linux/mutex.h> 78#include <linux/mutex.h>
@@ -201,7 +200,6 @@ static int do_microcode_update(const void __user *buf, size_t size)
201 200
202static int microcode_open(struct inode *unused1, struct file *unused2) 201static int microcode_open(struct inode *unused1, struct file *unused2)
203{ 202{
204 cycle_kernel_lock();
205 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; 203 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
206} 204}
207 205
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 6a3cefc7dda1..553449951b84 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -174,21 +174,17 @@ static int msr_open(struct inode *inode, struct file *file)
174{ 174{
175 unsigned int cpu = iminor(file->f_path.dentry->d_inode); 175 unsigned int cpu = iminor(file->f_path.dentry->d_inode);
176 struct cpuinfo_x86 *c = &cpu_data(cpu); 176 struct cpuinfo_x86 *c = &cpu_data(cpu);
177 int ret = 0;
178 177
179 lock_kernel();
180 cpu = iminor(file->f_path.dentry->d_inode); 178 cpu = iminor(file->f_path.dentry->d_inode);
181 179
182 if (cpu >= nr_cpu_ids || !cpu_online(cpu)) { 180 if (cpu >= nr_cpu_ids || !cpu_online(cpu))
183 ret = -ENXIO; /* No such CPU */ 181 return -ENXIO; /* No such CPU */
184 goto out; 182
185 }
186 c = &cpu_data(cpu); 183 c = &cpu_data(cpu);
187 if (!cpu_has(c, X86_FEATURE_MSR)) 184 if (!cpu_has(c, X86_FEATURE_MSR))
188 ret = -EIO; /* MSR not supported */ 185 return -EIO; /* MSR not supported */
189out: 186
190 unlock_kernel(); 187 return 0;
191 return ret;
192} 188}
193 189
194/* 190/*
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 5284cd2b5776..744508e7cfdd 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -10,6 +10,7 @@
10#include <linux/clockchips.h> 10#include <linux/clockchips.h>
11#include <linux/random.h> 11#include <linux/random.h>
12#include <trace/events/power.h> 12#include <trace/events/power.h>
13#include <linux/hw_breakpoint.h>
13#include <asm/system.h> 14#include <asm/system.h>
14#include <asm/apic.h> 15#include <asm/apic.h>
15#include <asm/syscalls.h> 16#include <asm/syscalls.h>
@@ -17,6 +18,7 @@
17#include <asm/uaccess.h> 18#include <asm/uaccess.h>
18#include <asm/i387.h> 19#include <asm/i387.h>
19#include <asm/ds.h> 20#include <asm/ds.h>
21#include <asm/debugreg.h>
20 22
21unsigned long idle_halt; 23unsigned long idle_halt;
22EXPORT_SYMBOL(idle_halt); 24EXPORT_SYMBOL(idle_halt);
@@ -103,14 +105,7 @@ void flush_thread(void)
103 } 105 }
104#endif 106#endif
105 107
106 clear_tsk_thread_flag(tsk, TIF_DEBUG); 108 flush_ptrace_hw_breakpoint(tsk);
107
108 tsk->thread.debugreg0 = 0;
109 tsk->thread.debugreg1 = 0;
110 tsk->thread.debugreg2 = 0;
111 tsk->thread.debugreg3 = 0;
112 tsk->thread.debugreg6 = 0;
113 tsk->thread.debugreg7 = 0;
114 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); 109 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
115 /* 110 /*
116 * Forget coprocessor state.. 111 * Forget coprocessor state..
@@ -192,16 +187,6 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
192 else if (next->debugctlmsr != prev->debugctlmsr) 187 else if (next->debugctlmsr != prev->debugctlmsr)
193 update_debugctlmsr(next->debugctlmsr); 188 update_debugctlmsr(next->debugctlmsr);
194 189
195 if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
196 set_debugreg(next->debugreg0, 0);
197 set_debugreg(next->debugreg1, 1);
198 set_debugreg(next->debugreg2, 2);
199 set_debugreg(next->debugreg3, 3);
200 /* no 4 and 5 */
201 set_debugreg(next->debugreg6, 6);
202 set_debugreg(next->debugreg7, 7);
203 }
204
205 if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ 190 if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
206 test_tsk_thread_flag(next_p, TIF_NOTSC)) { 191 test_tsk_thread_flag(next_p, TIF_NOTSC)) {
207 /* prev and next are different */ 192 /* prev and next are different */
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 4cf79567cdab..075580b35682 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -58,6 +58,7 @@
58#include <asm/idle.h> 58#include <asm/idle.h>
59#include <asm/syscalls.h> 59#include <asm/syscalls.h>
60#include <asm/ds.h> 60#include <asm/ds.h>
61#include <asm/debugreg.h>
61 62
62asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 63asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
63 64
@@ -134,7 +135,7 @@ void __show_regs(struct pt_regs *regs, int all)
134 ss = regs->ss & 0xffff; 135 ss = regs->ss & 0xffff;
135 gs = get_user_gs(regs); 136 gs = get_user_gs(regs);
136 } else { 137 } else {
137 sp = (unsigned long) (&regs->sp); 138 sp = kernel_stack_pointer(regs);
138 savesegment(ss, ss); 139 savesegment(ss, ss);
139 savesegment(gs, gs); 140 savesegment(gs, gs);
140 } 141 }
@@ -187,7 +188,7 @@ void __show_regs(struct pt_regs *regs, int all)
187 188
188void show_regs(struct pt_regs *regs) 189void show_regs(struct pt_regs *regs)
189{ 190{
190 __show_regs(regs, 1); 191 show_registers(regs);
191 show_trace(NULL, regs, &regs->sp, regs->bp); 192 show_trace(NULL, regs, &regs->sp, regs->bp);
192} 193}
193 194
@@ -259,7 +260,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
259 260
260 task_user_gs(p) = get_user_gs(regs); 261 task_user_gs(p) = get_user_gs(regs);
261 262
263 p->thread.io_bitmap_ptr = NULL;
262 tsk = current; 264 tsk = current;
265 err = -ENOMEM;
266
267 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
268
263 if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { 269 if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
264 p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr, 270 p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
265 IO_BITMAP_BYTES, GFP_KERNEL); 271 IO_BITMAP_BYTES, GFP_KERNEL);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index eb62cbcaa490..a98fe88fab64 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -52,6 +52,7 @@
52#include <asm/idle.h> 52#include <asm/idle.h>
53#include <asm/syscalls.h> 53#include <asm/syscalls.h>
54#include <asm/ds.h> 54#include <asm/ds.h>
55#include <asm/debugreg.h>
55 56
56asmlinkage extern void ret_from_fork(void); 57asmlinkage extern void ret_from_fork(void);
57 58
@@ -226,8 +227,7 @@ void __show_regs(struct pt_regs *regs, int all)
226 227
227void show_regs(struct pt_regs *regs) 228void show_regs(struct pt_regs *regs)
228{ 229{
229 printk(KERN_INFO "CPU %d:", smp_processor_id()); 230 show_registers(regs);
230 __show_regs(regs, 1);
231 show_trace(NULL, regs, (void *)(regs + 1), regs->bp); 231 show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
232} 232}
233 233
@@ -297,12 +297,16 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
297 297
298 p->thread.fs = me->thread.fs; 298 p->thread.fs = me->thread.fs;
299 p->thread.gs = me->thread.gs; 299 p->thread.gs = me->thread.gs;
300 p->thread.io_bitmap_ptr = NULL;
300 301
301 savesegment(gs, p->thread.gsindex); 302 savesegment(gs, p->thread.gsindex);
302 savesegment(fs, p->thread.fsindex); 303 savesegment(fs, p->thread.fsindex);
303 savesegment(es, p->thread.es); 304 savesegment(es, p->thread.es);
304 savesegment(ds, p->thread.ds); 305 savesegment(ds, p->thread.ds);
305 306
307 err = -ENOMEM;
308 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
309
306 if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { 310 if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
307 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); 311 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
308 if (!p->thread.io_bitmap_ptr) { 312 if (!p->thread.io_bitmap_ptr) {
@@ -341,6 +345,7 @@ out:
341 kfree(p->thread.io_bitmap_ptr); 345 kfree(p->thread.io_bitmap_ptr);
342 p->thread.io_bitmap_max = 0; 346 p->thread.io_bitmap_max = 0;
343 } 347 }
348
344 return err; 349 return err;
345} 350}
346 351
@@ -495,6 +500,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
495 */ 500 */
496 if (preload_fpu) 501 if (preload_fpu)
497 __math_state_restore(); 502 __math_state_restore();
503
498 return prev_p; 504 return prev_p;
499} 505}
500 506
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 7b058a2dc66a..04d182a7cfdb 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -22,6 +22,8 @@
22#include <linux/seccomp.h> 22#include <linux/seccomp.h>
23#include <linux/signal.h> 23#include <linux/signal.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/perf_event.h>
26#include <linux/hw_breakpoint.h>
25 27
26#include <asm/uaccess.h> 28#include <asm/uaccess.h>
27#include <asm/pgtable.h> 29#include <asm/pgtable.h>
@@ -34,6 +36,7 @@
34#include <asm/prctl.h> 36#include <asm/prctl.h>
35#include <asm/proto.h> 37#include <asm/proto.h>
36#include <asm/ds.h> 38#include <asm/ds.h>
39#include <asm/hw_breakpoint.h>
37 40
38#include "tls.h" 41#include "tls.h"
39 42
@@ -49,6 +52,118 @@ enum x86_regset {
49 REGSET_IOPERM32, 52 REGSET_IOPERM32,
50}; 53};
51 54
55struct pt_regs_offset {
56 const char *name;
57 int offset;
58};
59
60#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
61#define REG_OFFSET_END {.name = NULL, .offset = 0}
62
63static const struct pt_regs_offset regoffset_table[] = {
64#ifdef CONFIG_X86_64
65 REG_OFFSET_NAME(r15),
66 REG_OFFSET_NAME(r14),
67 REG_OFFSET_NAME(r13),
68 REG_OFFSET_NAME(r12),
69 REG_OFFSET_NAME(r11),
70 REG_OFFSET_NAME(r10),
71 REG_OFFSET_NAME(r9),
72 REG_OFFSET_NAME(r8),
73#endif
74 REG_OFFSET_NAME(bx),
75 REG_OFFSET_NAME(cx),
76 REG_OFFSET_NAME(dx),
77 REG_OFFSET_NAME(si),
78 REG_OFFSET_NAME(di),
79 REG_OFFSET_NAME(bp),
80 REG_OFFSET_NAME(ax),
81#ifdef CONFIG_X86_32
82 REG_OFFSET_NAME(ds),
83 REG_OFFSET_NAME(es),
84 REG_OFFSET_NAME(fs),
85 REG_OFFSET_NAME(gs),
86#endif
87 REG_OFFSET_NAME(orig_ax),
88 REG_OFFSET_NAME(ip),
89 REG_OFFSET_NAME(cs),
90 REG_OFFSET_NAME(flags),
91 REG_OFFSET_NAME(sp),
92 REG_OFFSET_NAME(ss),
93 REG_OFFSET_END,
94};
95
96/**
97 * regs_query_register_offset() - query register offset from its name
98 * @name: the name of a register
99 *
100 * regs_query_register_offset() returns the offset of a register in struct
101 * pt_regs from its name. If the name is invalid, this returns -EINVAL;
102 */
103int regs_query_register_offset(const char *name)
104{
105 const struct pt_regs_offset *roff;
106 for (roff = regoffset_table; roff->name != NULL; roff++)
107 if (!strcmp(roff->name, name))
108 return roff->offset;
109 return -EINVAL;
110}
111
112/**
113 * regs_query_register_name() - query register name from its offset
114 * @offset: the offset of a register in struct pt_regs.
115 *
116 * regs_query_register_name() returns the name of a register from its
117 * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
118 */
119const char *regs_query_register_name(unsigned int offset)
120{
121 const struct pt_regs_offset *roff;
122 for (roff = regoffset_table; roff->name != NULL; roff++)
123 if (roff->offset == offset)
124 return roff->name;
125 return NULL;
126}
127
128static const int arg_offs_table[] = {
129#ifdef CONFIG_X86_32
130 [0] = offsetof(struct pt_regs, ax),
131 [1] = offsetof(struct pt_regs, dx),
132 [2] = offsetof(struct pt_regs, cx)
133#else /* CONFIG_X86_64 */
134 [0] = offsetof(struct pt_regs, di),
135 [1] = offsetof(struct pt_regs, si),
136 [2] = offsetof(struct pt_regs, dx),
137 [3] = offsetof(struct pt_regs, cx),
138 [4] = offsetof(struct pt_regs, r8),
139 [5] = offsetof(struct pt_regs, r9)
140#endif
141};
142
143/**
144 * regs_get_argument_nth() - get Nth argument at function call
145 * @regs: pt_regs which contains registers at function entry.
146 * @n: argument number.
147 *
148 * regs_get_argument_nth() returns @n th argument of a function call.
149 * Since usually the kernel stack will be changed right after function entry,
150 * you must use this at function entry. If the @n th entry is NOT in the
151 * kernel stack or pt_regs, this returns 0.
152 */
153unsigned long regs_get_argument_nth(struct pt_regs *regs, unsigned int n)
154{
155 if (n < ARRAY_SIZE(arg_offs_table))
156 return *(unsigned long *)((char *)regs + arg_offs_table[n]);
157 else {
158 /*
159 * The typical case: arg n is on the stack.
160 * (Note: stack[0] = return address, so skip it)
161 */
162 n -= ARRAY_SIZE(arg_offs_table);
163 return regs_get_kernel_stack_nth(regs, 1 + n);
164 }
165}
166
52/* 167/*
53 * does not yet catch signals sent when the child dies. 168 * does not yet catch signals sent when the child dies.
54 * in exit.c or in signal.c. 169 * in exit.c or in signal.c.
@@ -137,11 +252,6 @@ static int set_segment_reg(struct task_struct *task,
137 return 0; 252 return 0;
138} 253}
139 254
140static unsigned long debugreg_addr_limit(struct task_struct *task)
141{
142 return TASK_SIZE - 3;
143}
144
145#else /* CONFIG_X86_64 */ 255#else /* CONFIG_X86_64 */
146 256
147#define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT) 257#define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT)
@@ -266,15 +376,6 @@ static int set_segment_reg(struct task_struct *task,
266 return 0; 376 return 0;
267} 377}
268 378
269static unsigned long debugreg_addr_limit(struct task_struct *task)
270{
271#ifdef CONFIG_IA32_EMULATION
272 if (test_tsk_thread_flag(task, TIF_IA32))
273 return IA32_PAGE_OFFSET - 3;
274#endif
275 return TASK_SIZE_MAX - 7;
276}
277
278#endif /* CONFIG_X86_32 */ 379#endif /* CONFIG_X86_32 */
279 380
280static unsigned long get_flags(struct task_struct *task) 381static unsigned long get_flags(struct task_struct *task)
@@ -454,99 +555,239 @@ static int genregs_set(struct task_struct *target,
454 return ret; 555 return ret;
455} 556}
456 557
558static void ptrace_triggered(struct perf_event *bp, void *data)
559{
560 int i;
561 struct thread_struct *thread = &(current->thread);
562
563 /*
564 * Store in the virtual DR6 register the fact that the breakpoint
565 * was hit so the thread's debugger will see it.
566 */
567 for (i = 0; i < HBP_NUM; i++) {
568 if (thread->ptrace_bps[i] == bp)
569 break;
570 }
571
572 thread->debugreg6 |= (DR_TRAP0 << i);
573}
574
457/* 575/*
458 * This function is trivial and will be inlined by the compiler. 576 * Walk through every ptrace breakpoints for this thread and
459 * Having it separates the implementation details of debug 577 * build the dr7 value on top of their attributes.
460 * registers from the interface details of ptrace. 578 *
461 */ 579 */
462static unsigned long ptrace_get_debugreg(struct task_struct *child, int n) 580static unsigned long ptrace_get_dr7(struct perf_event *bp[])
463{ 581{
464 switch (n) { 582 int i;
465 case 0: return child->thread.debugreg0; 583 int dr7 = 0;
466 case 1: return child->thread.debugreg1; 584 struct arch_hw_breakpoint *info;
467 case 2: return child->thread.debugreg2; 585
468 case 3: return child->thread.debugreg3; 586 for (i = 0; i < HBP_NUM; i++) {
469 case 6: return child->thread.debugreg6; 587 if (bp[i] && !bp[i]->attr.disabled) {
470 case 7: return child->thread.debugreg7; 588 info = counter_arch_bp(bp[i]);
589 dr7 |= encode_dr7(i, info->len, info->type);
590 }
471 } 591 }
472 return 0; 592
593 return dr7;
473} 594}
474 595
475static int ptrace_set_debugreg(struct task_struct *child, 596static struct perf_event *
476 int n, unsigned long data) 597ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
598 struct task_struct *tsk, int disabled)
477{ 599{
478 int i; 600 int err;
601 int gen_len, gen_type;
602 DEFINE_BREAKPOINT_ATTR(attr);
479 603
480 if (unlikely(n == 4 || n == 5)) 604 /*
481 return -EIO; 605 * We shoud have at least an inactive breakpoint at this
606 * slot. It means the user is writing dr7 without having
607 * written the address register first
608 */
609 if (!bp)
610 return ERR_PTR(-EINVAL);
482 611
483 if (n < 4 && unlikely(data >= debugreg_addr_limit(child))) 612 err = arch_bp_generic_fields(len, type, &gen_len, &gen_type);
484 return -EIO; 613 if (err)
614 return ERR_PTR(err);
485 615
486 switch (n) { 616 attr = bp->attr;
487 case 0: child->thread.debugreg0 = data; break; 617 attr.bp_len = gen_len;
488 case 1: child->thread.debugreg1 = data; break; 618 attr.bp_type = gen_type;
489 case 2: child->thread.debugreg2 = data; break; 619 attr.disabled = disabled;
490 case 3: child->thread.debugreg3 = data; break;
491 620
492 case 6: 621 return modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk);
493 if ((data & ~0xffffffffUL) != 0) 622}
494 return -EIO; 623
495 child->thread.debugreg6 = data; 624/*
496 break; 625 * Handle ptrace writes to debug register 7.
626 */
627static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
628{
629 struct thread_struct *thread = &(tsk->thread);
630 unsigned long old_dr7;
631 int i, orig_ret = 0, rc = 0;
632 int enabled, second_pass = 0;
633 unsigned len, type;
634 struct perf_event *bp;
635
636 data &= ~DR_CONTROL_RESERVED;
637 old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
638restore:
639 /*
640 * Loop through all the hardware breakpoints, making the
641 * appropriate changes to each.
642 */
643 for (i = 0; i < HBP_NUM; i++) {
644 enabled = decode_dr7(data, i, &len, &type);
645 bp = thread->ptrace_bps[i];
646
647 if (!enabled) {
648 if (bp) {
649 /*
650 * Don't unregister the breakpoints right-away,
651 * unless all register_user_hw_breakpoint()
652 * requests have succeeded. This prevents
653 * any window of opportunity for debug
654 * register grabbing by other users.
655 */
656 if (!second_pass)
657 continue;
658
659 thread->ptrace_bps[i] = NULL;
660 bp = ptrace_modify_breakpoint(bp, len, type,
661 tsk, 1);
662 if (IS_ERR(bp)) {
663 rc = PTR_ERR(bp);
664 thread->ptrace_bps[i] = NULL;
665 break;
666 }
667 thread->ptrace_bps[i] = bp;
668 }
669 continue;
670 }
671
672 bp = ptrace_modify_breakpoint(bp, len, type, tsk, 0);
673
674 /* Incorrect bp, or we have a bug in bp API */
675 if (IS_ERR(bp)) {
676 rc = PTR_ERR(bp);
677 thread->ptrace_bps[i] = NULL;
678 break;
679 }
680 thread->ptrace_bps[i] = bp;
681 }
682 /*
683 * Make a second pass to free the remaining unused breakpoints
684 * or to restore the original breakpoints if an error occurred.
685 */
686 if (!second_pass) {
687 second_pass = 1;
688 if (rc < 0) {
689 orig_ret = rc;
690 data = old_dr7;
691 }
692 goto restore;
693 }
694 return ((orig_ret < 0) ? orig_ret : rc);
695}
696
697/*
698 * Handle PTRACE_PEEKUSR calls for the debug register area.
699 */
700static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)
701{
702 struct thread_struct *thread = &(tsk->thread);
703 unsigned long val = 0;
497 704
498 case 7: 705 if (n < HBP_NUM) {
706 struct perf_event *bp;
707 bp = thread->ptrace_bps[n];
708 if (!bp)
709 return 0;
710 val = bp->hw.info.address;
711 } else if (n == 6) {
712 val = thread->debugreg6;
713 } else if (n == 7) {
714 val = ptrace_get_dr7(thread->ptrace_bps);
715 }
716 return val;
717}
718
719static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
720 unsigned long addr)
721{
722 struct perf_event *bp;
723 struct thread_struct *t = &tsk->thread;
724 DEFINE_BREAKPOINT_ATTR(attr);
725
726 if (!t->ptrace_bps[nr]) {
499 /* 727 /*
500 * Sanity-check data. Take one half-byte at once with 728 * Put stub len and type to register (reserve) an inactive but
501 * check = (val >> (16 + 4*i)) & 0xf. It contains the 729 * correct bp
502 * R/Wi and LENi bits; bits 0 and 1 are R/Wi, and bits
503 * 2 and 3 are LENi. Given a list of invalid values,
504 * we do mask |= 1 << invalid_value, so that
505 * (mask >> check) & 1 is a correct test for invalid
506 * values.
507 *
508 * R/Wi contains the type of the breakpoint /
509 * watchpoint, LENi contains the length of the watched
510 * data in the watchpoint case.
511 *
512 * The invalid values are:
513 * - LENi == 0x10 (undefined), so mask |= 0x0f00. [32-bit]
514 * - R/Wi == 0x10 (break on I/O reads or writes), so
515 * mask |= 0x4444.
516 * - R/Wi == 0x00 && LENi != 0x00, so we have mask |=
517 * 0x1110.
518 *
519 * Finally, mask = 0x0f00 | 0x4444 | 0x1110 == 0x5f54.
520 *
521 * See the Intel Manual "System Programming Guide",
522 * 15.2.4
523 *
524 * Note that LENi == 0x10 is defined on x86_64 in long
525 * mode (i.e. even for 32-bit userspace software, but
526 * 64-bit kernel), so the x86_64 mask value is 0x5454.
527 * See the AMD manual no. 24593 (AMD64 System Programming)
528 */ 730 */
529#ifdef CONFIG_X86_32 731 attr.bp_addr = addr;
530#define DR7_MASK 0x5f54 732 attr.bp_len = HW_BREAKPOINT_LEN_1;
531#else 733 attr.bp_type = HW_BREAKPOINT_W;
532#define DR7_MASK 0x5554 734 attr.disabled = 1;
533#endif 735
534 data &= ~DR_CONTROL_RESERVED; 736 bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
535 for (i = 0; i < 4; i++) 737 } else {
536 if ((DR7_MASK >> ((data >> (16 + 4*i)) & 0xf)) & 1) 738 bp = t->ptrace_bps[nr];
537 return -EIO; 739 t->ptrace_bps[nr] = NULL;
538 child->thread.debugreg7 = data; 740
539 if (data) 741 attr = bp->attr;
540 set_tsk_thread_flag(child, TIF_DEBUG); 742 attr.bp_addr = addr;
541 else 743 bp = modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk);
542 clear_tsk_thread_flag(child, TIF_DEBUG);
543 break;
544 } 744 }
745 /*
746 * CHECKME: the previous code returned -EIO if the addr wasn't a
747 * valid task virtual addr. The new one will return -EINVAL in this
748 * case.
749 * -EINVAL may be what we want for in-kernel breakpoints users, but
750 * -EIO looks better for ptrace, since we refuse a register writing
751 * for the user. And anyway this is the previous behaviour.
752 */
753 if (IS_ERR(bp))
754 return PTR_ERR(bp);
755
756 t->ptrace_bps[nr] = bp;
545 757
546 return 0; 758 return 0;
547} 759}
548 760
549/* 761/*
762 * Handle PTRACE_POKEUSR calls for the debug register area.
763 */
764int ptrace_set_debugreg(struct task_struct *tsk, int n, unsigned long val)
765{
766 struct thread_struct *thread = &(tsk->thread);
767 int rc = 0;
768
769 /* There are no DR4 or DR5 registers */
770 if (n == 4 || n == 5)
771 return -EIO;
772
773 if (n == 6) {
774 thread->debugreg6 = val;
775 goto ret_path;
776 }
777 if (n < HBP_NUM) {
778 rc = ptrace_set_breakpoint_addr(tsk, n, val);
779 if (rc)
780 return rc;
781 }
782 /* All that's left is DR7 */
783 if (n == 7)
784 rc = ptrace_write_dr7(tsk, val);
785
786ret_path:
787 return rc;
788}
789
790/*
550 * These access the current or another (stopped) task's io permission 791 * These access the current or another (stopped) task's io permission
551 * bitmap for debugging or core dump. 792 * bitmap for debugging or core dump.
552 */ 793 */
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 2a34f9c5be21..82e88cdda9bc 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -109,6 +109,7 @@
109#ifdef CONFIG_X86_64 109#ifdef CONFIG_X86_64
110#include <asm/numa_64.h> 110#include <asm/numa_64.h>
111#endif 111#endif
112#include <asm/mce.h>
112 113
113/* 114/*
114 * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. 115 * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -247,7 +248,7 @@ EXPORT_SYMBOL(edd);
247 * from boot_params into a safe place. 248 * from boot_params into a safe place.
248 * 249 *
249 */ 250 */
250static inline void copy_edd(void) 251static inline void __init copy_edd(void)
251{ 252{
252 memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer, 253 memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
253 sizeof(edd.mbr_signature)); 254 sizeof(edd.mbr_signature));
@@ -256,7 +257,7 @@ static inline void copy_edd(void)
256 edd.edd_info_nr = boot_params.eddbuf_entries; 257 edd.edd_info_nr = boot_params.eddbuf_entries;
257} 258}
258#else 259#else
259static inline void copy_edd(void) 260static inline void __init copy_edd(void)
260{ 261{
261} 262}
262#endif 263#endif
@@ -1031,6 +1032,8 @@ void __init setup_arch(char **cmdline_p)
1031#endif 1032#endif
1032#endif 1033#endif
1033 x86_init.oem.banner(); 1034 x86_init.oem.banner();
1035
1036 mcheck_init();
1034} 1037}
1035 1038
1036#ifdef CONFIG_X86_32 1039#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 6a44a76055ad..fbf3b07c8567 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -799,15 +799,6 @@ static void do_signal(struct pt_regs *regs)
799 799
800 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 800 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
801 if (signr > 0) { 801 if (signr > 0) {
802 /*
803 * Re-enable any watchpoints before delivering the
804 * signal to user space. The processor register will
805 * have been cleared if the watchpoint triggered
806 * inside the kernel.
807 */
808 if (current->thread.debugreg7)
809 set_debugreg(current->thread.debugreg7, 7);
810
811 /* Whee! Actually deliver the signal. */ 802 /* Whee! Actually deliver the signal. */
812 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { 803 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
813 /* 804 /*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 565ebc65920e..324f2a44c221 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1250,16 +1250,7 @@ static void __ref remove_cpu_from_maps(int cpu)
1250void cpu_disable_common(void) 1250void cpu_disable_common(void)
1251{ 1251{
1252 int cpu = smp_processor_id(); 1252 int cpu = smp_processor_id();
1253 /*
1254 * HACK:
1255 * Allow any queued timer interrupts to get serviced
1256 * This is only a temporary solution until we cleanup
1257 * fixup_irqs as we do for IA64.
1258 */
1259 local_irq_enable();
1260 mdelay(1);
1261 1253
1262 local_irq_disable();
1263 remove_siblinginfo(cpu); 1254 remove_siblinginfo(cpu);
1264 1255
1265 /* It's now safe to remove this processor from the online map */ 1256 /* It's now safe to remove this processor from the online map */
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 7e37dcee0cc3..33399176512a 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -529,77 +529,56 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
529dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) 529dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
530{ 530{
531 struct task_struct *tsk = current; 531 struct task_struct *tsk = current;
532 unsigned long condition; 532 unsigned long dr6;
533 int si_code; 533 int si_code;
534 534
535 get_debugreg(condition, 6); 535 get_debugreg(dr6, 6);
536 536
537 /* Catch kmemcheck conditions first of all! */ 537 /* Catch kmemcheck conditions first of all! */
538 if (condition & DR_STEP && kmemcheck_trap(regs)) 538 if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
539 return; 539 return;
540 540
541 /* DR6 may or may not be cleared by the CPU */
542 set_debugreg(0, 6);
541 /* 543 /*
542 * The processor cleared BTF, so don't mark that we need it set. 544 * The processor cleared BTF, so don't mark that we need it set.
543 */ 545 */
544 clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR); 546 clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
545 tsk->thread.debugctlmsr = 0; 547 tsk->thread.debugctlmsr = 0;
546 548
547 if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, 549 /* Store the virtualized DR6 value */
548 SIGTRAP) == NOTIFY_STOP) 550 tsk->thread.debugreg6 = dr6;
551
552 if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
553 SIGTRAP) == NOTIFY_STOP)
549 return; 554 return;
550 555
551 /* It's safe to allow irq's after DR6 has been saved */ 556 /* It's safe to allow irq's after DR6 has been saved */
552 preempt_conditional_sti(regs); 557 preempt_conditional_sti(regs);
553 558
554 /* Mask out spurious debug traps due to lazy DR7 setting */ 559 if (regs->flags & X86_VM_MASK) {
555 if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { 560 handle_vm86_trap((struct kernel_vm86_regs *) regs,
556 if (!tsk->thread.debugreg7) 561 error_code, 1);
557 goto clear_dr7; 562 return;
558 } 563 }
559 564
560#ifdef CONFIG_X86_32
561 if (regs->flags & X86_VM_MASK)
562 goto debug_vm86;
563#endif
564
565 /* Save debug status register where ptrace can see it */
566 tsk->thread.debugreg6 = condition;
567
568 /* 565 /*
569 * Single-stepping through TF: make sure we ignore any events in 566 * Single-stepping through system calls: ignore any exceptions in
570 * kernel space (but re-enable TF when returning to user mode). 567 * kernel space, but re-enable TF when returning to user mode.
568 *
569 * We already checked v86 mode above, so we can check for kernel mode
570 * by just checking the CPL of CS.
571 */ 571 */
572 if (condition & DR_STEP) { 572 if ((dr6 & DR_STEP) && !user_mode(regs)) {
573 if (!user_mode(regs)) 573 tsk->thread.debugreg6 &= ~DR_STEP;
574 goto clear_TF_reenable; 574 set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
575 regs->flags &= ~X86_EFLAGS_TF;
575 } 576 }
576 577 si_code = get_si_code(tsk->thread.debugreg6);
577 si_code = get_si_code(condition); 578 if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS))
578 /* Ok, finally something we can handle */ 579 send_sigtrap(tsk, regs, error_code, si_code);
579 send_sigtrap(tsk, regs, error_code, si_code);
580
581 /*
582 * Disable additional traps. They'll be re-enabled when
583 * the signal is delivered.
584 */
585clear_dr7:
586 set_debugreg(0, 7);
587 preempt_conditional_cli(regs); 580 preempt_conditional_cli(regs);
588 return;
589 581
590#ifdef CONFIG_X86_32
591debug_vm86:
592 /* reenable preemption: handle_vm86_trap() might sleep */
593 dec_preempt_count();
594 handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
595 conditional_cli(regs);
596 return;
597#endif
598
599clear_TF_reenable:
600 set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
601 regs->flags &= ~X86_EFLAGS_TF;
602 preempt_conditional_cli(regs);
603 return; 582 return;
604} 583}
605 584
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index f37930954d15..eed156851f5d 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -114,13 +114,12 @@ void __cpuinit check_tsc_sync_source(int cpu)
114 return; 114 return;
115 115
116 if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) { 116 if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
117 printk_once(KERN_INFO "Skipping synchronization checks as TSC is reliable.\n"); 117 if (cpu == (nr_cpu_ids-1) || system_state != SYSTEM_BOOTING)
118 pr_info(
119 "Skipped synchronization checks as TSC is reliable.\n");
118 return; 120 return;
119 } 121 }
120 122
121 pr_info("checking TSC synchronization [CPU#%d -> CPU#%d]:",
122 smp_processor_id(), cpu);
123
124 /* 123 /*
125 * Reset it - in case this is a second bootup: 124 * Reset it - in case this is a second bootup:
126 */ 125 */
@@ -142,12 +141,14 @@ void __cpuinit check_tsc_sync_source(int cpu)
142 cpu_relax(); 141 cpu_relax();
143 142
144 if (nr_warps) { 143 if (nr_warps) {
145 printk("\n"); 144 pr_warning("TSC synchronization [CPU#%d -> CPU#%d]:\n",
145 smp_processor_id(), cpu);
146 pr_warning("Measured %Ld cycles TSC warp between CPUs, " 146 pr_warning("Measured %Ld cycles TSC warp between CPUs, "
147 "turning off TSC clock.\n", max_warp); 147 "turning off TSC clock.\n", max_warp);
148 mark_tsc_unstable("check_tsc_sync_source failed"); 148 mark_tsc_unstable("check_tsc_sync_source failed");
149 } else { 149 } else {
150 printk(" passed.\n"); 150 pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n",
151 smp_processor_id(), cpu);
151 } 152 }
152 153
153 /* 154 /*
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c
index aeef529917e4..61d805df4c91 100644
--- a/arch/x86/kernel/uv_irq.c
+++ b/arch/x86/kernel/uv_irq.c
@@ -9,10 +9,25 @@
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/rbtree.h>
12#include <linux/irq.h> 13#include <linux/irq.h>
13 14
14#include <asm/apic.h> 15#include <asm/apic.h>
15#include <asm/uv/uv_irq.h> 16#include <asm/uv/uv_irq.h>
17#include <asm/uv/uv_hub.h>
18
19/* MMR offset and pnode of hub sourcing interrupts for a given irq */
20struct uv_irq_2_mmr_pnode{
21 struct rb_node list;
22 unsigned long offset;
23 int pnode;
24 int irq;
25};
26
27static spinlock_t uv_irq_lock;
28static struct rb_root uv_irq_root;
29
30static int uv_set_irq_affinity(unsigned int, const struct cpumask *);
16 31
17static void uv_noop(unsigned int irq) 32static void uv_noop(unsigned int irq)
18{ 33{
@@ -39,25 +54,214 @@ struct irq_chip uv_irq_chip = {
39 .unmask = uv_noop, 54 .unmask = uv_noop,
40 .eoi = uv_ack_apic, 55 .eoi = uv_ack_apic,
41 .end = uv_noop, 56 .end = uv_noop,
57 .set_affinity = uv_set_irq_affinity,
42}; 58};
43 59
44/* 60/*
61 * Add offset and pnode information of the hub sourcing interrupts to the
62 * rb tree for a specific irq.
63 */
64static int uv_set_irq_2_mmr_info(int irq, unsigned long offset, unsigned blade)
65{
66 struct rb_node **link = &uv_irq_root.rb_node;
67 struct rb_node *parent = NULL;
68 struct uv_irq_2_mmr_pnode *n;
69 struct uv_irq_2_mmr_pnode *e;
70 unsigned long irqflags;
71
72 n = kmalloc_node(sizeof(struct uv_irq_2_mmr_pnode), GFP_KERNEL,
73 uv_blade_to_memory_nid(blade));
74 if (!n)
75 return -ENOMEM;
76
77 n->irq = irq;
78 n->offset = offset;
79 n->pnode = uv_blade_to_pnode(blade);
80 spin_lock_irqsave(&uv_irq_lock, irqflags);
81 /* Find the right place in the rbtree: */
82 while (*link) {
83 parent = *link;
84 e = rb_entry(parent, struct uv_irq_2_mmr_pnode, list);
85
86 if (unlikely(irq == e->irq)) {
87 /* irq entry exists */
88 e->pnode = uv_blade_to_pnode(blade);
89 e->offset = offset;
90 spin_unlock_irqrestore(&uv_irq_lock, irqflags);
91 kfree(n);
92 return 0;
93 }
94
95 if (irq < e->irq)
96 link = &(*link)->rb_left;
97 else
98 link = &(*link)->rb_right;
99 }
100
101 /* Insert the node into the rbtree. */
102 rb_link_node(&n->list, parent, link);
103 rb_insert_color(&n->list, &uv_irq_root);
104
105 spin_unlock_irqrestore(&uv_irq_lock, irqflags);
106 return 0;
107}
108
109/* Retrieve offset and pnode information from the rb tree for a specific irq */
110int uv_irq_2_mmr_info(int irq, unsigned long *offset, int *pnode)
111{
112 struct uv_irq_2_mmr_pnode *e;
113 struct rb_node *n;
114 unsigned long irqflags;
115
116 spin_lock_irqsave(&uv_irq_lock, irqflags);
117 n = uv_irq_root.rb_node;
118 while (n) {
119 e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
120
121 if (e->irq == irq) {
122 *offset = e->offset;
123 *pnode = e->pnode;
124 spin_unlock_irqrestore(&uv_irq_lock, irqflags);
125 return 0;
126 }
127
128 if (irq < e->irq)
129 n = n->rb_left;
130 else
131 n = n->rb_right;
132 }
133 spin_unlock_irqrestore(&uv_irq_lock, irqflags);
134 return -1;
135}
136
137/*
138 * Re-target the irq to the specified CPU and enable the specified MMR located
139 * on the specified blade to allow the sending of MSIs to the specified CPU.
140 */
141static int
142arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
143 unsigned long mmr_offset, int restrict)
144{
145 const struct cpumask *eligible_cpu = cpumask_of(cpu);
146 struct irq_desc *desc = irq_to_desc(irq);
147 struct irq_cfg *cfg;
148 int mmr_pnode;
149 unsigned long mmr_value;
150 struct uv_IO_APIC_route_entry *entry;
151 int err;
152
153 BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
154 sizeof(unsigned long));
155
156 cfg = irq_cfg(irq);
157
158 err = assign_irq_vector(irq, cfg, eligible_cpu);
159 if (err != 0)
160 return err;
161
162 if (restrict == UV_AFFINITY_CPU)
163 desc->status |= IRQ_NO_BALANCING;
164 else
165 desc->status |= IRQ_MOVE_PCNTXT;
166
167 set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
168 irq_name);
169
170 mmr_value = 0;
171 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
172 entry->vector = cfg->vector;
173 entry->delivery_mode = apic->irq_delivery_mode;
174 entry->dest_mode = apic->irq_dest_mode;
175 entry->polarity = 0;
176 entry->trigger = 0;
177 entry->mask = 0;
178 entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
179
180 mmr_pnode = uv_blade_to_pnode(mmr_blade);
181 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
182
183 if (cfg->move_in_progress)
184 send_cleanup_vector(cfg);
185
186 return irq;
187}
188
189/*
190 * Disable the specified MMR located on the specified blade so that MSIs are
191 * longer allowed to be sent.
192 */
193static void arch_disable_uv_irq(int mmr_pnode, unsigned long mmr_offset)
194{
195 unsigned long mmr_value;
196 struct uv_IO_APIC_route_entry *entry;
197
198 BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
199 sizeof(unsigned long));
200
201 mmr_value = 0;
202 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
203 entry->mask = 1;
204
205 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
206}
207
208static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
209{
210 struct irq_desc *desc = irq_to_desc(irq);
211 struct irq_cfg *cfg = desc->chip_data;
212 unsigned int dest;
213 unsigned long mmr_value;
214 struct uv_IO_APIC_route_entry *entry;
215 unsigned long mmr_offset;
216 unsigned mmr_pnode;
217
218 dest = set_desc_affinity(desc, mask);
219 if (dest == BAD_APICID)
220 return -1;
221
222 mmr_value = 0;
223 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
224
225 entry->vector = cfg->vector;
226 entry->delivery_mode = apic->irq_delivery_mode;
227 entry->dest_mode = apic->irq_dest_mode;
228 entry->polarity = 0;
229 entry->trigger = 0;
230 entry->mask = 0;
231 entry->dest = dest;
232
233 /* Get previously stored MMR and pnode of hub sourcing interrupts */
234 if (uv_irq_2_mmr_info(irq, &mmr_offset, &mmr_pnode))
235 return -1;
236
237 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
238
239 if (cfg->move_in_progress)
240 send_cleanup_vector(cfg);
241
242 return 0;
243}
244
245/*
45 * Set up a mapping of an available irq and vector, and enable the specified 246 * Set up a mapping of an available irq and vector, and enable the specified
46 * MMR that defines the MSI that is to be sent to the specified CPU when an 247 * MMR that defines the MSI that is to be sent to the specified CPU when an
47 * interrupt is raised. 248 * interrupt is raised.
48 */ 249 */
49int uv_setup_irq(char *irq_name, int cpu, int mmr_blade, 250int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
50 unsigned long mmr_offset) 251 unsigned long mmr_offset, int restrict)
51{ 252{
52 int irq; 253 int irq, ret;
53 int ret; 254
255 irq = create_irq_nr(NR_IRQS_LEGACY, uv_blade_to_memory_nid(mmr_blade));
54 256
55 irq = create_irq();
56 if (irq <= 0) 257 if (irq <= 0)
57 return -EBUSY; 258 return -EBUSY;
58 259
59 ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset); 260 ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
60 if (ret != irq) 261 restrict);
262 if (ret == irq)
263 uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
264 else
61 destroy_irq(irq); 265 destroy_irq(irq);
62 266
63 return ret; 267 return ret;
@@ -71,9 +275,28 @@ EXPORT_SYMBOL_GPL(uv_setup_irq);
71 * 275 *
72 * Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq(). 276 * Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq().
73 */ 277 */
74void uv_teardown_irq(unsigned int irq, int mmr_blade, unsigned long mmr_offset) 278void uv_teardown_irq(unsigned int irq)
75{ 279{
76 arch_disable_uv_irq(mmr_blade, mmr_offset); 280 struct uv_irq_2_mmr_pnode *e;
281 struct rb_node *n;
282 unsigned long irqflags;
283
284 spin_lock_irqsave(&uv_irq_lock, irqflags);
285 n = uv_irq_root.rb_node;
286 while (n) {
287 e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
288 if (e->irq == irq) {
289 arch_disable_uv_irq(e->pnode, e->offset);
290 rb_erase(n, &uv_irq_root);
291 kfree(e);
292 break;
293 }
294 if (irq < e->irq)
295 n = n->rb_left;
296 else
297 n = n->rb_right;
298 }
299 spin_unlock_irqrestore(&uv_irq_lock, irqflags);
77 destroy_irq(irq); 300 destroy_irq(irq);
78} 301}
79EXPORT_SYMBOL_GPL(uv_teardown_irq); 302EXPORT_SYMBOL_GPL(uv_teardown_irq);
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index f068553a1b17..abda6f53e71e 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -183,7 +183,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)
183 return; 183 return;
184 } 184 }
185 185
186 apic_cpus = apic->apicid_to_cpu_present(m->apicid); 186 apic->apicid_to_cpu_present(m->apicid, &apic_cpus);
187 physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus); 187 physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
188 /* 188 /*
189 * Validate version 189 * Validate version
@@ -486,7 +486,7 @@ static void end_cobalt_irq(unsigned int irq)
486} 486}
487 487
488static struct irq_chip cobalt_irq_type = { 488static struct irq_chip cobalt_irq_type = {
489 .typename = "Cobalt-APIC", 489 .name = "Cobalt-APIC",
490 .startup = startup_cobalt_irq, 490 .startup = startup_cobalt_irq,
491 .shutdown = disable_cobalt_irq, 491 .shutdown = disable_cobalt_irq,
492 .enable = enable_cobalt_irq, 492 .enable = enable_cobalt_irq,
@@ -523,7 +523,7 @@ static void end_piix4_master_irq(unsigned int irq)
523} 523}
524 524
525static struct irq_chip piix4_master_irq_type = { 525static struct irq_chip piix4_master_irq_type = {
526 .typename = "PIIX4-master", 526 .name = "PIIX4-master",
527 .startup = startup_piix4_master_irq, 527 .startup = startup_piix4_master_irq,
528 .ack = ack_cobalt_irq, 528 .ack = ack_cobalt_irq,
529 .end = end_piix4_master_irq, 529 .end = end_piix4_master_irq,
@@ -531,7 +531,7 @@ static struct irq_chip piix4_master_irq_type = {
531 531
532 532
533static struct irq_chip piix4_virtual_irq_type = { 533static struct irq_chip piix4_virtual_irq_type = {
534 .typename = "PIIX4-virtual", 534 .name = "PIIX4-virtual",
535 .shutdown = disable_8259A_irq, 535 .shutdown = disable_8259A_irq,
536 .enable = enable_8259A_irq, 536 .enable = enable_8259A_irq,
537 .disable = disable_8259A_irq, 537 .disable = disable_8259A_irq,
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 8cb4974ff599..e02d92d12bcd 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -237,7 +237,7 @@ static ctl_table kernel_table2[] = {
237}; 237};
238 238
239static ctl_table kernel_root_table2[] = { 239static ctl_table kernel_root_table2[] = {
240 { .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555, 240 { .procname = "kernel", .mode = 0555,
241 .child = kernel_table2 }, 241 .child = kernel_table2 },
242 {} 242 {}
243}; 243};
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 3909e3ba5ce3..a1029769b6f2 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -30,9 +30,8 @@ EXPORT_SYMBOL(__put_user_8);
30 30
31EXPORT_SYMBOL(copy_user_generic); 31EXPORT_SYMBOL(copy_user_generic);
32EXPORT_SYMBOL(__copy_user_nocache); 32EXPORT_SYMBOL(__copy_user_nocache);
33EXPORT_SYMBOL(copy_from_user); 33EXPORT_SYMBOL(_copy_from_user);
34EXPORT_SYMBOL(copy_to_user); 34EXPORT_SYMBOL(_copy_to_user);
35EXPORT_SYMBOL(__copy_from_user_inatomic);
36 35
37EXPORT_SYMBOL(copy_page); 36EXPORT_SYMBOL(copy_page);
38EXPORT_SYMBOL(clear_page); 37EXPORT_SYMBOL(clear_page);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ae07d261527c..4fc80174191c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -42,6 +42,7 @@
42#define CREATE_TRACE_POINTS 42#define CREATE_TRACE_POINTS
43#include "trace.h" 43#include "trace.h"
44 44
45#include <asm/debugreg.h>
45#include <asm/uaccess.h> 46#include <asm/uaccess.h>
46#include <asm/msr.h> 47#include <asm/msr.h>
47#include <asm/desc.h> 48#include <asm/desc.h>
@@ -3643,14 +3644,15 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3643 trace_kvm_entry(vcpu->vcpu_id); 3644 trace_kvm_entry(vcpu->vcpu_id);
3644 kvm_x86_ops->run(vcpu, kvm_run); 3645 kvm_x86_ops->run(vcpu, kvm_run);
3645 3646
3646 if (unlikely(vcpu->arch.switch_db_regs || test_thread_flag(TIF_DEBUG))) { 3647 /*
3647 set_debugreg(current->thread.debugreg0, 0); 3648 * If the guest has used debug registers, at least dr7
3648 set_debugreg(current->thread.debugreg1, 1); 3649 * will be disabled while returning to the host.
3649 set_debugreg(current->thread.debugreg2, 2); 3650 * If we don't have active breakpoints in the host, we don't
3650 set_debugreg(current->thread.debugreg3, 3); 3651 * care about the messed up debug address registers. But if
3651 set_debugreg(current->thread.debugreg6, 6); 3652 * we have some of them active, restore the old state.
3652 set_debugreg(current->thread.debugreg7, 7); 3653 */
3653 } 3654 if (hw_breakpoint_active())
3655 hw_breakpoint_restore();
3654 3656
3655 set_bit(KVM_REQ_KICK, &vcpu->requests); 3657 set_bit(KVM_REQ_KICK, &vcpu->requests);
3656 local_irq_enable(); 3658 local_irq_enable();
diff --git a/arch/x86/lib/.gitignore b/arch/x86/lib/.gitignore
new file mode 100644
index 000000000000..8df89f0a3fe6
--- /dev/null
+++ b/arch/x86/lib/.gitignore
@@ -0,0 +1 @@
inat-tables.c
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 85f5db95c60f..a2d6472895fb 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -2,12 +2,25 @@
2# Makefile for x86 specific library files. 2# Makefile for x86 specific library files.
3# 3#
4 4
5inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
6inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
7quiet_cmd_inat_tables = GEN $@
8 cmd_inat_tables = $(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@
9
10$(obj)/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
11 $(call cmd,inat_tables)
12
13$(obj)/inat.o: $(obj)/inat-tables.c
14
15clean-files := inat-tables.c
16
5obj-$(CONFIG_SMP) := msr.o 17obj-$(CONFIG_SMP) := msr.o
6 18
7lib-y := delay.o 19lib-y := delay.o
8lib-y += thunk_$(BITS).o 20lib-y += thunk_$(BITS).o
9lib-y += usercopy_$(BITS).o getuser.o putuser.o 21lib-y += usercopy_$(BITS).o getuser.o putuser.o
10lib-y += memcpy_$(BITS).o 22lib-y += memcpy_$(BITS).o
23lib-y += insn.o inat.o
11 24
12obj-y += msr-reg.o msr-reg-export.o 25obj-y += msr-reg.o msr-reg-export.o
13 26
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 6ba0f7bb85ea..cf889d4e076a 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -65,7 +65,7 @@
65 .endm 65 .endm
66 66
67/* Standard copy_to_user with segment limit checking */ 67/* Standard copy_to_user with segment limit checking */
68ENTRY(copy_to_user) 68ENTRY(_copy_to_user)
69 CFI_STARTPROC 69 CFI_STARTPROC
70 GET_THREAD_INFO(%rax) 70 GET_THREAD_INFO(%rax)
71 movq %rdi,%rcx 71 movq %rdi,%rcx
@@ -75,10 +75,10 @@ ENTRY(copy_to_user)
75 jae bad_to_user 75 jae bad_to_user
76 ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string 76 ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
77 CFI_ENDPROC 77 CFI_ENDPROC
78ENDPROC(copy_to_user) 78ENDPROC(_copy_to_user)
79 79
80/* Standard copy_from_user with segment limit checking */ 80/* Standard copy_from_user with segment limit checking */
81ENTRY(copy_from_user) 81ENTRY(_copy_from_user)
82 CFI_STARTPROC 82 CFI_STARTPROC
83 GET_THREAD_INFO(%rax) 83 GET_THREAD_INFO(%rax)
84 movq %rsi,%rcx 84 movq %rsi,%rcx
@@ -88,7 +88,7 @@ ENTRY(copy_from_user)
88 jae bad_from_user 88 jae bad_from_user
89 ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string 89 ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
90 CFI_ENDPROC 90 CFI_ENDPROC
91ENDPROC(copy_from_user) 91ENDPROC(_copy_from_user)
92 92
93ENTRY(copy_user_generic) 93ENTRY(copy_user_generic)
94 CFI_STARTPROC 94 CFI_STARTPROC
@@ -96,12 +96,6 @@ ENTRY(copy_user_generic)
96 CFI_ENDPROC 96 CFI_ENDPROC
97ENDPROC(copy_user_generic) 97ENDPROC(copy_user_generic)
98 98
99ENTRY(__copy_from_user_inatomic)
100 CFI_STARTPROC
101 ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
102 CFI_ENDPROC
103ENDPROC(__copy_from_user_inatomic)
104
105 .section .fixup,"ax" 99 .section .fixup,"ax"
106 /* must zero dest */ 100 /* must zero dest */
107ENTRY(bad_from_user) 101ENTRY(bad_from_user)
diff --git a/arch/x86/lib/inat.c b/arch/x86/lib/inat.c
new file mode 100644
index 000000000000..46fc4ee09fc4
--- /dev/null
+++ b/arch/x86/lib/inat.c
@@ -0,0 +1,90 @@
1/*
2 * x86 instruction attribute tables
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21#include <asm/insn.h>
22
23/* Attribute tables are generated from opcode map */
24#include "inat-tables.c"
25
26/* Attribute search APIs */
27insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
28{
29 return inat_primary_table[opcode];
30}
31
32insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, insn_byte_t last_pfx,
33 insn_attr_t esc_attr)
34{
35 const insn_attr_t *table;
36 insn_attr_t lpfx_attr;
37 int n, m = 0;
38
39 n = inat_escape_id(esc_attr);
40 if (last_pfx) {
41 lpfx_attr = inat_get_opcode_attribute(last_pfx);
42 m = inat_last_prefix_id(lpfx_attr);
43 }
44 table = inat_escape_tables[n][0];
45 if (!table)
46 return 0;
47 if (inat_has_variant(table[opcode]) && m) {
48 table = inat_escape_tables[n][m];
49 if (!table)
50 return 0;
51 }
52 return table[opcode];
53}
54
55insn_attr_t inat_get_group_attribute(insn_byte_t modrm, insn_byte_t last_pfx,
56 insn_attr_t grp_attr)
57{
58 const insn_attr_t *table;
59 insn_attr_t lpfx_attr;
60 int n, m = 0;
61
62 n = inat_group_id(grp_attr);
63 if (last_pfx) {
64 lpfx_attr = inat_get_opcode_attribute(last_pfx);
65 m = inat_last_prefix_id(lpfx_attr);
66 }
67 table = inat_group_tables[n][0];
68 if (!table)
69 return inat_group_common_attribute(grp_attr);
70 if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && m) {
71 table = inat_group_tables[n][m];
72 if (!table)
73 return inat_group_common_attribute(grp_attr);
74 }
75 return table[X86_MODRM_REG(modrm)] |
76 inat_group_common_attribute(grp_attr);
77}
78
79insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
80 insn_byte_t vex_p)
81{
82 const insn_attr_t *table;
83 if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX)
84 return 0;
85 table = inat_avx_tables[vex_m][vex_p];
86 if (!table)
87 return 0;
88 return table[opcode];
89}
90
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c
new file mode 100644
index 000000000000..9f33b984d0ef
--- /dev/null
+++ b/arch/x86/lib/insn.c
@@ -0,0 +1,516 @@
1/*
2 * x86 instruction analysis
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright (C) IBM Corporation, 2002, 2004, 2009
19 */
20
21#include <linux/string.h>
22#include <asm/inat.h>
23#include <asm/insn.h>
24
25#define get_next(t, insn) \
26 ({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
27
28#define peek_next(t, insn) \
29 ({t r; r = *(t*)insn->next_byte; r; })
30
31#define peek_nbyte_next(t, insn, n) \
32 ({t r; r = *(t*)((insn)->next_byte + n); r; })
33
34/**
35 * insn_init() - initialize struct insn
36 * @insn: &struct insn to be initialized
37 * @kaddr: address (in kernel memory) of instruction (or copy thereof)
38 * @x86_64: !0 for 64-bit kernel or 64-bit app
39 */
40void insn_init(struct insn *insn, const void *kaddr, int x86_64)
41{
42 memset(insn, 0, sizeof(*insn));
43 insn->kaddr = kaddr;
44 insn->next_byte = kaddr;
45 insn->x86_64 = x86_64 ? 1 : 0;
46 insn->opnd_bytes = 4;
47 if (x86_64)
48 insn->addr_bytes = 8;
49 else
50 insn->addr_bytes = 4;
51}
52
53/**
54 * insn_get_prefixes - scan x86 instruction prefix bytes
55 * @insn: &struct insn containing instruction
56 *
57 * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
58 * to point to the (first) opcode. No effect if @insn->prefixes.got
59 * is already set.
60 */
61void insn_get_prefixes(struct insn *insn)
62{
63 struct insn_field *prefixes = &insn->prefixes;
64 insn_attr_t attr;
65 insn_byte_t b, lb;
66 int i, nb;
67
68 if (prefixes->got)
69 return;
70
71 nb = 0;
72 lb = 0;
73 b = peek_next(insn_byte_t, insn);
74 attr = inat_get_opcode_attribute(b);
75 while (inat_is_legacy_prefix(attr)) {
76 /* Skip if same prefix */
77 for (i = 0; i < nb; i++)
78 if (prefixes->bytes[i] == b)
79 goto found;
80 if (nb == 4)
81 /* Invalid instruction */
82 break;
83 prefixes->bytes[nb++] = b;
84 if (inat_is_address_size_prefix(attr)) {
85 /* address size switches 2/4 or 4/8 */
86 if (insn->x86_64)
87 insn->addr_bytes ^= 12;
88 else
89 insn->addr_bytes ^= 6;
90 } else if (inat_is_operand_size_prefix(attr)) {
91 /* oprand size switches 2/4 */
92 insn->opnd_bytes ^= 6;
93 }
94found:
95 prefixes->nbytes++;
96 insn->next_byte++;
97 lb = b;
98 b = peek_next(insn_byte_t, insn);
99 attr = inat_get_opcode_attribute(b);
100 }
101 /* Set the last prefix */
102 if (lb && lb != insn->prefixes.bytes[3]) {
103 if (unlikely(insn->prefixes.bytes[3])) {
104 /* Swap the last prefix */
105 b = insn->prefixes.bytes[3];
106 for (i = 0; i < nb; i++)
107 if (prefixes->bytes[i] == lb)
108 prefixes->bytes[i] = b;
109 }
110 insn->prefixes.bytes[3] = lb;
111 }
112
113 /* Decode REX prefix */
114 if (insn->x86_64) {
115 b = peek_next(insn_byte_t, insn);
116 attr = inat_get_opcode_attribute(b);
117 if (inat_is_rex_prefix(attr)) {
118 insn->rex_prefix.value = b;
119 insn->rex_prefix.nbytes = 1;
120 insn->next_byte++;
121 if (X86_REX_W(b))
122 /* REX.W overrides opnd_size */
123 insn->opnd_bytes = 8;
124 }
125 }
126 insn->rex_prefix.got = 1;
127
128 /* Decode VEX prefix */
129 b = peek_next(insn_byte_t, insn);
130 attr = inat_get_opcode_attribute(b);
131 if (inat_is_vex_prefix(attr)) {
132 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
133 if (!insn->x86_64) {
134 /*
135 * In 32-bits mode, if the [7:6] bits (mod bits of
136 * ModRM) on the second byte are not 11b, it is
137 * LDS or LES.
138 */
139 if (X86_MODRM_MOD(b2) != 3)
140 goto vex_end;
141 }
142 insn->vex_prefix.bytes[0] = b;
143 insn->vex_prefix.bytes[1] = b2;
144 if (inat_is_vex3_prefix(attr)) {
145 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
146 insn->vex_prefix.bytes[2] = b2;
147 insn->vex_prefix.nbytes = 3;
148 insn->next_byte += 3;
149 if (insn->x86_64 && X86_VEX_W(b2))
150 /* VEX.W overrides opnd_size */
151 insn->opnd_bytes = 8;
152 } else {
153 insn->vex_prefix.nbytes = 2;
154 insn->next_byte += 2;
155 }
156 }
157vex_end:
158 insn->vex_prefix.got = 1;
159
160 prefixes->got = 1;
161 return;
162}
163
164/**
165 * insn_get_opcode - collect opcode(s)
166 * @insn: &struct insn containing instruction
167 *
168 * Populates @insn->opcode, updates @insn->next_byte to point past the
169 * opcode byte(s), and set @insn->attr (except for groups).
170 * If necessary, first collects any preceding (prefix) bytes.
171 * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got
172 * is already 1.
173 */
174void insn_get_opcode(struct insn *insn)
175{
176 struct insn_field *opcode = &insn->opcode;
177 insn_byte_t op, pfx;
178 if (opcode->got)
179 return;
180 if (!insn->prefixes.got)
181 insn_get_prefixes(insn);
182
183 /* Get first opcode */
184 op = get_next(insn_byte_t, insn);
185 opcode->bytes[0] = op;
186 opcode->nbytes = 1;
187
188 /* Check if there is VEX prefix or not */
189 if (insn_is_avx(insn)) {
190 insn_byte_t m, p;
191 m = insn_vex_m_bits(insn);
192 p = insn_vex_p_bits(insn);
193 insn->attr = inat_get_avx_attribute(op, m, p);
194 if (!inat_accept_vex(insn->attr))
195 insn->attr = 0; /* This instruction is bad */
196 goto end; /* VEX has only 1 byte for opcode */
197 }
198
199 insn->attr = inat_get_opcode_attribute(op);
200 while (inat_is_escape(insn->attr)) {
201 /* Get escaped opcode */
202 op = get_next(insn_byte_t, insn);
203 opcode->bytes[opcode->nbytes++] = op;
204 pfx = insn_last_prefix(insn);
205 insn->attr = inat_get_escape_attribute(op, pfx, insn->attr);
206 }
207 if (inat_must_vex(insn->attr))
208 insn->attr = 0; /* This instruction is bad */
209end:
210 opcode->got = 1;
211}
212
213/**
214 * insn_get_modrm - collect ModRM byte, if any
215 * @insn: &struct insn containing instruction
216 *
217 * Populates @insn->modrm and updates @insn->next_byte to point past the
218 * ModRM byte, if any. If necessary, first collects the preceding bytes
219 * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1.
220 */
221void insn_get_modrm(struct insn *insn)
222{
223 struct insn_field *modrm = &insn->modrm;
224 insn_byte_t pfx, mod;
225 if (modrm->got)
226 return;
227 if (!insn->opcode.got)
228 insn_get_opcode(insn);
229
230 if (inat_has_modrm(insn->attr)) {
231 mod = get_next(insn_byte_t, insn);
232 modrm->value = mod;
233 modrm->nbytes = 1;
234 if (inat_is_group(insn->attr)) {
235 pfx = insn_last_prefix(insn);
236 insn->attr = inat_get_group_attribute(mod, pfx,
237 insn->attr);
238 }
239 }
240
241 if (insn->x86_64 && inat_is_force64(insn->attr))
242 insn->opnd_bytes = 8;
243 modrm->got = 1;
244}
245
246
247/**
248 * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
249 * @insn: &struct insn containing instruction
250 *
251 * If necessary, first collects the instruction up to and including the
252 * ModRM byte. No effect if @insn->x86_64 is 0.
253 */
254int insn_rip_relative(struct insn *insn)
255{
256 struct insn_field *modrm = &insn->modrm;
257
258 if (!insn->x86_64)
259 return 0;
260 if (!modrm->got)
261 insn_get_modrm(insn);
262 /*
263 * For rip-relative instructions, the mod field (top 2 bits)
264 * is zero and the r/m field (bottom 3 bits) is 0x5.
265 */
266 return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
267}
268
269/**
270 * insn_get_sib() - Get the SIB byte of instruction
271 * @insn: &struct insn containing instruction
272 *
273 * If necessary, first collects the instruction up to and including the
274 * ModRM byte.
275 */
276void insn_get_sib(struct insn *insn)
277{
278 insn_byte_t modrm;
279
280 if (insn->sib.got)
281 return;
282 if (!insn->modrm.got)
283 insn_get_modrm(insn);
284 if (insn->modrm.nbytes) {
285 modrm = (insn_byte_t)insn->modrm.value;
286 if (insn->addr_bytes != 2 &&
287 X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
288 insn->sib.value = get_next(insn_byte_t, insn);
289 insn->sib.nbytes = 1;
290 }
291 }
292 insn->sib.got = 1;
293}
294
295
296/**
297 * insn_get_displacement() - Get the displacement of instruction
298 * @insn: &struct insn containing instruction
299 *
300 * If necessary, first collects the instruction up to and including the
301 * SIB byte.
302 * Displacement value is sign-expanded.
303 */
304void insn_get_displacement(struct insn *insn)
305{
306 insn_byte_t mod, rm, base;
307
308 if (insn->displacement.got)
309 return;
310 if (!insn->sib.got)
311 insn_get_sib(insn);
312 if (insn->modrm.nbytes) {
313 /*
314 * Interpreting the modrm byte:
315 * mod = 00 - no displacement fields (exceptions below)
316 * mod = 01 - 1-byte displacement field
317 * mod = 10 - displacement field is 4 bytes, or 2 bytes if
318 * address size = 2 (0x67 prefix in 32-bit mode)
319 * mod = 11 - no memory operand
320 *
321 * If address size = 2...
322 * mod = 00, r/m = 110 - displacement field is 2 bytes
323 *
324 * If address size != 2...
325 * mod != 11, r/m = 100 - SIB byte exists
326 * mod = 00, SIB base = 101 - displacement field is 4 bytes
327 * mod = 00, r/m = 101 - rip-relative addressing, displacement
328 * field is 4 bytes
329 */
330 mod = X86_MODRM_MOD(insn->modrm.value);
331 rm = X86_MODRM_RM(insn->modrm.value);
332 base = X86_SIB_BASE(insn->sib.value);
333 if (mod == 3)
334 goto out;
335 if (mod == 1) {
336 insn->displacement.value = get_next(char, insn);
337 insn->displacement.nbytes = 1;
338 } else if (insn->addr_bytes == 2) {
339 if ((mod == 0 && rm == 6) || mod == 2) {
340 insn->displacement.value =
341 get_next(short, insn);
342 insn->displacement.nbytes = 2;
343 }
344 } else {
345 if ((mod == 0 && rm == 5) || mod == 2 ||
346 (mod == 0 && base == 5)) {
347 insn->displacement.value = get_next(int, insn);
348 insn->displacement.nbytes = 4;
349 }
350 }
351 }
352out:
353 insn->displacement.got = 1;
354}
355
356/* Decode moffset16/32/64 */
357static void __get_moffset(struct insn *insn)
358{
359 switch (insn->addr_bytes) {
360 case 2:
361 insn->moffset1.value = get_next(short, insn);
362 insn->moffset1.nbytes = 2;
363 break;
364 case 4:
365 insn->moffset1.value = get_next(int, insn);
366 insn->moffset1.nbytes = 4;
367 break;
368 case 8:
369 insn->moffset1.value = get_next(int, insn);
370 insn->moffset1.nbytes = 4;
371 insn->moffset2.value = get_next(int, insn);
372 insn->moffset2.nbytes = 4;
373 break;
374 }
375 insn->moffset1.got = insn->moffset2.got = 1;
376}
377
378/* Decode imm v32(Iz) */
379static void __get_immv32(struct insn *insn)
380{
381 switch (insn->opnd_bytes) {
382 case 2:
383 insn->immediate.value = get_next(short, insn);
384 insn->immediate.nbytes = 2;
385 break;
386 case 4:
387 case 8:
388 insn->immediate.value = get_next(int, insn);
389 insn->immediate.nbytes = 4;
390 break;
391 }
392}
393
394/* Decode imm v64(Iv/Ov) */
395static void __get_immv(struct insn *insn)
396{
397 switch (insn->opnd_bytes) {
398 case 2:
399 insn->immediate1.value = get_next(short, insn);
400 insn->immediate1.nbytes = 2;
401 break;
402 case 4:
403 insn->immediate1.value = get_next(int, insn);
404 insn->immediate1.nbytes = 4;
405 break;
406 case 8:
407 insn->immediate1.value = get_next(int, insn);
408 insn->immediate1.nbytes = 4;
409 insn->immediate2.value = get_next(int, insn);
410 insn->immediate2.nbytes = 4;
411 break;
412 }
413 insn->immediate1.got = insn->immediate2.got = 1;
414}
415
416/* Decode ptr16:16/32(Ap) */
417static void __get_immptr(struct insn *insn)
418{
419 switch (insn->opnd_bytes) {
420 case 2:
421 insn->immediate1.value = get_next(short, insn);
422 insn->immediate1.nbytes = 2;
423 break;
424 case 4:
425 insn->immediate1.value = get_next(int, insn);
426 insn->immediate1.nbytes = 4;
427 break;
428 case 8:
429 /* ptr16:64 is not exist (no segment) */
430 return;
431 }
432 insn->immediate2.value = get_next(unsigned short, insn);
433 insn->immediate2.nbytes = 2;
434 insn->immediate1.got = insn->immediate2.got = 1;
435}
436
437/**
438 * insn_get_immediate() - Get the immediates of instruction
439 * @insn: &struct insn containing instruction
440 *
441 * If necessary, first collects the instruction up to and including the
442 * displacement bytes.
443 * Basically, most of immediates are sign-expanded. Unsigned-value can be
444 * get by bit masking with ((1 << (nbytes * 8)) - 1)
445 */
446void insn_get_immediate(struct insn *insn)
447{
448 if (insn->immediate.got)
449 return;
450 if (!insn->displacement.got)
451 insn_get_displacement(insn);
452
453 if (inat_has_moffset(insn->attr)) {
454 __get_moffset(insn);
455 goto done;
456 }
457
458 if (!inat_has_immediate(insn->attr))
459 /* no immediates */
460 goto done;
461
462 switch (inat_immediate_size(insn->attr)) {
463 case INAT_IMM_BYTE:
464 insn->immediate.value = get_next(char, insn);
465 insn->immediate.nbytes = 1;
466 break;
467 case INAT_IMM_WORD:
468 insn->immediate.value = get_next(short, insn);
469 insn->immediate.nbytes = 2;
470 break;
471 case INAT_IMM_DWORD:
472 insn->immediate.value = get_next(int, insn);
473 insn->immediate.nbytes = 4;
474 break;
475 case INAT_IMM_QWORD:
476 insn->immediate1.value = get_next(int, insn);
477 insn->immediate1.nbytes = 4;
478 insn->immediate2.value = get_next(int, insn);
479 insn->immediate2.nbytes = 4;
480 break;
481 case INAT_IMM_PTR:
482 __get_immptr(insn);
483 break;
484 case INAT_IMM_VWORD32:
485 __get_immv32(insn);
486 break;
487 case INAT_IMM_VWORD:
488 __get_immv(insn);
489 break;
490 default:
491 break;
492 }
493 if (inat_has_second_immediate(insn->attr)) {
494 insn->immediate2.value = get_next(char, insn);
495 insn->immediate2.nbytes = 1;
496 }
497done:
498 insn->immediate.got = 1;
499}
500
501/**
502 * insn_get_length() - Get the length of instruction
503 * @insn: &struct insn containing instruction
504 *
505 * If necessary, first collects the instruction up to and including the
506 * immediates bytes.
507 */
508void insn_get_length(struct insn *insn)
509{
510 if (insn->length)
511 return;
512 if (!insn->immediate.got)
513 insn_get_immediate(insn);
514 insn->length = (unsigned char)((unsigned long)insn->next_byte
515 - (unsigned long)insn->kaddr);
516}
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index 33a1e3ca22d8..41628b104b9e 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -71,14 +71,9 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
71} 71}
72EXPORT_SYMBOL(wrmsr_on_cpu); 72EXPORT_SYMBOL(wrmsr_on_cpu);
73 73
74/* rdmsr on a bunch of CPUs 74static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
75 * 75 struct msr *msrs,
76 * @mask: which CPUs 76 void (*msr_func) (void *info))
77 * @msr_no: which MSR
78 * @msrs: array of MSR values
79 *
80 */
81void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
82{ 77{
83 struct msr_info rv; 78 struct msr_info rv;
84 int this_cpu; 79 int this_cpu;
@@ -92,11 +87,23 @@ void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
92 this_cpu = get_cpu(); 87 this_cpu = get_cpu();
93 88
94 if (cpumask_test_cpu(this_cpu, mask)) 89 if (cpumask_test_cpu(this_cpu, mask))
95 __rdmsr_on_cpu(&rv); 90 msr_func(&rv);
96 91
97 smp_call_function_many(mask, __rdmsr_on_cpu, &rv, 1); 92 smp_call_function_many(mask, msr_func, &rv, 1);
98 put_cpu(); 93 put_cpu();
99} 94}
95
96/* rdmsr on a bunch of CPUs
97 *
98 * @mask: which CPUs
99 * @msr_no: which MSR
100 * @msrs: array of MSR values
101 *
102 */
103void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
104{
105 __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
106}
100EXPORT_SYMBOL(rdmsr_on_cpus); 107EXPORT_SYMBOL(rdmsr_on_cpus);
101 108
102/* 109/*
@@ -107,24 +114,9 @@ EXPORT_SYMBOL(rdmsr_on_cpus);
107 * @msrs: array of MSR values 114 * @msrs: array of MSR values
108 * 115 *
109 */ 116 */
110void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs) 117void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
111{ 118{
112 struct msr_info rv; 119 __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
113 int this_cpu;
114
115 memset(&rv, 0, sizeof(rv));
116
117 rv.off = cpumask_first(mask);
118 rv.msrs = msrs;
119 rv.msr_no = msr_no;
120
121 this_cpu = get_cpu();
122
123 if (cpumask_test_cpu(this_cpu, mask))
124 __wrmsr_on_cpu(&rv);
125
126 smp_call_function_many(mask, __wrmsr_on_cpu, &rv, 1);
127 put_cpu();
128} 120}
129EXPORT_SYMBOL(wrmsr_on_cpus); 121EXPORT_SYMBOL(wrmsr_on_cpus);
130 122
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 1f118d462acc..e218d5df85ff 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -874,7 +874,7 @@ EXPORT_SYMBOL(copy_to_user);
874 * data to the requested size using zero bytes. 874 * data to the requested size using zero bytes.
875 */ 875 */
876unsigned long 876unsigned long
877copy_from_user(void *to, const void __user *from, unsigned long n) 877_copy_from_user(void *to, const void __user *from, unsigned long n)
878{ 878{
879 if (access_ok(VERIFY_READ, from, n)) 879 if (access_ok(VERIFY_READ, from, n))
880 n = __copy_from_user(to, from, n); 880 n = __copy_from_user(to, from, n);
@@ -882,4 +882,10 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
882 memset(to, 0, n); 882 memset(to, 0, n);
883 return n; 883 return n;
884} 884}
885EXPORT_SYMBOL(copy_from_user); 885EXPORT_SYMBOL(_copy_from_user);
886
887void copy_from_user_overflow(void)
888{
889 WARN(1, "Buffer overflow detected!\n");
890}
891EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt
new file mode 100644
index 000000000000..a793da5e560e
--- /dev/null
+++ b/arch/x86/lib/x86-opcode-map.txt
@@ -0,0 +1,893 @@
1# x86 Opcode Maps
2#
3#<Opcode maps>
4# Table: table-name
5# Referrer: escaped-name
6# AVXcode: avx-code
7# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
8# (or)
9# opcode: escape # escaped-name
10# EndTable
11#
12#<group maps>
13# GrpTable: GrpXXX
14# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
15# EndTable
16#
17# AVX Superscripts
18# (VEX): this opcode can accept VEX prefix.
19# (oVEX): this opcode requires VEX prefix.
20# (o128): this opcode only supports 128bit VEX.
21# (o256): this opcode only supports 256bit VEX.
22#
23
24Table: one byte opcode
25Referrer:
26AVXcode:
27# 0x00 - 0x0f
2800: ADD Eb,Gb
2901: ADD Ev,Gv
3002: ADD Gb,Eb
3103: ADD Gv,Ev
3204: ADD AL,Ib
3305: ADD rAX,Iz
3406: PUSH ES (i64)
3507: POP ES (i64)
3608: OR Eb,Gb
3709: OR Ev,Gv
380a: OR Gb,Eb
390b: OR Gv,Ev
400c: OR AL,Ib
410d: OR rAX,Iz
420e: PUSH CS (i64)
430f: escape # 2-byte escape
44# 0x10 - 0x1f
4510: ADC Eb,Gb
4611: ADC Ev,Gv
4712: ADC Gb,Eb
4813: ADC Gv,Ev
4914: ADC AL,Ib
5015: ADC rAX,Iz
5116: PUSH SS (i64)
5217: POP SS (i64)
5318: SBB Eb,Gb
5419: SBB Ev,Gv
551a: SBB Gb,Eb
561b: SBB Gv,Ev
571c: SBB AL,Ib
581d: SBB rAX,Iz
591e: PUSH DS (i64)
601f: POP DS (i64)
61# 0x20 - 0x2f
6220: AND Eb,Gb
6321: AND Ev,Gv
6422: AND Gb,Eb
6523: AND Gv,Ev
6624: AND AL,Ib
6725: AND rAx,Iz
6826: SEG=ES (Prefix)
6927: DAA (i64)
7028: SUB Eb,Gb
7129: SUB Ev,Gv
722a: SUB Gb,Eb
732b: SUB Gv,Ev
742c: SUB AL,Ib
752d: SUB rAX,Iz
762e: SEG=CS (Prefix)
772f: DAS (i64)
78# 0x30 - 0x3f
7930: XOR Eb,Gb
8031: XOR Ev,Gv
8132: XOR Gb,Eb
8233: XOR Gv,Ev
8334: XOR AL,Ib
8435: XOR rAX,Iz
8536: SEG=SS (Prefix)
8637: AAA (i64)
8738: CMP Eb,Gb
8839: CMP Ev,Gv
893a: CMP Gb,Eb
903b: CMP Gv,Ev
913c: CMP AL,Ib
923d: CMP rAX,Iz
933e: SEG=DS (Prefix)
943f: AAS (i64)
95# 0x40 - 0x4f
9640: INC eAX (i64) | REX (o64)
9741: INC eCX (i64) | REX.B (o64)
9842: INC eDX (i64) | REX.X (o64)
9943: INC eBX (i64) | REX.XB (o64)
10044: INC eSP (i64) | REX.R (o64)
10145: INC eBP (i64) | REX.RB (o64)
10246: INC eSI (i64) | REX.RX (o64)
10347: INC eDI (i64) | REX.RXB (o64)
10448: DEC eAX (i64) | REX.W (o64)
10549: DEC eCX (i64) | REX.WB (o64)
1064a: DEC eDX (i64) | REX.WX (o64)
1074b: DEC eBX (i64) | REX.WXB (o64)
1084c: DEC eSP (i64) | REX.WR (o64)
1094d: DEC eBP (i64) | REX.WRB (o64)
1104e: DEC eSI (i64) | REX.WRX (o64)
1114f: DEC eDI (i64) | REX.WRXB (o64)
112# 0x50 - 0x5f
11350: PUSH rAX/r8 (d64)
11451: PUSH rCX/r9 (d64)
11552: PUSH rDX/r10 (d64)
11653: PUSH rBX/r11 (d64)
11754: PUSH rSP/r12 (d64)
11855: PUSH rBP/r13 (d64)
11956: PUSH rSI/r14 (d64)
12057: PUSH rDI/r15 (d64)
12158: POP rAX/r8 (d64)
12259: POP rCX/r9 (d64)
1235a: POP rDX/r10 (d64)
1245b: POP rBX/r11 (d64)
1255c: POP rSP/r12 (d64)
1265d: POP rBP/r13 (d64)
1275e: POP rSI/r14 (d64)
1285f: POP rDI/r15 (d64)
129# 0x60 - 0x6f
13060: PUSHA/PUSHAD (i64)
13161: POPA/POPAD (i64)
13262: BOUND Gv,Ma (i64)
13363: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
13464: SEG=FS (Prefix)
13565: SEG=GS (Prefix)
13666: Operand-Size (Prefix)
13767: Address-Size (Prefix)
13868: PUSH Iz (d64)
13969: IMUL Gv,Ev,Iz
1406a: PUSH Ib (d64)
1416b: IMUL Gv,Ev,Ib
1426c: INS/INSB Yb,DX
1436d: INS/INSW/INSD Yz,DX
1446e: OUTS/OUTSB DX,Xb
1456f: OUTS/OUTSW/OUTSD DX,Xz
146# 0x70 - 0x7f
14770: JO Jb
14871: JNO Jb
14972: JB/JNAE/JC Jb
15073: JNB/JAE/JNC Jb
15174: JZ/JE Jb
15275: JNZ/JNE Jb
15376: JBE/JNA Jb
15477: JNBE/JA Jb
15578: JS Jb
15679: JNS Jb
1577a: JP/JPE Jb
1587b: JNP/JPO Jb
1597c: JL/JNGE Jb
1607d: JNL/JGE Jb
1617e: JLE/JNG Jb
1627f: JNLE/JG Jb
163# 0x80 - 0x8f
16480: Grp1 Eb,Ib (1A)
16581: Grp1 Ev,Iz (1A)
16682: Grp1 Eb,Ib (1A),(i64)
16783: Grp1 Ev,Ib (1A)
16884: TEST Eb,Gb
16985: TEST Ev,Gv
17086: XCHG Eb,Gb
17187: XCHG Ev,Gv
17288: MOV Eb,Gb
17389: MOV Ev,Gv
1748a: MOV Gb,Eb
1758b: MOV Gv,Ev
1768c: MOV Ev,Sw
1778d: LEA Gv,M
1788e: MOV Sw,Ew
1798f: Grp1A (1A) | POP Ev (d64)
180# 0x90 - 0x9f
18190: NOP | PAUSE (F3) | XCHG r8,rAX
18291: XCHG rCX/r9,rAX
18392: XCHG rDX/r10,rAX
18493: XCHG rBX/r11,rAX
18594: XCHG rSP/r12,rAX
18695: XCHG rBP/r13,rAX
18796: XCHG rSI/r14,rAX
18897: XCHG rDI/r15,rAX
18998: CBW/CWDE/CDQE
19099: CWD/CDQ/CQO
1919a: CALLF Ap (i64)
1929b: FWAIT/WAIT
1939c: PUSHF/D/Q Fv (d64)
1949d: POPF/D/Q Fv (d64)
1959e: SAHF
1969f: LAHF
197# 0xa0 - 0xaf
198a0: MOV AL,Ob
199a1: MOV rAX,Ov
200a2: MOV Ob,AL
201a3: MOV Ov,rAX
202a4: MOVS/B Xb,Yb
203a5: MOVS/W/D/Q Xv,Yv
204a6: CMPS/B Xb,Yb
205a7: CMPS/W/D Xv,Yv
206a8: TEST AL,Ib
207a9: TEST rAX,Iz
208aa: STOS/B Yb,AL
209ab: STOS/W/D/Q Yv,rAX
210ac: LODS/B AL,Xb
211ad: LODS/W/D/Q rAX,Xv
212ae: SCAS/B AL,Yb
213af: SCAS/W/D/Q rAX,Xv
214# 0xb0 - 0xbf
215b0: MOV AL/R8L,Ib
216b1: MOV CL/R9L,Ib
217b2: MOV DL/R10L,Ib
218b3: MOV BL/R11L,Ib
219b4: MOV AH/R12L,Ib
220b5: MOV CH/R13L,Ib
221b6: MOV DH/R14L,Ib
222b7: MOV BH/R15L,Ib
223b8: MOV rAX/r8,Iv
224b9: MOV rCX/r9,Iv
225ba: MOV rDX/r10,Iv
226bb: MOV rBX/r11,Iv
227bc: MOV rSP/r12,Iv
228bd: MOV rBP/r13,Iv
229be: MOV rSI/r14,Iv
230bf: MOV rDI/r15,Iv
231# 0xc0 - 0xcf
232c0: Grp2 Eb,Ib (1A)
233c1: Grp2 Ev,Ib (1A)
234c2: RETN Iw (f64)
235c3: RETN
236c4: LES Gz,Mp (i64) | 3bytes-VEX (Prefix)
237c5: LDS Gz,Mp (i64) | 2bytes-VEX (Prefix)
238c6: Grp11 Eb,Ib (1A)
239c7: Grp11 Ev,Iz (1A)
240c8: ENTER Iw,Ib
241c9: LEAVE (d64)
242ca: RETF Iw
243cb: RETF
244cc: INT3
245cd: INT Ib
246ce: INTO (i64)
247cf: IRET/D/Q
248# 0xd0 - 0xdf
249d0: Grp2 Eb,1 (1A)
250d1: Grp2 Ev,1 (1A)
251d2: Grp2 Eb,CL (1A)
252d3: Grp2 Ev,CL (1A)
253d4: AAM Ib (i64)
254d5: AAD Ib (i64)
255d6:
256d7: XLAT/XLATB
257d8: ESC
258d9: ESC
259da: ESC
260db: ESC
261dc: ESC
262dd: ESC
263de: ESC
264df: ESC
265# 0xe0 - 0xef
266e0: LOOPNE/LOOPNZ Jb (f64)
267e1: LOOPE/LOOPZ Jb (f64)
268e2: LOOP Jb (f64)
269e3: JrCXZ Jb (f64)
270e4: IN AL,Ib
271e5: IN eAX,Ib
272e6: OUT Ib,AL
273e7: OUT Ib,eAX
274e8: CALL Jz (f64)
275e9: JMP-near Jz (f64)
276ea: JMP-far Ap (i64)
277eb: JMP-short Jb (f64)
278ec: IN AL,DX
279ed: IN eAX,DX
280ee: OUT DX,AL
281ef: OUT DX,eAX
282# 0xf0 - 0xff
283f0: LOCK (Prefix)
284f1:
285f2: REPNE (Prefix)
286f3: REP/REPE (Prefix)
287f4: HLT
288f5: CMC
289f6: Grp3_1 Eb (1A)
290f7: Grp3_2 Ev (1A)
291f8: CLC
292f9: STC
293fa: CLI
294fb: STI
295fc: CLD
296fd: STD
297fe: Grp4 (1A)
298ff: Grp5 (1A)
299EndTable
300
301Table: 2-byte opcode (0x0f)
302Referrer: 2-byte escape
303AVXcode: 1
304# 0x0f 0x00-0x0f
30500: Grp6 (1A)
30601: Grp7 (1A)
30702: LAR Gv,Ew
30803: LSL Gv,Ew
30904:
31005: SYSCALL (o64)
31106: CLTS
31207: SYSRET (o64)
31308: INVD
31409: WBINVD
3150a:
3160b: UD2 (1B)
3170c:
3180d: NOP Ev | GrpP
3190e: FEMMS
320# 3DNow! uses the last imm byte as opcode extension.
3210f: 3DNow! Pq,Qq,Ib
322# 0x0f 0x10-0x1f
32310: movups Vps,Wps (VEX) | movss Vss,Wss (F3),(VEX),(o128) | movupd Vpd,Wpd (66),(VEX) | movsd Vsd,Wsd (F2),(VEX),(o128)
32411: movups Wps,Vps (VEX) | movss Wss,Vss (F3),(VEX),(o128) | movupd Wpd,Vpd (66),(VEX) | movsd Wsd,Vsd (F2),(VEX),(o128)
32512: movlps Vq,Mq (VEX),(o128) | movlpd Vq,Mq (66),(VEX),(o128) | movhlps Vq,Uq (VEX),(o128) | movddup Vq,Wq (F2),(VEX) | movsldup Vq,Wq (F3),(VEX)
32613: mpvlps Mq,Vq (VEX),(o128) | movlpd Mq,Vq (66),(VEX),(o128)
32714: unpcklps Vps,Wq (VEX) | unpcklpd Vpd,Wq (66),(VEX)
32815: unpckhps Vps,Wq (VEX) | unpckhpd Vpd,Wq (66),(VEX)
32916: movhps Vq,Mq (VEX),(o128) | movhpd Vq,Mq (66),(VEX),(o128) | movlsps Vq,Uq (VEX),(o128) | movshdup Vq,Wq (F3),(VEX)
33017: movhps Mq,Vq (VEX),(o128) | movhpd Mq,Vq (66),(VEX),(o128)
33118: Grp16 (1A)
33219:
3331a:
3341b:
3351c:
3361d:
3371e:
3381f: NOP Ev
339# 0x0f 0x20-0x2f
34020: MOV Rd,Cd
34121: MOV Rd,Dd
34222: MOV Cd,Rd
34323: MOV Dd,Rd
34424:
34525:
34626:
34727:
34828: movaps Vps,Wps (VEX) | movapd Vpd,Wpd (66),(VEX)
34929: movaps Wps,Vps (VEX) | movapd Wpd,Vpd (66),(VEX)
3502a: cvtpi2ps Vps,Qpi | cvtsi2ss Vss,Ed/q (F3),(VEX),(o128) | cvtpi2pd Vpd,Qpi (66) | cvtsi2sd Vsd,Ed/q (F2),(VEX),(o128)
3512b: movntps Mps,Vps (VEX) | movntpd Mpd,Vpd (66),(VEX)
3522c: cvttps2pi Ppi,Wps | cvttss2si Gd/q,Wss (F3),(VEX),(o128) | cvttpd2pi Ppi,Wpd (66) | cvttsd2si Gd/q,Wsd (F2),(VEX),(o128)
3532d: cvtps2pi Ppi,Wps | cvtss2si Gd/q,Wss (F3),(VEX),(o128) | cvtpd2pi Qpi,Wpd (66) | cvtsd2si Gd/q,Wsd (F2),(VEX),(o128)
3542e: ucomiss Vss,Wss (VEX),(o128) | ucomisd Vsd,Wsd (66),(VEX),(o128)
3552f: comiss Vss,Wss (VEX),(o128) | comisd Vsd,Wsd (66),(VEX),(o128)
356# 0x0f 0x30-0x3f
35730: WRMSR
35831: RDTSC
35932: RDMSR
36033: RDPMC
36134: SYSENTER
36235: SYSEXIT
36336:
36437: GETSEC
36538: escape # 3-byte escape 1
36639:
3673a: escape # 3-byte escape 2
3683b:
3693c:
3703d:
3713e:
3723f:
373# 0x0f 0x40-0x4f
37440: CMOVO Gv,Ev
37541: CMOVNO Gv,Ev
37642: CMOVB/C/NAE Gv,Ev
37743: CMOVAE/NB/NC Gv,Ev
37844: CMOVE/Z Gv,Ev
37945: CMOVNE/NZ Gv,Ev
38046: CMOVBE/NA Gv,Ev
38147: CMOVA/NBE Gv,Ev
38248: CMOVS Gv,Ev
38349: CMOVNS Gv,Ev
3844a: CMOVP/PE Gv,Ev
3854b: CMOVNP/PO Gv,Ev
3864c: CMOVL/NGE Gv,Ev
3874d: CMOVNL/GE Gv,Ev
3884e: CMOVLE/NG Gv,Ev
3894f: CMOVNLE/G Gv,Ev
390# 0x0f 0x50-0x5f
39150: movmskps Gd/q,Ups (VEX) | movmskpd Gd/q,Upd (66),(VEX)
39251: sqrtps Vps,Wps (VEX) | sqrtss Vss,Wss (F3),(VEX),(o128) | sqrtpd Vpd,Wpd (66),(VEX) | sqrtsd Vsd,Wsd (F2),(VEX),(o128)
39352: rsqrtps Vps,Wps (VEX) | rsqrtss Vss,Wss (F3),(VEX),(o128)
39453: rcpps Vps,Wps (VEX) | rcpss Vss,Wss (F3),(VEX),(o128)
39554: andps Vps,Wps (VEX) | andpd Vpd,Wpd (66),(VEX)
39655: andnps Vps,Wps (VEX) | andnpd Vpd,Wpd (66),(VEX)
39756: orps Vps,Wps (VEX) | orpd Vpd,Wpd (66),(VEX)
39857: xorps Vps,Wps (VEX) | xorpd Vpd,Wpd (66),(VEX)
39958: addps Vps,Wps (VEX) | addss Vss,Wss (F3),(VEX),(o128) | addpd Vpd,Wpd (66),(VEX) | addsd Vsd,Wsd (F2),(VEX),(o128)
40059: mulps Vps,Wps (VEX) | mulss Vss,Wss (F3),(VEX),(o128) | mulpd Vpd,Wpd (66),(VEX) | mulsd Vsd,Wsd (F2),(VEX),(o128)
4015a: cvtps2pd Vpd,Wps (VEX) | cvtss2sd Vsd,Wss (F3),(VEX),(o128) | cvtpd2ps Vps,Wpd (66),(VEX) | cvtsd2ss Vsd,Wsd (F2),(VEX),(o128)
4025b: cvtdq2ps Vps,Wdq (VEX) | cvtps2dq Vdq,Wps (66),(VEX) | cvttps2dq Vdq,Wps (F3),(VEX)
4035c: subps Vps,Wps (VEX) | subss Vss,Wss (F3),(VEX),(o128) | subpd Vpd,Wpd (66),(VEX) | subsd Vsd,Wsd (F2),(VEX),(o128)
4045d: minps Vps,Wps (VEX) | minss Vss,Wss (F3),(VEX),(o128) | minpd Vpd,Wpd (66),(VEX) | minsd Vsd,Wsd (F2),(VEX),(o128)
4055e: divps Vps,Wps (VEX) | divss Vss,Wss (F3),(VEX),(o128) | divpd Vpd,Wpd (66),(VEX) | divsd Vsd,Wsd (F2),(VEX),(o128)
4065f: maxps Vps,Wps (VEX) | maxss Vss,Wss (F3),(VEX),(o128) | maxpd Vpd,Wpd (66),(VEX) | maxsd Vsd,Wsd (F2),(VEX),(o128)
407# 0x0f 0x60-0x6f
40860: punpcklbw Pq,Qd | punpcklbw Vdq,Wdq (66),(VEX),(o128)
40961: punpcklwd Pq,Qd | punpcklwd Vdq,Wdq (66),(VEX),(o128)
41062: punpckldq Pq,Qd | punpckldq Vdq,Wdq (66),(VEX),(o128)
41163: packsswb Pq,Qq | packsswb Vdq,Wdq (66),(VEX),(o128)
41264: pcmpgtb Pq,Qq | pcmpgtb Vdq,Wdq (66),(VEX),(o128)
41365: pcmpgtw Pq,Qq | pcmpgtw Vdq,Wdq (66),(VEX),(o128)
41466: pcmpgtd Pq,Qq | pcmpgtd Vdq,Wdq (66),(VEX),(o128)
41567: packuswb Pq,Qq | packuswb Vdq,Wdq (66),(VEX),(o128)
41668: punpckhbw Pq,Qd | punpckhbw Vdq,Wdq (66),(VEX),(o128)
41769: punpckhwd Pq,Qd | punpckhwd Vdq,Wdq (66),(VEX),(o128)
4186a: punpckhdq Pq,Qd | punpckhdq Vdq,Wdq (66),(VEX),(o128)
4196b: packssdw Pq,Qd | packssdw Vdq,Wdq (66),(VEX),(o128)
4206c: punpcklqdq Vdq,Wdq (66),(VEX),(o128)
4216d: punpckhqdq Vdq,Wdq (66),(VEX),(o128)
4226e: movd/q/ Pd,Ed/q | movd/q Vdq,Ed/q (66),(VEX),(o128)
4236f: movq Pq,Qq | movdqa Vdq,Wdq (66),(VEX) | movdqu Vdq,Wdq (F3),(VEX)
424# 0x0f 0x70-0x7f
42570: pshufw Pq,Qq,Ib | pshufd Vdq,Wdq,Ib (66),(VEX),(o128) | pshufhw Vdq,Wdq,Ib (F3),(VEX),(o128) | pshuflw VdqWdq,Ib (F2),(VEX),(o128)
42671: Grp12 (1A)
42772: Grp13 (1A)
42873: Grp14 (1A)
42974: pcmpeqb Pq,Qq | pcmpeqb Vdq,Wdq (66),(VEX),(o128)
43075: pcmpeqw Pq,Qq | pcmpeqw Vdq,Wdq (66),(VEX),(o128)
43176: pcmpeqd Pq,Qq | pcmpeqd Vdq,Wdq (66),(VEX),(o128)
43277: emms/vzeroupper/vzeroall (VEX)
43378: VMREAD Ed/q,Gd/q
43479: VMWRITE Gd/q,Ed/q
4357a:
4367b:
4377c: haddps Vps,Wps (F2),(VEX) | haddpd Vpd,Wpd (66),(VEX)
4387d: hsubps Vps,Wps (F2),(VEX) | hsubpd Vpd,Wpd (66),(VEX)
4397e: movd/q Ed/q,Pd | movd/q Ed/q,Vdq (66),(VEX),(o128) | movq Vq,Wq (F3),(VEX),(o128)
4407f: movq Qq,Pq | movdqa Wdq,Vdq (66),(VEX) | movdqu Wdq,Vdq (F3),(VEX)
441# 0x0f 0x80-0x8f
44280: JO Jz (f64)
44381: JNO Jz (f64)
44482: JB/JNAE/JC Jz (f64)
44583: JNB/JAE/JNC Jz (f64)
44684: JZ/JE Jz (f64)
44785: JNZ/JNE Jz (f64)
44886: JBE/JNA Jz (f64)
44987: JNBE/JA Jz (f64)
45088: JS Jz (f64)
45189: JNS Jz (f64)
4528a: JP/JPE Jz (f64)
4538b: JNP/JPO Jz (f64)
4548c: JL/JNGE Jz (f64)
4558d: JNL/JGE Jz (f64)
4568e: JLE/JNG Jz (f64)
4578f: JNLE/JG Jz (f64)
458# 0x0f 0x90-0x9f
45990: SETO Eb
46091: SETNO Eb
46192: SETB/C/NAE Eb
46293: SETAE/NB/NC Eb
46394: SETE/Z Eb
46495: SETNE/NZ Eb
46596: SETBE/NA Eb
46697: SETA/NBE Eb
46798: SETS Eb
46899: SETNS Eb
4699a: SETP/PE Eb
4709b: SETNP/PO Eb
4719c: SETL/NGE Eb
4729d: SETNL/GE Eb
4739e: SETLE/NG Eb
4749f: SETNLE/G Eb
475# 0x0f 0xa0-0xaf
476a0: PUSH FS (d64)
477a1: POP FS (d64)
478a2: CPUID
479a3: BT Ev,Gv
480a4: SHLD Ev,Gv,Ib
481a5: SHLD Ev,Gv,CL
482a6: GrpPDLK
483a7: GrpRNG
484a8: PUSH GS (d64)
485a9: POP GS (d64)
486aa: RSM
487ab: BTS Ev,Gv
488ac: SHRD Ev,Gv,Ib
489ad: SHRD Ev,Gv,CL
490ae: Grp15 (1A),(1C)
491af: IMUL Gv,Ev
492# 0x0f 0xb0-0xbf
493b0: CMPXCHG Eb,Gb
494b1: CMPXCHG Ev,Gv
495b2: LSS Gv,Mp
496b3: BTR Ev,Gv
497b4: LFS Gv,Mp
498b5: LGS Gv,Mp
499b6: MOVZX Gv,Eb
500b7: MOVZX Gv,Ew
501b8: JMPE | POPCNT Gv,Ev (F3)
502b9: Grp10 (1A)
503ba: Grp8 Ev,Ib (1A)
504bb: BTC Ev,Gv
505bc: BSF Gv,Ev
506bd: BSR Gv,Ev
507be: MOVSX Gv,Eb
508bf: MOVSX Gv,Ew
509# 0x0f 0xc0-0xcf
510c0: XADD Eb,Gb
511c1: XADD Ev,Gv
512c2: cmpps Vps,Wps,Ib (VEX) | cmpss Vss,Wss,Ib (F3),(VEX),(o128) | cmppd Vpd,Wpd,Ib (66),(VEX) | cmpsd Vsd,Wsd,Ib (F2),(VEX)
513c3: movnti Md/q,Gd/q
514c4: pinsrw Pq,Rd/q/Mw,Ib | pinsrw Vdq,Rd/q/Mw,Ib (66),(VEX),(o128)
515c5: pextrw Gd,Nq,Ib | pextrw Gd,Udq,Ib (66),(VEX),(o128)
516c6: shufps Vps,Wps,Ib (VEX) | shufpd Vpd,Wpd,Ib (66),(VEX)
517c7: Grp9 (1A)
518c8: BSWAP RAX/EAX/R8/R8D
519c9: BSWAP RCX/ECX/R9/R9D
520ca: BSWAP RDX/EDX/R10/R10D
521cb: BSWAP RBX/EBX/R11/R11D
522cc: BSWAP RSP/ESP/R12/R12D
523cd: BSWAP RBP/EBP/R13/R13D
524ce: BSWAP RSI/ESI/R14/R14D
525cf: BSWAP RDI/EDI/R15/R15D
526# 0x0f 0xd0-0xdf
527d0: addsubps Vps,Wps (F2),(VEX) | addsubpd Vpd,Wpd (66),(VEX)
528d1: psrlw Pq,Qq | psrlw Vdq,Wdq (66),(VEX),(o128)
529d2: psrld Pq,Qq | psrld Vdq,Wdq (66),(VEX),(o128)
530d3: psrlq Pq,Qq | psrlq Vdq,Wdq (66),(VEX),(o128)
531d4: paddq Pq,Qq | paddq Vdq,Wdq (66),(VEX),(o128)
532d5: pmullw Pq,Qq | pmullw Vdq,Wdq (66),(VEX),(o128)
533d6: movq Wq,Vq (66),(VEX),(o128) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
534d7: pmovmskb Gd,Nq | pmovmskb Gd,Udq (66),(VEX),(o128)
535d8: psubusb Pq,Qq | psubusb Vdq,Wdq (66),(VEX),(o128)
536d9: psubusw Pq,Qq | psubusw Vdq,Wdq (66),(VEX),(o128)
537da: pminub Pq,Qq | pminub Vdq,Wdq (66),(VEX),(o128)
538db: pand Pq,Qq | pand Vdq,Wdq (66),(VEX),(o128)
539dc: paddusb Pq,Qq | paddusb Vdq,Wdq (66),(VEX),(o128)
540dd: paddusw Pq,Qq | paddusw Vdq,Wdq (66),(VEX),(o128)
541de: pmaxub Pq,Qq | pmaxub Vdq,Wdq (66),(VEX),(o128)
542df: pandn Pq,Qq | pandn Vdq,Wdq (66),(VEX),(o128)
543# 0x0f 0xe0-0xef
544e0: pavgb Pq,Qq | pavgb Vdq,Wdq (66),(VEX),(o128)
545e1: psraw Pq,Qq | psraw Vdq,Wdq (66),(VEX),(o128)
546e2: psrad Pq,Qq | psrad Vdq,Wdq (66),(VEX),(o128)
547e3: pavgw Pq,Qq | pavgw Vdq,Wdq (66),(VEX),(o128)
548e4: pmulhuw Pq,Qq | pmulhuw Vdq,Wdq (66),(VEX),(o128)
549e5: pmulhw Pq,Qq | pmulhw Vdq,Wdq (66),(VEX),(o128)
550e6: cvtpd2dq Vdq,Wpd (F2),(VEX) | cvttpd2dq Vdq,Wpd (66),(VEX) | cvtdq2pd Vpd,Wdq (F3),(VEX)
551e7: movntq Mq,Pq | movntdq Mdq,Vdq (66),(VEX)
552e8: psubsb Pq,Qq | psubsb Vdq,Wdq (66),(VEX),(o128)
553e9: psubsw Pq,Qq | psubsw Vdq,Wdq (66),(VEX),(o128)
554ea: pminsw Pq,Qq | pminsw Vdq,Wdq (66),(VEX),(o128)
555eb: por Pq,Qq | por Vdq,Wdq (66),(VEX),(o128)
556ec: paddsb Pq,Qq | paddsb Vdq,Wdq (66),(VEX),(o128)
557ed: paddsw Pq,Qq | paddsw Vdq,Wdq (66),(VEX),(o128)
558ee: pmaxsw Pq,Qq | pmaxsw Vdq,Wdq (66),(VEX),(o128)
559ef: pxor Pq,Qq | pxor Vdq,Wdq (66),(VEX),(o128)
560# 0x0f 0xf0-0xff
561f0: lddqu Vdq,Mdq (F2),(VEX)
562f1: psllw Pq,Qq | psllw Vdq,Wdq (66),(VEX),(o128)
563f2: pslld Pq,Qq | pslld Vdq,Wdq (66),(VEX),(o128)
564f3: psllq Pq,Qq | psllq Vdq,Wdq (66),(VEX),(o128)
565f4: pmuludq Pq,Qq | pmuludq Vdq,Wdq (66),(VEX),(o128)
566f5: pmaddwd Pq,Qq | pmaddwd Vdq,Wdq (66),(VEX),(o128)
567f6: psadbw Pq,Qq | psadbw Vdq,Wdq (66),(VEX),(o128)
568f7: maskmovq Pq,Nq | maskmovdqu Vdq,Udq (66),(VEX),(o128)
569f8: psubb Pq,Qq | psubb Vdq,Wdq (66),(VEX),(o128)
570f9: psubw Pq,Qq | psubw Vdq,Wdq (66),(VEX),(o128)
571fa: psubd Pq,Qq | psubd Vdq,Wdq (66),(VEX),(o128)
572fb: psubq Pq,Qq | psubq Vdq,Wdq (66),(VEX),(o128)
573fc: paddb Pq,Qq | paddb Vdq,Wdq (66),(VEX),(o128)
574fd: paddw Pq,Qq | paddw Vdq,Wdq (66),(VEX),(o128)
575fe: paddd Pq,Qq | paddd Vdq,Wdq (66),(VEX),(o128)
576ff:
577EndTable
578
579Table: 3-byte opcode 1 (0x0f 0x38)
580Referrer: 3-byte escape 1
581AVXcode: 2
582# 0x0f 0x38 0x00-0x0f
58300: pshufb Pq,Qq | pshufb Vdq,Wdq (66),(VEX),(o128)
58401: phaddw Pq,Qq | phaddw Vdq,Wdq (66),(VEX),(o128)
58502: phaddd Pq,Qq | phaddd Vdq,Wdq (66),(VEX),(o128)
58603: phaddsw Pq,Qq | phaddsw Vdq,Wdq (66),(VEX),(o128)
58704: pmaddubsw Pq,Qq | pmaddubsw Vdq,Wdq (66),(VEX),(o128)
58805: phsubw Pq,Qq | phsubw Vdq,Wdq (66),(VEX),(o128)
58906: phsubd Pq,Qq | phsubd Vdq,Wdq (66),(VEX),(o128)
59007: phsubsw Pq,Qq | phsubsw Vdq,Wdq (66),(VEX),(o128)
59108: psignb Pq,Qq | psignb Vdq,Wdq (66),(VEX),(o128)
59209: psignw Pq,Qq | psignw Vdq,Wdq (66),(VEX),(o128)
5930a: psignd Pq,Qq | psignd Vdq,Wdq (66),(VEX),(o128)
5940b: pmulhrsw Pq,Qq | pmulhrsw Vdq,Wdq (66),(VEX),(o128)
5950c: Vpermilps /r (66),(oVEX)
5960d: Vpermilpd /r (66),(oVEX)
5970e: vtestps /r (66),(oVEX)
5980f: vtestpd /r (66),(oVEX)
599# 0x0f 0x38 0x10-0x1f
60010: pblendvb Vdq,Wdq (66)
60111:
60212:
60313:
60414: blendvps Vdq,Wdq (66)
60515: blendvpd Vdq,Wdq (66)
60616:
60717: ptest Vdq,Wdq (66),(VEX)
60818: vbroadcastss /r (66),(oVEX)
60919: vbroadcastsd /r (66),(oVEX),(o256)
6101a: vbroadcastf128 /r (66),(oVEX),(o256)
6111b:
6121c: pabsb Pq,Qq | pabsb Vdq,Wdq (66),(VEX),(o128)
6131d: pabsw Pq,Qq | pabsw Vdq,Wdq (66),(VEX),(o128)
6141e: pabsd Pq,Qq | pabsd Vdq,Wdq (66),(VEX),(o128)
6151f:
616# 0x0f 0x38 0x20-0x2f
61720: pmovsxbw Vdq,Udq/Mq (66),(VEX),(o128)
61821: pmovsxbd Vdq,Udq/Md (66),(VEX),(o128)
61922: pmovsxbq Vdq,Udq/Mw (66),(VEX),(o128)
62023: pmovsxwd Vdq,Udq/Mq (66),(VEX),(o128)
62124: pmovsxwq Vdq,Udq/Md (66),(VEX),(o128)
62225: pmovsxdq Vdq,Udq/Mq (66),(VEX),(o128)
62326:
62427:
62528: pmuldq Vdq,Wdq (66),(VEX),(o128)
62629: pcmpeqq Vdq,Wdq (66),(VEX),(o128)
6272a: movntdqa Vdq,Mdq (66),(VEX),(o128)
6282b: packusdw Vdq,Wdq (66),(VEX),(o128)
6292c: vmaskmovps(ld) /r (66),(oVEX)
6302d: vmaskmovpd(ld) /r (66),(oVEX)
6312e: vmaskmovps(st) /r (66),(oVEX)
6322f: vmaskmovpd(st) /r (66),(oVEX)
633# 0x0f 0x38 0x30-0x3f
63430: pmovzxbw Vdq,Udq/Mq (66),(VEX),(o128)
63531: pmovzxbd Vdq,Udq/Md (66),(VEX),(o128)
63632: pmovzxbq Vdq,Udq/Mw (66),(VEX),(o128)
63733: pmovzxwd Vdq,Udq/Mq (66),(VEX),(o128)
63834: pmovzxwq Vdq,Udq/Md (66),(VEX),(o128)
63935: pmovzxdq Vdq,Udq/Mq (66),(VEX),(o128)
64036:
64137: pcmpgtq Vdq,Wdq (66),(VEX),(o128)
64238: pminsb Vdq,Wdq (66),(VEX),(o128)
64339: pminsd Vdq,Wdq (66),(VEX),(o128)
6443a: pminuw Vdq,Wdq (66),(VEX),(o128)
6453b: pminud Vdq,Wdq (66),(VEX),(o128)
6463c: pmaxsb Vdq,Wdq (66),(VEX),(o128)
6473d: pmaxsd Vdq,Wdq (66),(VEX),(o128)
6483e: pmaxuw Vdq,Wdq (66),(VEX),(o128)
6493f: pmaxud Vdq,Wdq (66),(VEX),(o128)
650# 0x0f 0x38 0x40-0x8f
65140: pmulld Vdq,Wdq (66),(VEX),(o128)
65241: phminposuw Vdq,Wdq (66),(VEX),(o128)
65380: INVEPT Gd/q,Mdq (66)
65481: INVPID Gd/q,Mdq (66)
655# 0x0f 0x38 0x90-0xbf (FMA)
65696: vfmaddsub132pd/ps /r (66),(VEX)
65797: vfmsubadd132pd/ps /r (66),(VEX)
65898: vfmadd132pd/ps /r (66),(VEX)
65999: vfmadd132sd/ss /r (66),(VEX),(o128)
6609a: vfmsub132pd/ps /r (66),(VEX)
6619b: vfmsub132sd/ss /r (66),(VEX),(o128)
6629c: vfnmadd132pd/ps /r (66),(VEX)
6639d: vfnmadd132sd/ss /r (66),(VEX),(o128)
6649e: vfnmsub132pd/ps /r (66),(VEX)
6659f: vfnmsub132sd/ss /r (66),(VEX),(o128)
666a6: vfmaddsub213pd/ps /r (66),(VEX)
667a7: vfmsubadd213pd/ps /r (66),(VEX)
668a8: vfmadd213pd/ps /r (66),(VEX)
669a9: vfmadd213sd/ss /r (66),(VEX),(o128)
670aa: vfmsub213pd/ps /r (66),(VEX)
671ab: vfmsub213sd/ss /r (66),(VEX),(o128)
672ac: vfnmadd213pd/ps /r (66),(VEX)
673ad: vfnmadd213sd/ss /r (66),(VEX),(o128)
674ae: vfnmsub213pd/ps /r (66),(VEX)
675af: vfnmsub213sd/ss /r (66),(VEX),(o128)
676b6: vfmaddsub231pd/ps /r (66),(VEX)
677b7: vfmsubadd231pd/ps /r (66),(VEX)
678b8: vfmadd231pd/ps /r (66),(VEX)
679b9: vfmadd231sd/ss /r (66),(VEX),(o128)
680ba: vfmsub231pd/ps /r (66),(VEX)
681bb: vfmsub231sd/ss /r (66),(VEX),(o128)
682bc: vfnmadd231pd/ps /r (66),(VEX)
683bd: vfnmadd231sd/ss /r (66),(VEX),(o128)
684be: vfnmsub231pd/ps /r (66),(VEX)
685bf: vfnmsub231sd/ss /r (66),(VEX),(o128)
686# 0x0f 0x38 0xc0-0xff
687db: aesimc Vdq,Wdq (66),(VEX),(o128)
688dc: aesenc Vdq,Wdq (66),(VEX),(o128)
689dd: aesenclast Vdq,Wdq (66),(VEX),(o128)
690de: aesdec Vdq,Wdq (66),(VEX),(o128)
691df: aesdeclast Vdq,Wdq (66),(VEX),(o128)
692f0: MOVBE Gv,Mv | CRC32 Gd,Eb (F2)
693f1: MOVBE Mv,Gv | CRC32 Gd,Ev (F2)
694EndTable
695
696Table: 3-byte opcode 2 (0x0f 0x3a)
697Referrer: 3-byte escape 2
698AVXcode: 3
699# 0x0f 0x3a 0x00-0xff
70004: vpermilps /r,Ib (66),(oVEX)
70105: vpermilpd /r,Ib (66),(oVEX)
70206: vperm2f128 /r,Ib (66),(oVEX),(o256)
70308: roundps Vdq,Wdq,Ib (66),(VEX)
70409: roundpd Vdq,Wdq,Ib (66),(VEX)
7050a: roundss Vss,Wss,Ib (66),(VEX),(o128)
7060b: roundsd Vsd,Wsd,Ib (66),(VEX),(o128)
7070c: blendps Vdq,Wdq,Ib (66),(VEX)
7080d: blendpd Vdq,Wdq,Ib (66),(VEX)
7090e: pblendw Vdq,Wdq,Ib (66),(VEX),(o128)
7100f: palignr Pq,Qq,Ib | palignr Vdq,Wdq,Ib (66),(VEX),(o128)
71114: pextrb Rd/Mb,Vdq,Ib (66),(VEX),(o128)
71215: pextrw Rd/Mw,Vdq,Ib (66),(VEX),(o128)
71316: pextrd/pextrq Ed/q,Vdq,Ib (66),(VEX),(o128)
71417: extractps Ed,Vdq,Ib (66),(VEX),(o128)
71518: vinsertf128 /r,Ib (66),(oVEX),(o256)
71619: vextractf128 /r,Ib (66),(oVEX),(o256)
71720: pinsrb Vdq,Rd/q/Mb,Ib (66),(VEX),(o128)
71821: insertps Vdq,Udq/Md,Ib (66),(VEX),(o128)
71922: pinsrd/pinsrq Vdq,Ed/q,Ib (66),(VEX),(o128)
72040: dpps Vdq,Wdq,Ib (66),(VEX)
72141: dppd Vdq,Wdq,Ib (66),(VEX),(o128)
72242: mpsadbw Vdq,Wdq,Ib (66),(VEX),(o128)
72344: pclmulq Vdq,Wdq,Ib (66),(VEX),(o128)
7244a: vblendvps /r,Ib (66),(oVEX)
7254b: vblendvpd /r,Ib (66),(oVEX)
7264c: vpblendvb /r,Ib (66),(oVEX),(o128)
72760: pcmpestrm Vdq,Wdq,Ib (66),(VEX),(o128)
72861: pcmpestri Vdq,Wdq,Ib (66),(VEX),(o128)
72962: pcmpistrm Vdq,Wdq,Ib (66),(VEX),(o128)
73063: pcmpistri Vdq,Wdq,Ib (66),(VEX),(o128)
731df: aeskeygenassist Vdq,Wdq,Ib (66),(VEX),(o128)
732EndTable
733
734GrpTable: Grp1
7350: ADD
7361: OR
7372: ADC
7383: SBB
7394: AND
7405: SUB
7416: XOR
7427: CMP
743EndTable
744
745GrpTable: Grp1A
7460: POP
747EndTable
748
749GrpTable: Grp2
7500: ROL
7511: ROR
7522: RCL
7533: RCR
7544: SHL/SAL
7555: SHR
7566:
7577: SAR
758EndTable
759
760GrpTable: Grp3_1
7610: TEST Eb,Ib
7621:
7632: NOT Eb
7643: NEG Eb
7654: MUL AL,Eb
7665: IMUL AL,Eb
7676: DIV AL,Eb
7687: IDIV AL,Eb
769EndTable
770
771GrpTable: Grp3_2
7720: TEST Ev,Iz
7731:
7742: NOT Ev
7753: NEG Ev
7764: MUL rAX,Ev
7775: IMUL rAX,Ev
7786: DIV rAX,Ev
7797: IDIV rAX,Ev
780EndTable
781
782GrpTable: Grp4
7830: INC Eb
7841: DEC Eb
785EndTable
786
787GrpTable: Grp5
7880: INC Ev
7891: DEC Ev
7902: CALLN Ev (f64)
7913: CALLF Ep
7924: JMPN Ev (f64)
7935: JMPF Ep
7946: PUSH Ev (d64)
7957:
796EndTable
797
798GrpTable: Grp6
7990: SLDT Rv/Mw
8001: STR Rv/Mw
8012: LLDT Ew
8023: LTR Ew
8034: VERR Ew
8045: VERW Ew
805EndTable
806
807GrpTable: Grp7
8080: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
8091: SIDT Ms | MONITOR (000),(11B) | MWAIT (001)
8102: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B)
8113: LIDT Ms
8124: SMSW Mw/Rv
8135:
8146: LMSW Ew
8157: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
816EndTable
817
818GrpTable: Grp8
8194: BT
8205: BTS
8216: BTR
8227: BTC
823EndTable
824
825GrpTable: Grp9
8261: CMPXCHG8B/16B Mq/Mdq
8276: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3)
8287: VMPTRST Mq
829EndTable
830
831GrpTable: Grp10
832EndTable
833
834GrpTable: Grp11
8350: MOV
836EndTable
837
838GrpTable: Grp12
8392: psrlw Nq,Ib (11B) | psrlw Udq,Ib (66),(11B),(VEX),(o128)
8404: psraw Nq,Ib (11B) | psraw Udq,Ib (66),(11B),(VEX),(o128)
8416: psllw Nq,Ib (11B) | psllw Udq,Ib (66),(11B),(VEX),(o128)
842EndTable
843
844GrpTable: Grp13
8452: psrld Nq,Ib (11B) | psrld Udq,Ib (66),(11B),(VEX),(o128)
8464: psrad Nq,Ib (11B) | psrad Udq,Ib (66),(11B),(VEX),(o128)
8476: pslld Nq,Ib (11B) | pslld Udq,Ib (66),(11B),(VEX),(o128)
848EndTable
849
850GrpTable: Grp14
8512: psrlq Nq,Ib (11B) | psrlq Udq,Ib (66),(11B),(VEX),(o128)
8523: psrldq Udq,Ib (66),(11B),(VEX),(o128)
8536: psllq Nq,Ib (11B) | psllq Udq,Ib (66),(11B),(VEX),(o128)
8547: pslldq Udq,Ib (66),(11B),(VEX),(o128)
855EndTable
856
857GrpTable: Grp15
8580: fxsave
8591: fxstor
8602: ldmxcsr (VEX)
8613: stmxcsr (VEX)
8624: XSAVE
8635: XRSTOR | lfence (11B)
8646: mfence (11B)
8657: clflush | sfence (11B)
866EndTable
867
868GrpTable: Grp16
8690: prefetch NTA
8701: prefetch T0
8712: prefetch T1
8723: prefetch T2
873EndTable
874
875# AMD's Prefetch Group
876GrpTable: GrpP
8770: PREFETCH
8781: PREFETCHW
879EndTable
880
881GrpTable: GrpPDLK
8820: MONTMUL
8831: XSHA1
8842: XSHA2
885EndTable
886
887GrpTable: GrpRNG
8880: xstore-rng
8891: xcrypt-ecb
8902: xcrypt-cbc
8914: xcrypt-cfb
8925: xcrypt-ofb
893EndTable
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 61b41ca3b5a2..d0474ad2a6e5 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -35,34 +35,3 @@ int fixup_exception(struct pt_regs *regs)
35 35
36 return 0; 36 return 0;
37} 37}
38
39#ifdef CONFIG_X86_64
40/*
41 * Need to defined our own search_extable on X86_64 to work around
42 * a B stepping K8 bug.
43 */
44const struct exception_table_entry *
45search_extable(const struct exception_table_entry *first,
46 const struct exception_table_entry *last,
47 unsigned long value)
48{
49 /* B stepping K8 bug */
50 if ((value >> 32) == 0)
51 value |= 0xffffffffUL << 32;
52
53 while (first <= last) {
54 const struct exception_table_entry *mid;
55 long diff;
56
57 mid = (last - first) / 2 + first;
58 diff = mid->insn - value;
59 if (diff == 0)
60 return mid;
61 else if (diff < 0)
62 first = mid+1;
63 else
64 last = mid-1;
65 }
66 return NULL;
67}
68#endif
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index f4cee9028cf0..f62777940dfb 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -38,7 +38,8 @@ enum x86_pf_error_code {
38 * Returns 0 if mmiotrace is disabled, or if the fault is not 38 * Returns 0 if mmiotrace is disabled, or if the fault is not
39 * handled by mmiotrace: 39 * handled by mmiotrace:
40 */ 40 */
41static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr) 41static inline int __kprobes
42kmmio_fault(struct pt_regs *regs, unsigned long addr)
42{ 43{
43 if (unlikely(is_kmmio_active())) 44 if (unlikely(is_kmmio_active()))
44 if (kmmio_handler(regs, addr) == 1) 45 if (kmmio_handler(regs, addr) == 1)
@@ -46,7 +47,7 @@ static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
46 return 0; 47 return 0;
47} 48}
48 49
49static inline int notify_page_fault(struct pt_regs *regs) 50static inline int __kprobes notify_page_fault(struct pt_regs *regs)
50{ 51{
51 int ret = 0; 52 int ret = 0;
52 53
@@ -240,7 +241,7 @@ void vmalloc_sync_all(void)
240 * 241 *
241 * Handle a fault on the vmalloc or module mapping area 242 * Handle a fault on the vmalloc or module mapping area
242 */ 243 */
243static noinline int vmalloc_fault(unsigned long address) 244static noinline __kprobes int vmalloc_fault(unsigned long address)
244{ 245{
245 unsigned long pgd_paddr; 246 unsigned long pgd_paddr;
246 pmd_t *pmd_k; 247 pmd_t *pmd_k;
@@ -357,7 +358,7 @@ void vmalloc_sync_all(void)
357 * 358 *
358 * This assumes no large pages in there. 359 * This assumes no large pages in there.
359 */ 360 */
360static noinline int vmalloc_fault(unsigned long address) 361static noinline __kprobes int vmalloc_fault(unsigned long address)
361{ 362{
362 pgd_t *pgd, *pgd_ref; 363 pgd_t *pgd, *pgd_ref;
363 pud_t *pud, *pud_ref; 364 pud_t *pud, *pud_ref;
@@ -658,7 +659,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
658 show_fault_oops(regs, error_code, address); 659 show_fault_oops(regs, error_code, address);
659 660
660 stackend = end_of_stack(tsk); 661 stackend = end_of_stack(tsk);
661 if (*stackend != STACK_END_MAGIC) 662 if (tsk != &init_task && *stackend != STACK_END_MAGIC)
662 printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); 663 printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
663 664
664 tsk->thread.cr2 = address; 665 tsk->thread.cr2 = address;
@@ -860,7 +861,7 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte)
860 * There are no security implications to leaving a stale TLB when 861 * There are no security implications to leaving a stale TLB when
861 * increasing the permissions on a page. 862 * increasing the permissions on a page.
862 */ 863 */
863static noinline int 864static noinline __kprobes int
864spurious_fault(unsigned long error_code, unsigned long address) 865spurious_fault(unsigned long error_code, unsigned long address)
865{ 866{
866 pgd_t *pgd; 867 pgd_t *pgd;
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 16ccbd77917f..11a4ad4d6253 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -540,8 +540,14 @@ kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
540 struct die_args *arg = args; 540 struct die_args *arg = args;
541 541
542 if (val == DIE_DEBUG && (arg->err & DR_STEP)) 542 if (val == DIE_DEBUG && (arg->err & DR_STEP))
543 if (post_kmmio_handler(arg->err, arg->regs) == 1) 543 if (post_kmmio_handler(arg->err, arg->regs) == 1) {
544 /*
545 * Reset the BS bit in dr6 (pointed by args->err) to
546 * denote completion of processing
547 */
548 (*(unsigned long *)ERR_PTR(arg->err)) &= ~DR_STEP;
544 return NOTIFY_STOP; 549 return NOTIFY_STOP;
550 }
545 551
546 return NOTIFY_DONE; 552 return NOTIFY_DONE;
547} 553}
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index dbb5381f7b3b..9d7ce96e5a5c 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -136,7 +136,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
136 apicid_to_node[apic_id] = node; 136 apicid_to_node[apic_id] = node;
137 node_set(node, cpu_nodes_parsed); 137 node_set(node, cpu_nodes_parsed);
138 acpi_numa = 1; 138 acpi_numa = 1;
139 printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", 139 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
140 pxm, apic_id, node); 140 pxm, apic_id, node);
141} 141}
142 142
@@ -170,7 +170,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
170 apicid_to_node[apic_id] = node; 170 apicid_to_node[apic_id] = node;
171 node_set(node, cpu_nodes_parsed); 171 node_set(node, cpu_nodes_parsed);
172 acpi_numa = 1; 172 acpi_numa = 1;
173 printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", 173 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
174 pxm, apic_id, node); 174 pxm, apic_id, node);
175} 175}
176 176
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 8aa85f17667e..0a979f3e5b8a 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -18,6 +18,7 @@
18#include <asm/mce.h> 18#include <asm/mce.h>
19#include <asm/xcr.h> 19#include <asm/xcr.h>
20#include <asm/suspend.h> 20#include <asm/suspend.h>
21#include <asm/debugreg.h>
21 22
22#ifdef CONFIG_X86_32 23#ifdef CONFIG_X86_32
23static struct saved_context saved_context; 24static struct saved_context saved_context;
@@ -142,31 +143,6 @@ static void fix_processor_context(void)
142#endif 143#endif
143 load_TR_desc(); /* This does ltr */ 144 load_TR_desc(); /* This does ltr */
144 load_LDT(&current->active_mm->context); /* This does lldt */ 145 load_LDT(&current->active_mm->context); /* This does lldt */
145
146 /*
147 * Now maybe reload the debug registers
148 */
149 if (current->thread.debugreg7) {
150#ifdef CONFIG_X86_32
151 set_debugreg(current->thread.debugreg0, 0);
152 set_debugreg(current->thread.debugreg1, 1);
153 set_debugreg(current->thread.debugreg2, 2);
154 set_debugreg(current->thread.debugreg3, 3);
155 /* no 4 and 5 */
156 set_debugreg(current->thread.debugreg6, 6);
157 set_debugreg(current->thread.debugreg7, 7);
158#else
159 /* CONFIG_X86_64 */
160 loaddebug(&current->thread, 0);
161 loaddebug(&current->thread, 1);
162 loaddebug(&current->thread, 2);
163 loaddebug(&current->thread, 3);
164 /* no 4 and 5 */
165 loaddebug(&current->thread, 6);
166 loaddebug(&current->thread, 7);
167#endif
168 }
169
170} 146}
171 147
172/** 148/**
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile
new file mode 100644
index 000000000000..f82082677337
--- /dev/null
+++ b/arch/x86/tools/Makefile
@@ -0,0 +1,31 @@
1PHONY += posttest
2
3ifeq ($(KBUILD_VERBOSE),1)
4 posttest_verbose = -v
5else
6 posttest_verbose =
7endif
8
9ifeq ($(CONFIG_64BIT),y)
10 posttest_64bit = -y
11else
12 posttest_64bit = -n
13endif
14
15distill_awk = $(srctree)/arch/x86/tools/distill.awk
16chkobjdump = $(srctree)/arch/x86/tools/chkobjdump.awk
17
18quiet_cmd_posttest = TEST $@
19 cmd_posttest = ($(OBJDUMP) -v | $(AWK) -f $(chkobjdump)) || $(OBJDUMP) -d -j .text $(objtree)/vmlinux | $(AWK) -f $(distill_awk) | $(obj)/test_get_len $(posttest_64bit) $(posttest_verbose)
20
21posttest: $(obj)/test_get_len vmlinux
22 $(call cmd,posttest)
23
24hostprogs-y := test_get_len
25
26# -I needed for generated C source and C source which in the kernel tree.
27HOSTCFLAGS_test_get_len.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x86/include/ -I$(srctree)/arch/x86/lib/ -I$(srctree)/include/
28
29# Dependencies are also needed.
30$(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c
31
diff --git a/arch/x86/tools/chkobjdump.awk b/arch/x86/tools/chkobjdump.awk
new file mode 100644
index 000000000000..0d13cd9fdcff
--- /dev/null
+++ b/arch/x86/tools/chkobjdump.awk
@@ -0,0 +1,23 @@
1# GNU objdump version checker
2#
3# Usage:
4# objdump -v | awk -f chkobjdump.awk
5BEGIN {
6 # objdump version 2.19 or later is OK for the test.
7 od_ver = 2;
8 od_sver = 19;
9}
10
11/^GNU/ {
12 split($4, ver, ".");
13 if (ver[1] > od_ver ||
14 (ver[1] == od_ver && ver[2] >= od_sver)) {
15 exit 1;
16 } else {
17 printf("Warning: objdump version %s is older than %d.%d\n",
18 $4, od_ver, od_sver);
19 print("Warning: Skipping posttest.");
20 # Logic is inverted, because we just skip test without error.
21 exit 0;
22 }
23}
diff --git a/arch/x86/tools/distill.awk b/arch/x86/tools/distill.awk
new file mode 100644
index 000000000000..c13c0ee48ab4
--- /dev/null
+++ b/arch/x86/tools/distill.awk
@@ -0,0 +1,47 @@
1#!/bin/awk -f
2# Usage: objdump -d a.out | awk -f distill.awk | ./test_get_len
3# Distills the disassembly as follows:
4# - Removes all lines except the disassembled instructions.
5# - For instructions that exceed 1 line (7 bytes), crams all the hex bytes
6# into a single line.
7# - Remove bad(or prefix only) instructions
8
9BEGIN {
10 prev_addr = ""
11 prev_hex = ""
12 prev_mnemonic = ""
13 bad_expr = "(\\(bad\\)|^rex|^.byte|^rep(z|nz)$|^lock$|^es$|^cs$|^ss$|^ds$|^fs$|^gs$|^data(16|32)$|^addr(16|32|64))"
14 fwait_expr = "^9b "
15 fwait_str="9b\tfwait"
16}
17
18/^ *[0-9a-f]+ <[^>]*>:/ {
19 # Symbol entry
20 printf("%s%s\n", $2, $1)
21}
22
23/^ *[0-9a-f]+:/ {
24 if (split($0, field, "\t") < 3) {
25 # This is a continuation of the same insn.
26 prev_hex = prev_hex field[2]
27 } else {
28 # Skip bad instructions
29 if (match(prev_mnemonic, bad_expr))
30 prev_addr = ""
31 # Split fwait from other f* instructions
32 if (match(prev_hex, fwait_expr) && prev_mnemonic != "fwait") {
33 printf "%s\t%s\n", prev_addr, fwait_str
34 sub(fwait_expr, "", prev_hex)
35 }
36 if (prev_addr != "")
37 printf "%s\t%s\t%s\n", prev_addr, prev_hex, prev_mnemonic
38 prev_addr = field[1]
39 prev_hex = field[2]
40 prev_mnemonic = field[3]
41 }
42}
43
44END {
45 if (prev_addr != "")
46 printf "%s\t%s\t%s\n", prev_addr, prev_hex, prev_mnemonic
47}
diff --git a/arch/x86/tools/gen-insn-attr-x86.awk b/arch/x86/tools/gen-insn-attr-x86.awk
new file mode 100644
index 000000000000..e34e92a28eb6
--- /dev/null
+++ b/arch/x86/tools/gen-insn-attr-x86.awk
@@ -0,0 +1,380 @@
1#!/bin/awk -f
2# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com>
4#
5# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
6
7# Awk implementation sanity check
8function check_awk_implement() {
9 if (!match("abc", "[[:lower:]]+"))
10 return "Your awk doesn't support charactor-class."
11 if (sprintf("%x", 0) != "0")
12 return "Your awk has a printf-format problem."
13 return ""
14}
15
16# Clear working vars
17function clear_vars() {
18 delete table
19 delete lptable2
20 delete lptable1
21 delete lptable3
22 eid = -1 # escape id
23 gid = -1 # group id
24 aid = -1 # AVX id
25 tname = ""
26}
27
28BEGIN {
29 # Implementation error checking
30 awkchecked = check_awk_implement()
31 if (awkchecked != "") {
32 print "Error: " awkchecked > "/dev/stderr"
33 print "Please try to use gawk." > "/dev/stderr"
34 exit 1
35 }
36
37 # Setup generating tables
38 print "/* x86 opcode map generated from x86-opcode-map.txt */"
39 print "/* Do not change this code. */\n"
40 ggid = 1
41 geid = 1
42 gaid = 0
43 delete etable
44 delete gtable
45 delete atable
46
47 opnd_expr = "^[[:alpha:]/]"
48 ext_expr = "^\\("
49 sep_expr = "^\\|$"
50 group_expr = "^Grp[[:alnum:]]+"
51
52 imm_expr = "^[IJAO][[:lower:]]"
53 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
54 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
55 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
56 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
57 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
58 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
59 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
60 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
61 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
62 imm_flag["Ob"] = "INAT_MOFFSET"
63 imm_flag["Ov"] = "INAT_MOFFSET"
64
65 modrm_expr = "^([CDEGMNPQRSUVW/][[:lower:]]+|NTA|T[012])"
66 force64_expr = "\\([df]64\\)"
67 rex_expr = "^REX(\\.[XRWB]+)*"
68 fpu_expr = "^ESC" # TODO
69
70 lprefix1_expr = "\\(66\\)"
71 lprefix2_expr = "\\(F3\\)"
72 lprefix3_expr = "\\(F2\\)"
73 max_lprefix = 4
74
75 vexok_expr = "\\(VEX\\)"
76 vexonly_expr = "\\(oVEX\\)"
77
78 prefix_expr = "\\(Prefix\\)"
79 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
80 prefix_num["REPNE"] = "INAT_PFX_REPNE"
81 prefix_num["REP/REPE"] = "INAT_PFX_REPE"
82 prefix_num["LOCK"] = "INAT_PFX_LOCK"
83 prefix_num["SEG=CS"] = "INAT_PFX_CS"
84 prefix_num["SEG=DS"] = "INAT_PFX_DS"
85 prefix_num["SEG=ES"] = "INAT_PFX_ES"
86 prefix_num["SEG=FS"] = "INAT_PFX_FS"
87 prefix_num["SEG=GS"] = "INAT_PFX_GS"
88 prefix_num["SEG=SS"] = "INAT_PFX_SS"
89 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
90 prefix_num["2bytes-VEX"] = "INAT_PFX_VEX2"
91 prefix_num["3bytes-VEX"] = "INAT_PFX_VEX3"
92
93 clear_vars()
94}
95
96function semantic_error(msg) {
97 print "Semantic error at " NR ": " msg > "/dev/stderr"
98 exit 1
99}
100
101function debug(msg) {
102 print "DEBUG: " msg
103}
104
105function array_size(arr, i,c) {
106 c = 0
107 for (i in arr)
108 c++
109 return c
110}
111
112/^Table:/ {
113 print "/* " $0 " */"
114 if (tname != "")
115 semantic_error("Hit Table: before EndTable:.");
116}
117
118/^Referrer:/ {
119 if (NF != 1) {
120 # escape opcode table
121 ref = ""
122 for (i = 2; i <= NF; i++)
123 ref = ref $i
124 eid = escape[ref]
125 tname = sprintf("inat_escape_table_%d", eid)
126 }
127}
128
129/^AVXcode:/ {
130 if (NF != 1) {
131 # AVX/escape opcode table
132 aid = $2
133 if (gaid <= aid)
134 gaid = aid + 1
135 if (tname == "") # AVX only opcode table
136 tname = sprintf("inat_avx_table_%d", $2)
137 }
138 if (aid == -1 && eid == -1) # primary opcode table
139 tname = "inat_primary_table"
140}
141
142/^GrpTable:/ {
143 print "/* " $0 " */"
144 if (!($2 in group))
145 semantic_error("No group: " $2 )
146 gid = group[$2]
147 tname = "inat_group_table_" gid
148}
149
150function print_table(tbl,name,fmt,n)
151{
152 print "const insn_attr_t " name " = {"
153 for (i = 0; i < n; i++) {
154 id = sprintf(fmt, i)
155 if (tbl[id])
156 print " [" id "] = " tbl[id] ","
157 }
158 print "};"
159}
160
161/^EndTable/ {
162 if (gid != -1) {
163 # print group tables
164 if (array_size(table) != 0) {
165 print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
166 "0x%x", 8)
167 gtable[gid,0] = tname
168 }
169 if (array_size(lptable1) != 0) {
170 print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
171 "0x%x", 8)
172 gtable[gid,1] = tname "_1"
173 }
174 if (array_size(lptable2) != 0) {
175 print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
176 "0x%x", 8)
177 gtable[gid,2] = tname "_2"
178 }
179 if (array_size(lptable3) != 0) {
180 print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
181 "0x%x", 8)
182 gtable[gid,3] = tname "_3"
183 }
184 } else {
185 # print primary/escaped tables
186 if (array_size(table) != 0) {
187 print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
188 "0x%02x", 256)
189 etable[eid,0] = tname
190 if (aid >= 0)
191 atable[aid,0] = tname
192 }
193 if (array_size(lptable1) != 0) {
194 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
195 "0x%02x", 256)
196 etable[eid,1] = tname "_1"
197 if (aid >= 0)
198 atable[aid,1] = tname "_1"
199 }
200 if (array_size(lptable2) != 0) {
201 print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
202 "0x%02x", 256)
203 etable[eid,2] = tname "_2"
204 if (aid >= 0)
205 atable[aid,2] = tname "_2"
206 }
207 if (array_size(lptable3) != 0) {
208 print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
209 "0x%02x", 256)
210 etable[eid,3] = tname "_3"
211 if (aid >= 0)
212 atable[aid,3] = tname "_3"
213 }
214 }
215 print ""
216 clear_vars()
217}
218
219function add_flags(old,new) {
220 if (old && new)
221 return old " | " new
222 else if (old)
223 return old
224 else
225 return new
226}
227
228# convert operands to flags.
229function convert_operands(opnd, i,imm,mod)
230{
231 imm = null
232 mod = null
233 for (i in opnd) {
234 i = opnd[i]
235 if (match(i, imm_expr) == 1) {
236 if (!imm_flag[i])
237 semantic_error("Unknown imm opnd: " i)
238 if (imm) {
239 if (i != "Ib")
240 semantic_error("Second IMM error")
241 imm = add_flags(imm, "INAT_SCNDIMM")
242 } else
243 imm = imm_flag[i]
244 } else if (match(i, modrm_expr))
245 mod = "INAT_MODRM"
246 }
247 return add_flags(imm, mod)
248}
249
250/^[0-9a-f]+\:/ {
251 if (NR == 1)
252 next
253 # get index
254 idx = "0x" substr($1, 1, index($1,":") - 1)
255 if (idx in table)
256 semantic_error("Redefine " idx " in " tname)
257
258 # check if escaped opcode
259 if ("escape" == $2) {
260 if ($3 != "#")
261 semantic_error("No escaped name")
262 ref = ""
263 for (i = 4; i <= NF; i++)
264 ref = ref $i
265 if (ref in escape)
266 semantic_error("Redefine escape (" ref ")")
267 escape[ref] = geid
268 geid++
269 table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
270 next
271 }
272
273 variant = null
274 # converts
275 i = 2
276 while (i <= NF) {
277 opcode = $(i++)
278 delete opnds
279 ext = null
280 flags = null
281 opnd = null
282 # parse one opcode
283 if (match($i, opnd_expr)) {
284 opnd = $i
285 split($(i++), opnds, ",")
286 flags = convert_operands(opnds)
287 }
288 if (match($i, ext_expr))
289 ext = $(i++)
290 if (match($i, sep_expr))
291 i++
292 else if (i < NF)
293 semantic_error($i " is not a separator")
294
295 # check if group opcode
296 if (match(opcode, group_expr)) {
297 if (!(opcode in group)) {
298 group[opcode] = ggid
299 ggid++
300 }
301 flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
302 }
303 # check force(or default) 64bit
304 if (match(ext, force64_expr))
305 flags = add_flags(flags, "INAT_FORCE64")
306
307 # check REX prefix
308 if (match(opcode, rex_expr))
309 flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
310
311 # check coprocessor escape : TODO
312 if (match(opcode, fpu_expr))
313 flags = add_flags(flags, "INAT_MODRM")
314
315 # check VEX only code
316 if (match(ext, vexonly_expr))
317 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
318
319 # check VEX only code
320 if (match(ext, vexok_expr))
321 flags = add_flags(flags, "INAT_VEXOK")
322
323 # check prefixes
324 if (match(ext, prefix_expr)) {
325 if (!prefix_num[opcode])
326 semantic_error("Unknown prefix: " opcode)
327 flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
328 }
329 if (length(flags) == 0)
330 continue
331 # check if last prefix
332 if (match(ext, lprefix1_expr)) {
333 lptable1[idx] = add_flags(lptable1[idx],flags)
334 variant = "INAT_VARIANT"
335 } else if (match(ext, lprefix2_expr)) {
336 lptable2[idx] = add_flags(lptable2[idx],flags)
337 variant = "INAT_VARIANT"
338 } else if (match(ext, lprefix3_expr)) {
339 lptable3[idx] = add_flags(lptable3[idx],flags)
340 variant = "INAT_VARIANT"
341 } else {
342 table[idx] = add_flags(table[idx],flags)
343 }
344 }
345 if (variant)
346 table[idx] = add_flags(table[idx],variant)
347}
348
349END {
350 if (awkchecked != "")
351 exit 1
352 # print escape opcode map's array
353 print "/* Escape opcode map array */"
354 print "const insn_attr_t const *inat_escape_tables[INAT_ESC_MAX + 1]" \
355 "[INAT_LSTPFX_MAX + 1] = {"
356 for (i = 0; i < geid; i++)
357 for (j = 0; j < max_lprefix; j++)
358 if (etable[i,j])
359 print " ["i"]["j"] = "etable[i,j]","
360 print "};\n"
361 # print group opcode map's array
362 print "/* Group opcode map array */"
363 print "const insn_attr_t const *inat_group_tables[INAT_GRP_MAX + 1]"\
364 "[INAT_LSTPFX_MAX + 1] = {"
365 for (i = 0; i < ggid; i++)
366 for (j = 0; j < max_lprefix; j++)
367 if (gtable[i,j])
368 print " ["i"]["j"] = "gtable[i,j]","
369 print "};\n"
370 # print AVX opcode map's array
371 print "/* AVX opcode map array */"
372 print "const insn_attr_t const *inat_avx_tables[X86_VEX_M_MAX + 1]"\
373 "[INAT_LSTPFX_MAX + 1] = {"
374 for (i = 0; i < gaid; i++)
375 for (j = 0; j < max_lprefix; j++)
376 if (atable[i,j])
377 print " ["i"]["j"] = "atable[i,j]","
378 print "};"
379}
380
diff --git a/arch/x86/tools/test_get_len.c b/arch/x86/tools/test_get_len.c
new file mode 100644
index 000000000000..d8214dc03fa7
--- /dev/null
+++ b/arch/x86/tools/test_get_len.c
@@ -0,0 +1,173 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) IBM Corporation, 2009
17 */
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <assert.h>
23#include <unistd.h>
24
25#define unlikely(cond) (cond)
26
27#include <asm/insn.h>
28#include <inat.c>
29#include <insn.c>
30
31/*
32 * Test of instruction analysis in general and insn_get_length() in
33 * particular. See if insn_get_length() and the disassembler agree
34 * on the length of each instruction in an elf disassembly.
35 *
36 * Usage: objdump -d a.out | awk -f distill.awk | ./test_get_len
37 */
38
39const char *prog;
40static int verbose;
41static int x86_64;
42
43static void usage(void)
44{
45 fprintf(stderr, "Usage: objdump -d a.out | awk -f distill.awk |"
46 " %s [-y|-n] [-v] \n", prog);
47 fprintf(stderr, "\t-y 64bit mode\n");
48 fprintf(stderr, "\t-n 32bit mode\n");
49 fprintf(stderr, "\t-v verbose mode\n");
50 exit(1);
51}
52
53static void malformed_line(const char *line, int line_nr)
54{
55 fprintf(stderr, "%s: malformed line %d:\n%s", prog, line_nr, line);
56 exit(3);
57}
58
59static void dump_field(FILE *fp, const char *name, const char *indent,
60 struct insn_field *field)
61{
62 fprintf(fp, "%s.%s = {\n", indent, name);
63 fprintf(fp, "%s\t.value = %d, bytes[] = {%x, %x, %x, %x},\n",
64 indent, field->value, field->bytes[0], field->bytes[1],
65 field->bytes[2], field->bytes[3]);
66 fprintf(fp, "%s\t.got = %d, .nbytes = %d},\n", indent,
67 field->got, field->nbytes);
68}
69
70static void dump_insn(FILE *fp, struct insn *insn)
71{
72 fprintf(fp, "Instruction = { \n");
73 dump_field(fp, "prefixes", "\t", &insn->prefixes);
74 dump_field(fp, "rex_prefix", "\t", &insn->rex_prefix);
75 dump_field(fp, "vex_prefix", "\t", &insn->vex_prefix);
76 dump_field(fp, "opcode", "\t", &insn->opcode);
77 dump_field(fp, "modrm", "\t", &insn->modrm);
78 dump_field(fp, "sib", "\t", &insn->sib);
79 dump_field(fp, "displacement", "\t", &insn->displacement);
80 dump_field(fp, "immediate1", "\t", &insn->immediate1);
81 dump_field(fp, "immediate2", "\t", &insn->immediate2);
82 fprintf(fp, "\t.attr = %x, .opnd_bytes = %d, .addr_bytes = %d,\n",
83 insn->attr, insn->opnd_bytes, insn->addr_bytes);
84 fprintf(fp, "\t.length = %d, .x86_64 = %d, .kaddr = %p}\n",
85 insn->length, insn->x86_64, insn->kaddr);
86}
87
88static void parse_args(int argc, char **argv)
89{
90 int c;
91 prog = argv[0];
92 while ((c = getopt(argc, argv, "ynv")) != -1) {
93 switch (c) {
94 case 'y':
95 x86_64 = 1;
96 break;
97 case 'n':
98 x86_64 = 0;
99 break;
100 case 'v':
101 verbose = 1;
102 break;
103 default:
104 usage();
105 }
106 }
107}
108
109#define BUFSIZE 256
110
111int main(int argc, char **argv)
112{
113 char line[BUFSIZE], sym[BUFSIZE] = "<unknown>";
114 unsigned char insn_buf[16];
115 struct insn insn;
116 int insns = 0, c;
117 int warnings = 0;
118
119 parse_args(argc, argv);
120
121 while (fgets(line, BUFSIZE, stdin)) {
122 char copy[BUFSIZE], *s, *tab1, *tab2;
123 int nb = 0;
124 unsigned int b;
125
126 if (line[0] == '<') {
127 /* Symbol line */
128 strcpy(sym, line);
129 continue;
130 }
131
132 insns++;
133 memset(insn_buf, 0, 16);
134 strcpy(copy, line);
135 tab1 = strchr(copy, '\t');
136 if (!tab1)
137 malformed_line(line, insns);
138 s = tab1 + 1;
139 s += strspn(s, " ");
140 tab2 = strchr(s, '\t');
141 if (!tab2)
142 malformed_line(line, insns);
143 *tab2 = '\0'; /* Characters beyond tab2 aren't examined */
144 while (s < tab2) {
145 if (sscanf(s, "%x", &b) == 1) {
146 insn_buf[nb++] = (unsigned char) b;
147 s += 3;
148 } else
149 break;
150 }
151 /* Decode an instruction */
152 insn_init(&insn, insn_buf, x86_64);
153 insn_get_length(&insn);
154 if (insn.length != nb) {
155 warnings++;
156 fprintf(stderr, "Warning: %s found difference at %s\n",
157 prog, sym);
158 fprintf(stderr, "Warning: %s", line);
159 fprintf(stderr, "Warning: objdump says %d bytes, but "
160 "insn_get_length() says %d\n", nb,
161 insn.length);
162 if (verbose)
163 dump_insn(stderr, &insn);
164 }
165 }
166 if (warnings)
167 fprintf(stderr, "Warning: decoded and checked %d"
168 " instructions with %d warnings\n", insns, warnings);
169 else
170 fprintf(stderr, "Succeed: decoded and checked %d"
171 " instructions\n", insns);
172 return 0;
173}
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index 58bc00f68b12..02b442e92007 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -393,7 +393,6 @@ static ctl_table abi_table2[] = {
393 393
394static ctl_table abi_root_table2[] = { 394static ctl_table abi_root_table2[] = {
395 { 395 {
396 .ctl_name = CTL_ABI,
397 .procname = "abi", 396 .procname = "abi",
398 .mode = 0555, 397 .mode = 0555,
399 .child = abi_table2 398 .child = abi_table2
diff --git a/crypto/proc.c b/crypto/proc.c
index 5dc07e442fca..1c38733c224d 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -25,28 +25,22 @@
25#ifdef CONFIG_CRYPTO_FIPS 25#ifdef CONFIG_CRYPTO_FIPS
26static struct ctl_table crypto_sysctl_table[] = { 26static struct ctl_table crypto_sysctl_table[] = {
27 { 27 {
28 .ctl_name = CTL_UNNUMBERED,
29 .procname = "fips_enabled", 28 .procname = "fips_enabled",
30 .data = &fips_enabled, 29 .data = &fips_enabled,
31 .maxlen = sizeof(int), 30 .maxlen = sizeof(int),
32 .mode = 0444, 31 .mode = 0444,
33 .proc_handler = &proc_dointvec 32 .proc_handler = proc_dointvec
34 },
35 {
36 .ctl_name = 0,
37 }, 33 },
34 {}
38}; 35};
39 36
40static struct ctl_table crypto_dir_table[] = { 37static struct ctl_table crypto_dir_table[] = {
41 { 38 {
42 .ctl_name = CTL_UNNUMBERED,
43 .procname = "crypto", 39 .procname = "crypto",
44 .mode = 0555, 40 .mode = 0555,
45 .child = crypto_sysctl_table 41 .child = crypto_sysctl_table
46 }, 42 },
47 { 43 {}
48 .ctl_name = 0,
49 },
50}; 44};
51 45
52static struct ctl_table_header *crypto_sysctls; 46static struct ctl_table_header *crypto_sysctls;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 614da5b8613a..e3749d0ba68b 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3557,67 +3557,65 @@ static ctl_table cdrom_table[] = {
3557 .data = &cdrom_sysctl_settings.info, 3557 .data = &cdrom_sysctl_settings.info,
3558 .maxlen = CDROM_STR_SIZE, 3558 .maxlen = CDROM_STR_SIZE,
3559 .mode = 0444, 3559 .mode = 0444,
3560 .proc_handler = &cdrom_sysctl_info, 3560 .proc_handler = cdrom_sysctl_info,
3561 }, 3561 },
3562 { 3562 {
3563 .procname = "autoclose", 3563 .procname = "autoclose",
3564 .data = &cdrom_sysctl_settings.autoclose, 3564 .data = &cdrom_sysctl_settings.autoclose,
3565 .maxlen = sizeof(int), 3565 .maxlen = sizeof(int),
3566 .mode = 0644, 3566 .mode = 0644,
3567 .proc_handler = &cdrom_sysctl_handler, 3567 .proc_handler = cdrom_sysctl_handler,
3568 }, 3568 },
3569 { 3569 {
3570 .procname = "autoeject", 3570 .procname = "autoeject",
3571 .data = &cdrom_sysctl_settings.autoeject, 3571 .data = &cdrom_sysctl_settings.autoeject,
3572 .maxlen = sizeof(int), 3572 .maxlen = sizeof(int),
3573 .mode = 0644, 3573 .mode = 0644,
3574 .proc_handler = &cdrom_sysctl_handler, 3574 .proc_handler = cdrom_sysctl_handler,
3575 }, 3575 },
3576 { 3576 {
3577 .procname = "debug", 3577 .procname = "debug",
3578 .data = &cdrom_sysctl_settings.debug, 3578 .data = &cdrom_sysctl_settings.debug,
3579 .maxlen = sizeof(int), 3579 .maxlen = sizeof(int),
3580 .mode = 0644, 3580 .mode = 0644,
3581 .proc_handler = &cdrom_sysctl_handler, 3581 .proc_handler = cdrom_sysctl_handler,
3582 }, 3582 },
3583 { 3583 {
3584 .procname = "lock", 3584 .procname = "lock",
3585 .data = &cdrom_sysctl_settings.lock, 3585 .data = &cdrom_sysctl_settings.lock,
3586 .maxlen = sizeof(int), 3586 .maxlen = sizeof(int),
3587 .mode = 0644, 3587 .mode = 0644,
3588 .proc_handler = &cdrom_sysctl_handler, 3588 .proc_handler = cdrom_sysctl_handler,
3589 }, 3589 },
3590 { 3590 {
3591 .procname = "check_media", 3591 .procname = "check_media",
3592 .data = &cdrom_sysctl_settings.check, 3592 .data = &cdrom_sysctl_settings.check,
3593 .maxlen = sizeof(int), 3593 .maxlen = sizeof(int),
3594 .mode = 0644, 3594 .mode = 0644,
3595 .proc_handler = &cdrom_sysctl_handler 3595 .proc_handler = cdrom_sysctl_handler
3596 }, 3596 },
3597 { .ctl_name = 0 } 3597 { }
3598}; 3598};
3599 3599
3600static ctl_table cdrom_cdrom_table[] = { 3600static ctl_table cdrom_cdrom_table[] = {
3601 { 3601 {
3602 .ctl_name = DEV_CDROM,
3603 .procname = "cdrom", 3602 .procname = "cdrom",
3604 .maxlen = 0, 3603 .maxlen = 0,
3605 .mode = 0555, 3604 .mode = 0555,
3606 .child = cdrom_table, 3605 .child = cdrom_table,
3607 }, 3606 },
3608 { .ctl_name = 0 } 3607 { }
3609}; 3608};
3610 3609
3611/* Make sure that /proc/sys/dev is there */ 3610/* Make sure that /proc/sys/dev is there */
3612static ctl_table cdrom_root_table[] = { 3611static ctl_table cdrom_root_table[] = {
3613 { 3612 {
3614 .ctl_name = CTL_DEV,
3615 .procname = "dev", 3613 .procname = "dev",
3616 .maxlen = 0, 3614 .maxlen = 0,
3617 .mode = 0555, 3615 .mode = 0555,
3618 .child = cdrom_cdrom_table, 3616 .child = cdrom_cdrom_table,
3619 }, 3617 },
3620 { .ctl_name = 0 } 3618 { }
3621}; 3619};
3622static struct ctl_table_header *cdrom_sysctl_header; 3620static struct ctl_table_header *cdrom_sysctl_header;
3623 3621
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 70a770ac0138..e481c5938bad 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -675,36 +675,33 @@ static int hpet_is_known(struct hpet_data *hdp)
675 675
676static ctl_table hpet_table[] = { 676static ctl_table hpet_table[] = {
677 { 677 {
678 .ctl_name = CTL_UNNUMBERED,
679 .procname = "max-user-freq", 678 .procname = "max-user-freq",
680 .data = &hpet_max_freq, 679 .data = &hpet_max_freq,
681 .maxlen = sizeof(int), 680 .maxlen = sizeof(int),
682 .mode = 0644, 681 .mode = 0644,
683 .proc_handler = &proc_dointvec, 682 .proc_handler = proc_dointvec,
684 }, 683 },
685 {.ctl_name = 0} 684 {}
686}; 685};
687 686
688static ctl_table hpet_root[] = { 687static ctl_table hpet_root[] = {
689 { 688 {
690 .ctl_name = CTL_UNNUMBERED,
691 .procname = "hpet", 689 .procname = "hpet",
692 .maxlen = 0, 690 .maxlen = 0,
693 .mode = 0555, 691 .mode = 0555,
694 .child = hpet_table, 692 .child = hpet_table,
695 }, 693 },
696 {.ctl_name = 0} 694 {}
697}; 695};
698 696
699static ctl_table dev_root[] = { 697static ctl_table dev_root[] = {
700 { 698 {
701 .ctl_name = CTL_DEV,
702 .procname = "dev", 699 .procname = "dev",
703 .maxlen = 0, 700 .maxlen = 0,
704 .mode = 0555, 701 .mode = 0555,
705 .child = hpet_root, 702 .child = hpet_root,
706 }, 703 },
707 {.ctl_name = 0} 704 {}
708}; 705};
709 706
710static struct ctl_table_header *sysctl_header; 707static struct ctl_table_header *sysctl_header;
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 2e66b5f773dd..0dec5da000ef 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -660,26 +660,23 @@ static struct ipmi_smi_watcher smi_watcher = {
660#include <linux/sysctl.h> 660#include <linux/sysctl.h>
661 661
662static ctl_table ipmi_table[] = { 662static ctl_table ipmi_table[] = {
663 { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE, 663 { .procname = "poweroff_powercycle",
664 .procname = "poweroff_powercycle",
665 .data = &poweroff_powercycle, 664 .data = &poweroff_powercycle,
666 .maxlen = sizeof(poweroff_powercycle), 665 .maxlen = sizeof(poweroff_powercycle),
667 .mode = 0644, 666 .mode = 0644,
668 .proc_handler = &proc_dointvec }, 667 .proc_handler = proc_dointvec },
669 { } 668 { }
670}; 669};
671 670
672static ctl_table ipmi_dir_table[] = { 671static ctl_table ipmi_dir_table[] = {
673 { .ctl_name = DEV_IPMI, 672 { .procname = "ipmi",
674 .procname = "ipmi",
675 .mode = 0555, 673 .mode = 0555,
676 .child = ipmi_table }, 674 .child = ipmi_table },
677 { } 675 { }
678}; 676};
679 677
680static ctl_table ipmi_root_table[] = { 678static ctl_table ipmi_root_table[] = {
681 { .ctl_name = CTL_DEV, 679 { .procname = "dev",
682 .procname = "dev",
683 .mode = 0555, 680 .mode = 0555,
684 .child = ipmi_dir_table }, 681 .child = ipmi_dir_table },
685 { } 682 { }
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 62f282e67638..d86c0bc05c1c 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -431,30 +431,25 @@ static struct cdev ptmx_cdev;
431 431
432static struct ctl_table pty_table[] = { 432static struct ctl_table pty_table[] = {
433 { 433 {
434 .ctl_name = PTY_MAX,
435 .procname = "max", 434 .procname = "max",
436 .maxlen = sizeof(int), 435 .maxlen = sizeof(int),
437 .mode = 0644, 436 .mode = 0644,
438 .data = &pty_limit, 437 .data = &pty_limit,
439 .proc_handler = &proc_dointvec_minmax, 438 .proc_handler = proc_dointvec_minmax,
440 .strategy = &sysctl_intvec,
441 .extra1 = &pty_limit_min, 439 .extra1 = &pty_limit_min,
442 .extra2 = &pty_limit_max, 440 .extra2 = &pty_limit_max,
443 }, { 441 }, {
444 .ctl_name = PTY_NR,
445 .procname = "nr", 442 .procname = "nr",
446 .maxlen = sizeof(int), 443 .maxlen = sizeof(int),
447 .mode = 0444, 444 .mode = 0444,
448 .data = &pty_count, 445 .data = &pty_count,
449 .proc_handler = &proc_dointvec, 446 .proc_handler = proc_dointvec,
450 }, { 447 },
451 .ctl_name = 0 448 {}
452 }
453}; 449};
454 450
455static struct ctl_table pty_kern_table[] = { 451static struct ctl_table pty_kern_table[] = {
456 { 452 {
457 .ctl_name = KERN_PTY,
458 .procname = "pty", 453 .procname = "pty",
459 .mode = 0555, 454 .mode = 0555,
460 .child = pty_table, 455 .child = pty_table,
@@ -464,7 +459,6 @@ static struct ctl_table pty_kern_table[] = {
464 459
465static struct ctl_table pty_root_table[] = { 460static struct ctl_table pty_root_table[] = {
466 { 461 {
467 .ctl_name = CTL_KERN,
468 .procname = "kernel", 462 .procname = "kernel",
469 .mode = 0555, 463 .mode = 0555,
470 .child = pty_kern_table, 464 .child = pty_kern_table,
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 04b505e5a5e2..dcd08635cf1b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1257,94 +1257,54 @@ static int proc_do_uuid(ctl_table *table, int write,
1257 return proc_dostring(&fake_table, write, buffer, lenp, ppos); 1257 return proc_dostring(&fake_table, write, buffer, lenp, ppos);
1258} 1258}
1259 1259
1260static int uuid_strategy(ctl_table *table,
1261 void __user *oldval, size_t __user *oldlenp,
1262 void __user *newval, size_t newlen)
1263{
1264 unsigned char tmp_uuid[16], *uuid;
1265 unsigned int len;
1266
1267 if (!oldval || !oldlenp)
1268 return 1;
1269
1270 uuid = table->data;
1271 if (!uuid) {
1272 uuid = tmp_uuid;
1273 uuid[8] = 0;
1274 }
1275 if (uuid[8] == 0)
1276 generate_random_uuid(uuid);
1277
1278 if (get_user(len, oldlenp))
1279 return -EFAULT;
1280 if (len) {
1281 if (len > 16)
1282 len = 16;
1283 if (copy_to_user(oldval, uuid, len) ||
1284 put_user(len, oldlenp))
1285 return -EFAULT;
1286 }
1287 return 1;
1288}
1289
1290static int sysctl_poolsize = INPUT_POOL_WORDS * 32; 1260static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
1291ctl_table random_table[] = { 1261ctl_table random_table[] = {
1292 { 1262 {
1293 .ctl_name = RANDOM_POOLSIZE,
1294 .procname = "poolsize", 1263 .procname = "poolsize",
1295 .data = &sysctl_poolsize, 1264 .data = &sysctl_poolsize,
1296 .maxlen = sizeof(int), 1265 .maxlen = sizeof(int),
1297 .mode = 0444, 1266 .mode = 0444,
1298 .proc_handler = &proc_dointvec, 1267 .proc_handler = proc_dointvec,
1299 }, 1268 },
1300 { 1269 {
1301 .ctl_name = RANDOM_ENTROPY_COUNT,
1302 .procname = "entropy_avail", 1270 .procname = "entropy_avail",
1303 .maxlen = sizeof(int), 1271 .maxlen = sizeof(int),
1304 .mode = 0444, 1272 .mode = 0444,
1305 .proc_handler = &proc_dointvec, 1273 .proc_handler = proc_dointvec,
1306 .data = &input_pool.entropy_count, 1274 .data = &input_pool.entropy_count,
1307 }, 1275 },
1308 { 1276 {
1309 .ctl_name = RANDOM_READ_THRESH,
1310 .procname = "read_wakeup_threshold", 1277 .procname = "read_wakeup_threshold",
1311 .data = &random_read_wakeup_thresh, 1278 .data = &random_read_wakeup_thresh,
1312 .maxlen = sizeof(int), 1279 .maxlen = sizeof(int),
1313 .mode = 0644, 1280 .mode = 0644,
1314 .proc_handler = &proc_dointvec_minmax, 1281 .proc_handler = proc_dointvec_minmax,
1315 .strategy = &sysctl_intvec,
1316 .extra1 = &min_read_thresh, 1282 .extra1 = &min_read_thresh,
1317 .extra2 = &max_read_thresh, 1283 .extra2 = &max_read_thresh,
1318 }, 1284 },
1319 { 1285 {
1320 .ctl_name = RANDOM_WRITE_THRESH,
1321 .procname = "write_wakeup_threshold", 1286 .procname = "write_wakeup_threshold",
1322 .data = &random_write_wakeup_thresh, 1287 .data = &random_write_wakeup_thresh,
1323 .maxlen = sizeof(int), 1288 .maxlen = sizeof(int),
1324 .mode = 0644, 1289 .mode = 0644,
1325 .proc_handler = &proc_dointvec_minmax, 1290 .proc_handler = proc_dointvec_minmax,
1326 .strategy = &sysctl_intvec,
1327 .extra1 = &min_write_thresh, 1291 .extra1 = &min_write_thresh,
1328 .extra2 = &max_write_thresh, 1292 .extra2 = &max_write_thresh,
1329 }, 1293 },
1330 { 1294 {
1331 .ctl_name = RANDOM_BOOT_ID,
1332 .procname = "boot_id", 1295 .procname = "boot_id",
1333 .data = &sysctl_bootid, 1296 .data = &sysctl_bootid,
1334 .maxlen = 16, 1297 .maxlen = 16,
1335 .mode = 0444, 1298 .mode = 0444,
1336 .proc_handler = &proc_do_uuid, 1299 .proc_handler = proc_do_uuid,
1337 .strategy = &uuid_strategy,
1338 }, 1300 },
1339 { 1301 {
1340 .ctl_name = RANDOM_UUID,
1341 .procname = "uuid", 1302 .procname = "uuid",
1342 .maxlen = 16, 1303 .maxlen = 16,
1343 .mode = 0444, 1304 .mode = 0444,
1344 .proc_handler = &proc_do_uuid, 1305 .proc_handler = proc_do_uuid,
1345 .strategy = &uuid_strategy,
1346 }, 1306 },
1347 { .ctl_name = 0 } 1307 { }
1348}; 1308};
1349#endif /* CONFIG_SYSCTL */ 1309#endif /* CONFIG_SYSCTL */
1350 1310
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index bc4ab3e54550..95acb8c880f4 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -282,34 +282,31 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
282 */ 282 */
283static ctl_table rtc_table[] = { 283static ctl_table rtc_table[] = {
284 { 284 {
285 .ctl_name = CTL_UNNUMBERED,
286 .procname = "max-user-freq", 285 .procname = "max-user-freq",
287 .data = &rtc_max_user_freq, 286 .data = &rtc_max_user_freq,
288 .maxlen = sizeof(int), 287 .maxlen = sizeof(int),
289 .mode = 0644, 288 .mode = 0644,
290 .proc_handler = &proc_dointvec, 289 .proc_handler = proc_dointvec,
291 }, 290 },
292 { .ctl_name = 0 } 291 { }
293}; 292};
294 293
295static ctl_table rtc_root[] = { 294static ctl_table rtc_root[] = {
296 { 295 {
297 .ctl_name = CTL_UNNUMBERED,
298 .procname = "rtc", 296 .procname = "rtc",
299 .mode = 0555, 297 .mode = 0555,
300 .child = rtc_table, 298 .child = rtc_table,
301 }, 299 },
302 { .ctl_name = 0 } 300 { }
303}; 301};
304 302
305static ctl_table dev_root[] = { 303static ctl_table dev_root[] = {
306 { 304 {
307 .ctl_name = CTL_DEV,
308 .procname = "dev", 305 .procname = "dev",
309 .mode = 0555, 306 .mode = 0555,
310 .child = rtc_root, 307 .child = rtc_root,
311 }, 308 },
312 { .ctl_name = 0 } 309 { }
313}; 310};
314 311
315static struct ctl_table_header *sysctl_header; 312static struct ctl_table_header *sysctl_header;
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
index 713ed7d37247..689cc6a6214d 100644
--- a/drivers/edac/edac_mce_amd.c
+++ b/drivers/edac/edac_mce_amd.c
@@ -3,7 +3,6 @@
3 3
4static bool report_gart_errors; 4static bool report_gart_errors;
5static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); 5static void (*nb_bus_decoder)(int node_id, struct err_regs *regs);
6static void (*orig_mce_callback)(struct mce *m);
7 6
8void amd_report_gart_errors(bool v) 7void amd_report_gart_errors(bool v)
9{ 8{
@@ -363,8 +362,10 @@ static inline void amd_decode_err_code(unsigned int ec)
363 pr_warning("Huh? Unknown MCE error 0x%x\n", ec); 362 pr_warning("Huh? Unknown MCE error 0x%x\n", ec);
364} 363}
365 364
366static void amd_decode_mce(struct mce *m) 365static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
366 void *data)
367{ 367{
368 struct mce *m = (struct mce *)data;
368 struct err_regs regs; 369 struct err_regs regs;
369 int node, ecc; 370 int node, ecc;
370 371
@@ -420,20 +421,22 @@ static void amd_decode_mce(struct mce *m)
420 } 421 }
421 422
422 amd_decode_err_code(m->status & 0xffff); 423 amd_decode_err_code(m->status & 0xffff);
424
425 return NOTIFY_STOP;
423} 426}
424 427
428static struct notifier_block amd_mce_dec_nb = {
429 .notifier_call = amd_decode_mce,
430};
431
425static int __init mce_amd_init(void) 432static int __init mce_amd_init(void)
426{ 433{
427 /* 434 /*
428 * We can decode MCEs for Opteron and later CPUs: 435 * We can decode MCEs for Opteron and later CPUs:
429 */ 436 */
430 if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && 437 if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
431 (boot_cpu_data.x86 >= 0xf)) { 438 (boot_cpu_data.x86 >= 0xf))
432 /* safe the default decode mce callback */ 439 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
433 orig_mce_callback = x86_mce_decode_callback;
434
435 x86_mce_decode_callback = amd_decode_mce;
436 }
437 440
438 return 0; 441 return 0;
439} 442}
@@ -442,7 +445,7 @@ early_initcall(mce_amd_init);
442#ifdef MODULE 445#ifdef MODULE
443static void __exit mce_amd_exit(void) 446static void __exit mce_amd_exit(void)
444{ 447{
445 x86_mce_decode_callback = orig_mce_callback; 448 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
446} 449}
447 450
448MODULE_DESCRIPTION("AMD MCE decoder"); 451MODULE_DESCRIPTION("AMD MCE decoder");
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index cc9f27514aef..7b4ef5bb556b 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -27,54 +27,49 @@ static int mouse_last_keycode;
27/* file(s) in /proc/sys/dev/mac_hid */ 27/* file(s) in /proc/sys/dev/mac_hid */
28static ctl_table mac_hid_files[] = { 28static ctl_table mac_hid_files[] = {
29 { 29 {
30 .ctl_name = DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
31 .procname = "mouse_button_emulation", 30 .procname = "mouse_button_emulation",
32 .data = &mouse_emulate_buttons, 31 .data = &mouse_emulate_buttons,
33 .maxlen = sizeof(int), 32 .maxlen = sizeof(int),
34 .mode = 0644, 33 .mode = 0644,
35 .proc_handler = &proc_dointvec, 34 .proc_handler = proc_dointvec,
36 }, 35 },
37 { 36 {
38 .ctl_name = DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE,
39 .procname = "mouse_button2_keycode", 37 .procname = "mouse_button2_keycode",
40 .data = &mouse_button2_keycode, 38 .data = &mouse_button2_keycode,
41 .maxlen = sizeof(int), 39 .maxlen = sizeof(int),
42 .mode = 0644, 40 .mode = 0644,
43 .proc_handler = &proc_dointvec, 41 .proc_handler = proc_dointvec,
44 }, 42 },
45 { 43 {
46 .ctl_name = DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE,
47 .procname = "mouse_button3_keycode", 44 .procname = "mouse_button3_keycode",
48 .data = &mouse_button3_keycode, 45 .data = &mouse_button3_keycode,
49 .maxlen = sizeof(int), 46 .maxlen = sizeof(int),
50 .mode = 0644, 47 .mode = 0644,
51 .proc_handler = &proc_dointvec, 48 .proc_handler = proc_dointvec,
52 }, 49 },
53 { .ctl_name = 0 } 50 { }
54}; 51};
55 52
56/* dir in /proc/sys/dev */ 53/* dir in /proc/sys/dev */
57static ctl_table mac_hid_dir[] = { 54static ctl_table mac_hid_dir[] = {
58 { 55 {
59 .ctl_name = DEV_MAC_HID,
60 .procname = "mac_hid", 56 .procname = "mac_hid",
61 .maxlen = 0, 57 .maxlen = 0,
62 .mode = 0555, 58 .mode = 0555,
63 .child = mac_hid_files, 59 .child = mac_hid_files,
64 }, 60 },
65 { .ctl_name = 0 } 61 { }
66}; 62};
67 63
68/* /proc/sys/dev itself, in case that is not there yet */ 64/* /proc/sys/dev itself, in case that is not there yet */
69static ctl_table mac_hid_root_dir[] = { 65static ctl_table mac_hid_root_dir[] = {
70 { 66 {
71 .ctl_name = CTL_DEV,
72 .procname = "dev", 67 .procname = "dev",
73 .maxlen = 0, 68 .maxlen = 0,
74 .mode = 0555, 69 .mode = 0555,
75 .child = mac_hid_dir, 70 .child = mac_hid_dir,
76 }, 71 },
77 { .ctl_name = 0 } 72 { }
78}; 73};
79 74
80static struct ctl_table_header *mac_hid_sysctl_header; 75static struct ctl_table_header *mac_hid_sysctl_header;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b182f86a19dd..5f154ef1e4be 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -98,44 +98,40 @@ static struct ctl_table_header *raid_table_header;
98 98
99static ctl_table raid_table[] = { 99static ctl_table raid_table[] = {
100 { 100 {
101 .ctl_name = DEV_RAID_SPEED_LIMIT_MIN,
102 .procname = "speed_limit_min", 101 .procname = "speed_limit_min",
103 .data = &sysctl_speed_limit_min, 102 .data = &sysctl_speed_limit_min,
104 .maxlen = sizeof(int), 103 .maxlen = sizeof(int),
105 .mode = S_IRUGO|S_IWUSR, 104 .mode = S_IRUGO|S_IWUSR,
106 .proc_handler = &proc_dointvec, 105 .proc_handler = proc_dointvec,
107 }, 106 },
108 { 107 {
109 .ctl_name = DEV_RAID_SPEED_LIMIT_MAX,
110 .procname = "speed_limit_max", 108 .procname = "speed_limit_max",
111 .data = &sysctl_speed_limit_max, 109 .data = &sysctl_speed_limit_max,
112 .maxlen = sizeof(int), 110 .maxlen = sizeof(int),
113 .mode = S_IRUGO|S_IWUSR, 111 .mode = S_IRUGO|S_IWUSR,
114 .proc_handler = &proc_dointvec, 112 .proc_handler = proc_dointvec,
115 }, 113 },
116 { .ctl_name = 0 } 114 { }
117}; 115};
118 116
119static ctl_table raid_dir_table[] = { 117static ctl_table raid_dir_table[] = {
120 { 118 {
121 .ctl_name = DEV_RAID,
122 .procname = "raid", 119 .procname = "raid",
123 .maxlen = 0, 120 .maxlen = 0,
124 .mode = S_IRUGO|S_IXUGO, 121 .mode = S_IRUGO|S_IXUGO,
125 .child = raid_table, 122 .child = raid_table,
126 }, 123 },
127 { .ctl_name = 0 } 124 { }
128}; 125};
129 126
130static ctl_table raid_root_table[] = { 127static ctl_table raid_root_table[] = {
131 { 128 {
132 .ctl_name = CTL_DEV,
133 .procname = "dev", 129 .procname = "dev",
134 .maxlen = 0, 130 .maxlen = 0,
135 .mode = 0555, 131 .mode = 0555,
136 .child = raid_dir_table, 132 .child = raid_dir_table,
137 }, 133 },
138 { .ctl_name = 0 } 134 { }
139}; 135};
140 136
141static const struct block_device_operations md_fops; 137static const struct block_device_operations md_fops;
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index a87a477c87f2..b134553eb3b5 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -195,6 +195,24 @@ config RADIO_MAESTRO
195 To compile this driver as a module, choose M here: the 195 To compile this driver as a module, choose M here: the
196 module will be called radio-maestro. 196 module will be called radio-maestro.
197 197
198config RADIO_MIROPCM20
199 tristate "miroSOUND PCM20 radio"
200 depends on ISA && VIDEO_V4L2
201 select SND_MIRO
202 ---help---
203 Choose Y here if you have this FM radio card. You also need to enable
204 the ALSA sound system. This choice automatically selects the ALSA
205 sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this
206 is required for the radio-miropcm20.
207
208 In order to control your radio card, you will need to use programs
209 that are compatible with the Video For Linux API. Information on
210 this API and pointers to "v4l" programs may be found at
211 <file:Documentation/video4linux/API.html>.
212
213 To compile this driver as a module, choose M here: the
214 module will be called radio-miropcm20.
215
198config RADIO_SF16FMI 216config RADIO_SF16FMI
199 tristate "SF16FMI Radio" 217 tristate "SF16FMI Radio"
200 depends on ISA && VIDEO_V4L2 218 depends on ISA && VIDEO_V4L2
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 2a1be3bf4f7c..8a63d543ae41 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
18obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o 18obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
19obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o 19obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
20obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o 20obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
21obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
21obj-$(CONFIG_USB_DSBR) += dsbr100.o 22obj-$(CONFIG_USB_DSBR) += dsbr100.o
22obj-$(CONFIG_RADIO_SI470X) += si470x/ 23obj-$(CONFIG_RADIO_SI470X) += si470x/
23obj-$(CONFIG_USB_MR800) += radio-mr800.o 24obj-$(CONFIG_USB_MR800) += radio-mr800.o
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
new file mode 100644
index 000000000000..4ff885445fd4
--- /dev/null
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -0,0 +1,270 @@
1/* Miro PCM20 radio driver for Linux radio support
2 * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
3 * Thanks to Norberto Pellici for the ACI device interface specification
4 * The API part is based on the radiotrack driver by M. Kirkwood
5 * This driver relies on the aci mixer provided by the snd-miro
6 * ALSA driver.
7 * Look there for further info...
8 */
9
10/* What ever you think about the ACI, version 0x07 is not very well!
11 * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
12 * conditions... Robert
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/videodev2.h>
18#include <media/v4l2-device.h>
19#include <media/v4l2-ioctl.h>
20#include <sound/aci.h>
21
22static int radio_nr = -1;
23module_param(radio_nr, int, 0);
24MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)");
25
26static int mono;
27module_param(mono, bool, 0);
28MODULE_PARM_DESC(mono, "Force tuner into mono mode.");
29
30struct pcm20 {
31 struct v4l2_device v4l2_dev;
32 struct video_device vdev;
33 unsigned long freq;
34 int muted;
35 struct snd_miro_aci *aci;
36};
37
38static struct pcm20 pcm20_card = {
39 .freq = 87*16000,
40 .muted = 1,
41};
42
43static int pcm20_mute(struct pcm20 *dev, unsigned char mute)
44{
45 dev->muted = mute;
46 return snd_aci_cmd(dev->aci, ACI_SET_TUNERMUTE, mute, -1);
47}
48
49static int pcm20_stereo(struct pcm20 *dev, unsigned char stereo)
50{
51 return snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO, !stereo, -1);
52}
53
54static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
55{
56 unsigned char freql;
57 unsigned char freqh;
58 struct snd_miro_aci *aci = dev->aci;
59
60 dev->freq = freq;
61
62 freq /= 160;
63 if (!(aci->aci_version == 0x07 || aci->aci_version >= 0xb0))
64 freq /= 10; /* I don't know exactly which version
65 * needs this hack */
66 freql = freq & 0xff;
67 freqh = freq >> 8;
68
69 pcm20_stereo(dev, !mono);
70 return snd_aci_cmd(aci, ACI_WRITE_TUNE, freql, freqh);
71}
72
73static const struct v4l2_file_operations pcm20_fops = {
74 .owner = THIS_MODULE,
75 .ioctl = video_ioctl2,
76};
77
78static int vidioc_querycap(struct file *file, void *priv,
79 struct v4l2_capability *v)
80{
81 strlcpy(v->driver, "Miro PCM20", sizeof(v->driver));
82 strlcpy(v->card, "Miro PCM20", sizeof(v->card));
83 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
84 v->version = 0x1;
85 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
86 return 0;
87}
88
89static int vidioc_g_tuner(struct file *file, void *priv,
90 struct v4l2_tuner *v)
91{
92 if (v->index) /* Only 1 tuner */
93 return -EINVAL;
94 strlcpy(v->name, "FM", sizeof(v->name));
95 v->type = V4L2_TUNER_RADIO;
96 v->rangelow = 87*16000;
97 v->rangehigh = 108*16000;
98 v->signal = 0xffff;
99 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
100 v->capability = V4L2_TUNER_CAP_LOW;
101 v->audmode = V4L2_TUNER_MODE_MONO;
102 return 0;
103}
104
105static int vidioc_s_tuner(struct file *file, void *priv,
106 struct v4l2_tuner *v)
107{
108 return v->index ? -EINVAL : 0;
109}
110
111static int vidioc_g_frequency(struct file *file, void *priv,
112 struct v4l2_frequency *f)
113{
114 struct pcm20 *dev = video_drvdata(file);
115
116 if (f->tuner != 0)
117 return -EINVAL;
118
119 f->type = V4L2_TUNER_RADIO;
120 f->frequency = dev->freq;
121 return 0;
122}
123
124
125static int vidioc_s_frequency(struct file *file, void *priv,
126 struct v4l2_frequency *f)
127{
128 struct pcm20 *dev = video_drvdata(file);
129
130 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
131 return -EINVAL;
132
133 dev->freq = f->frequency;
134 pcm20_setfreq(dev, f->frequency);
135 return 0;
136}
137
138static int vidioc_queryctrl(struct file *file, void *priv,
139 struct v4l2_queryctrl *qc)
140{
141 switch (qc->id) {
142 case V4L2_CID_AUDIO_MUTE:
143 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
144 }
145 return -EINVAL;
146}
147
148static int vidioc_g_ctrl(struct file *file, void *priv,
149 struct v4l2_control *ctrl)
150{
151 struct pcm20 *dev = video_drvdata(file);
152
153 switch (ctrl->id) {
154 case V4L2_CID_AUDIO_MUTE:
155 ctrl->value = dev->muted;
156 break;
157 default:
158 return -EINVAL;
159 }
160 return 0;
161}
162
163static int vidioc_s_ctrl(struct file *file, void *priv,
164 struct v4l2_control *ctrl)
165{
166 struct pcm20 *dev = video_drvdata(file);
167
168 switch (ctrl->id) {
169 case V4L2_CID_AUDIO_MUTE:
170 pcm20_mute(dev, ctrl->value);
171 break;
172 default:
173 return -EINVAL;
174 }
175 return 0;
176}
177
178static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
179{
180 *i = 0;
181 return 0;
182}
183
184static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
185{
186 return i ? -EINVAL : 0;
187}
188
189static int vidioc_g_audio(struct file *file, void *priv,
190 struct v4l2_audio *a)
191{
192 a->index = 0;
193 strlcpy(a->name, "Radio", sizeof(a->name));
194 a->capability = V4L2_AUDCAP_STEREO;
195 return 0;
196}
197
198static int vidioc_s_audio(struct file *file, void *priv,
199 struct v4l2_audio *a)
200{
201 return a->index ? -EINVAL : 0;
202}
203
204static const struct v4l2_ioctl_ops pcm20_ioctl_ops = {
205 .vidioc_querycap = vidioc_querycap,
206 .vidioc_g_tuner = vidioc_g_tuner,
207 .vidioc_s_tuner = vidioc_s_tuner,
208 .vidioc_g_frequency = vidioc_g_frequency,
209 .vidioc_s_frequency = vidioc_s_frequency,
210 .vidioc_queryctrl = vidioc_queryctrl,
211 .vidioc_g_ctrl = vidioc_g_ctrl,
212 .vidioc_s_ctrl = vidioc_s_ctrl,
213 .vidioc_g_audio = vidioc_g_audio,
214 .vidioc_s_audio = vidioc_s_audio,
215 .vidioc_g_input = vidioc_g_input,
216 .vidioc_s_input = vidioc_s_input,
217};
218
219static int __init pcm20_init(void)
220{
221 struct pcm20 *dev = &pcm20_card;
222 struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
223 int res;
224
225 dev->aci = snd_aci_get_aci();
226 if (dev->aci == NULL) {
227 v4l2_err(v4l2_dev,
228 "you must load the snd-miro driver first!\n");
229 return -ENODEV;
230 }
231 strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
232
233
234 res = v4l2_device_register(NULL, v4l2_dev);
235 if (res < 0) {
236 v4l2_err(v4l2_dev, "could not register v4l2_device\n");
237 return -EINVAL;
238 }
239
240 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
241 dev->vdev.v4l2_dev = v4l2_dev;
242 dev->vdev.fops = &pcm20_fops;
243 dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
244 dev->vdev.release = video_device_release_empty;
245 video_set_drvdata(&dev->vdev, dev);
246
247 if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
248 goto fail;
249
250 v4l2_info(v4l2_dev, "Mirosound PCM20 Radio tuner\n");
251 return 0;
252fail:
253 v4l2_device_unregister(v4l2_dev);
254 return -EINVAL;
255}
256
257MODULE_AUTHOR("Ruurd Reitsma, Krzysztof Helt");
258MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
259MODULE_LICENSE("GPL");
260
261static void __exit pcm20_cleanup(void)
262{
263 struct pcm20 *dev = &pcm20_card;
264
265 video_unregister_device(&dev->vdev);
266 v4l2_device_unregister(&dev->v4l2_dev);
267}
268
269module_init(pcm20_init);
270module_exit(pcm20_cleanup);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 570be139f9df..08f2d07bf56a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -121,6 +121,12 @@ config TWL4030_POWER
121 and load scripts controling which resources are switched off/on 121 and load scripts controling which resources are switched off/on
122 or reset when a sleep, wakeup or warm reset event occurs. 122 or reset when a sleep, wakeup or warm reset event occurs.
123 123
124config TWL4030_CODEC
125 bool
126 depends on TWL4030_CORE
127 select MFD_CORE
128 default n
129
124config MFD_TMIO 130config MFD_TMIO
125 bool 131 bool
126 default n 132 default n
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f3b277b90d40..af0fc903cec8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
26 26
27obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o 27obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
28obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o 28obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
29obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
29 30
30obj-$(CONFIG_MFD_MC13783) += mc13783-core.o 31obj-$(CONFIG_MFD_MC13783) += mc13783-core.o
31 32
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
new file mode 100644
index 000000000000..77b914907d7c
--- /dev/null
+++ b/drivers/mfd/twl4030-codec.c
@@ -0,0 +1,276 @@
1/*
2 * MFD driver for twl4030 codec submodule
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/types.h>
26#include <linux/kernel.h>
27#include <linux/fs.h>
28#include <linux/platform_device.h>
29#include <linux/i2c/twl4030.h>
30#include <linux/mfd/core.h>
31#include <linux/mfd/twl4030-codec.h>
32
33#define TWL4030_CODEC_CELLS 2
34
35static struct platform_device *twl4030_codec_dev;
36
37struct twl4030_codec_resource {
38 int request_count;
39 u8 reg;
40 u8 mask;
41};
42
43struct twl4030_codec {
44 unsigned int audio_mclk;
45 struct mutex mutex;
46 struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX];
47 struct mfd_cell cells[TWL4030_CODEC_CELLS];
48};
49
50/*
51 * Modify the resource, the function returns the content of the register
52 * after the modification.
53 */
54static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable)
55{
56 struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
57 u8 val;
58
59 twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
60 codec->resource[id].reg);
61
62 if (enable)
63 val |= codec->resource[id].mask;
64 else
65 val &= ~codec->resource[id].mask;
66
67 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
68 val, codec->resource[id].reg);
69
70 return val;
71}
72
73static inline int twl4030_codec_get_resource(enum twl4030_codec_res id)
74{
75 struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
76 u8 val;
77
78 twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
79 codec->resource[id].reg);
80
81 return val;
82}
83
84/*
85 * Enable the resource.
86 * The function returns with error or the content of the register
87 */
88int twl4030_codec_enable_resource(enum twl4030_codec_res id)
89{
90 struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
91 int val;
92
93 if (id >= TWL4030_CODEC_RES_MAX) {
94 dev_err(&twl4030_codec_dev->dev,
95 "Invalid resource ID (%u)\n", id);
96 return -EINVAL;
97 }
98
99 mutex_lock(&codec->mutex);
100 if (!codec->resource[id].request_count)
101 /* Resource was disabled, enable it */
102 val = twl4030_codec_set_resource(id, 1);
103 else
104 val = twl4030_codec_get_resource(id);
105
106 codec->resource[id].request_count++;
107 mutex_unlock(&codec->mutex);
108
109 return val;
110}
111EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource);
112
113/*
114 * Disable the resource.
115 * The function returns with error or the content of the register
116 */
117int twl4030_codec_disable_resource(unsigned id)
118{
119 struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
120 int val;
121
122 if (id >= TWL4030_CODEC_RES_MAX) {
123 dev_err(&twl4030_codec_dev->dev,
124 "Invalid resource ID (%u)\n", id);
125 return -EINVAL;
126 }
127
128 mutex_lock(&codec->mutex);
129 if (!codec->resource[id].request_count) {
130 dev_err(&twl4030_codec_dev->dev,
131 "Resource has been disabled already (%u)\n", id);
132 mutex_unlock(&codec->mutex);
133 return -EPERM;
134 }
135 codec->resource[id].request_count--;
136
137 if (!codec->resource[id].request_count)
138 /* Resource can be disabled now */
139 val = twl4030_codec_set_resource(id, 0);
140 else
141 val = twl4030_codec_get_resource(id);
142
143 mutex_unlock(&codec->mutex);
144
145 return val;
146}
147EXPORT_SYMBOL_GPL(twl4030_codec_disable_resource);
148
149unsigned int twl4030_codec_get_mclk(void)
150{
151 struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
152
153 return codec->audio_mclk;
154}
155EXPORT_SYMBOL_GPL(twl4030_codec_get_mclk);
156
157static int __devinit twl4030_codec_probe(struct platform_device *pdev)
158{
159 struct twl4030_codec *codec;
160 struct twl4030_codec_data *pdata = pdev->dev.platform_data;
161 struct mfd_cell *cell = NULL;
162 int ret, childs = 0;
163 u8 val;
164
165 if (!pdata) {
166 dev_err(&pdev->dev, "Platform data is missing\n");
167 return -EINVAL;
168 }
169
170 /* Configure APLL_INFREQ and disable APLL if enabled */
171 val = 0;
172 switch (pdata->audio_mclk) {
173 case 19200000:
174 val |= TWL4030_APLL_INFREQ_19200KHZ;
175 break;
176 case 26000000:
177 val |= TWL4030_APLL_INFREQ_26000KHZ;
178 break;
179 case 38400000:
180 val |= TWL4030_APLL_INFREQ_38400KHZ;
181 break;
182 default:
183 dev_err(&pdev->dev, "Invalid audio_mclk\n");
184 return -EINVAL;
185 }
186 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
187 val, TWL4030_REG_APLL_CTL);
188
189 codec = kzalloc(sizeof(struct twl4030_codec), GFP_KERNEL);
190 if (!codec)
191 return -ENOMEM;
192
193 platform_set_drvdata(pdev, codec);
194
195 twl4030_codec_dev = pdev;
196 mutex_init(&codec->mutex);
197 codec->audio_mclk = pdata->audio_mclk;
198
199 /* Codec power */
200 codec->resource[TWL4030_CODEC_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
201 codec->resource[TWL4030_CODEC_RES_POWER].mask = TWL4030_CODECPDZ;
202
203 /* PLL */
204 codec->resource[TWL4030_CODEC_RES_APLL].reg = TWL4030_REG_APLL_CTL;
205 codec->resource[TWL4030_CODEC_RES_APLL].mask = TWL4030_APLL_EN;
206
207 if (pdata->audio) {
208 cell = &codec->cells[childs];
209 cell->name = "twl4030_codec_audio";
210 cell->platform_data = pdata->audio;
211 cell->data_size = sizeof(*pdata->audio);
212 childs++;
213 }
214 if (pdata->vibra) {
215 cell = &codec->cells[childs];
216 cell->name = "twl4030_codec_vibra";
217 cell->platform_data = pdata->vibra;
218 cell->data_size = sizeof(*pdata->vibra);
219 childs++;
220 }
221
222 if (childs)
223 ret = mfd_add_devices(&pdev->dev, pdev->id, codec->cells,
224 childs, NULL, 0);
225 else {
226 dev_err(&pdev->dev, "No platform data found for childs\n");
227 ret = -ENODEV;
228 }
229
230 if (!ret)
231 return 0;
232
233 platform_set_drvdata(pdev, NULL);
234 kfree(codec);
235 twl4030_codec_dev = NULL;
236 return ret;
237}
238
239static int __devexit twl4030_codec_remove(struct platform_device *pdev)
240{
241 struct twl4030_codec *codec = platform_get_drvdata(pdev);
242
243 mfd_remove_devices(&pdev->dev);
244 platform_set_drvdata(pdev, NULL);
245 kfree(codec);
246 twl4030_codec_dev = NULL;
247
248 return 0;
249}
250
251MODULE_ALIAS("platform:twl4030_codec");
252
253static struct platform_driver twl4030_codec_driver = {
254 .probe = twl4030_codec_probe,
255 .remove = __devexit_p(twl4030_codec_remove),
256 .driver = {
257 .owner = THIS_MODULE,
258 .name = "twl4030_codec",
259 },
260};
261
262static int __devinit twl4030_codec_init(void)
263{
264 return platform_driver_register(&twl4030_codec_driver);
265}
266module_init(twl4030_codec_init);
267
268static void __devexit twl4030_codec_exit(void)
269{
270 platform_driver_unregister(&twl4030_codec_driver);
271}
272module_exit(twl4030_codec_exit);
273
274MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>");
275MODULE_LICENSE("GPL");
276
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index a1c47ee95c0e..98b984e191d5 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -114,6 +114,12 @@
114#define twl_has_watchdog() false 114#define twl_has_watchdog() false
115#endif 115#endif
116 116
117#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE)
118#define twl_has_codec() true
119#else
120#define twl_has_codec() false
121#endif
122
117/* Triton Core internal information (BEGIN) */ 123/* Triton Core internal information (BEGIN) */
118 124
119/* Last - for index max*/ 125/* Last - for index max*/
@@ -601,6 +607,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
601 return PTR_ERR(child); 607 return PTR_ERR(child);
602 } 608 }
603 609
610 if (twl_has_codec() && pdata->codec) {
611 child = add_child(1, "twl4030_codec",
612 pdata->codec, sizeof(*pdata->codec),
613 false, 0, 0);
614 if (IS_ERR(child))
615 return PTR_ERR(child);
616 }
617
604 if (twl_has_regulator()) { 618 if (twl_has_regulator()) {
605 /* 619 /*
606 child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); 620 child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
@@ -763,7 +777,7 @@ static int twl4030_remove(struct i2c_client *client)
763} 777}
764 778
765/* NOTE: this driver only handles a single twl4030/tps659x0 chip */ 779/* NOTE: this driver only handles a single twl4030/tps659x0 chip */
766static int 780static int __init
767twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) 781twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
768{ 782{
769 int status; 783 int status;
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index fd3688a3e23f..832ed4c88cf7 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -89,48 +89,40 @@ static int xpc_disengage_max_timelimit = 120;
89 89
90static ctl_table xpc_sys_xpc_hb_dir[] = { 90static ctl_table xpc_sys_xpc_hb_dir[] = {
91 { 91 {
92 .ctl_name = CTL_UNNUMBERED,
93 .procname = "hb_interval", 92 .procname = "hb_interval",
94 .data = &xpc_hb_interval, 93 .data = &xpc_hb_interval,
95 .maxlen = sizeof(int), 94 .maxlen = sizeof(int),
96 .mode = 0644, 95 .mode = 0644,
97 .proc_handler = &proc_dointvec_minmax, 96 .proc_handler = proc_dointvec_minmax,
98 .strategy = &sysctl_intvec,
99 .extra1 = &xpc_hb_min_interval, 97 .extra1 = &xpc_hb_min_interval,
100 .extra2 = &xpc_hb_max_interval}, 98 .extra2 = &xpc_hb_max_interval},
101 { 99 {
102 .ctl_name = CTL_UNNUMBERED,
103 .procname = "hb_check_interval", 100 .procname = "hb_check_interval",
104 .data = &xpc_hb_check_interval, 101 .data = &xpc_hb_check_interval,
105 .maxlen = sizeof(int), 102 .maxlen = sizeof(int),
106 .mode = 0644, 103 .mode = 0644,
107 .proc_handler = &proc_dointvec_minmax, 104 .proc_handler = proc_dointvec_minmax,
108 .strategy = &sysctl_intvec,
109 .extra1 = &xpc_hb_check_min_interval, 105 .extra1 = &xpc_hb_check_min_interval,
110 .extra2 = &xpc_hb_check_max_interval}, 106 .extra2 = &xpc_hb_check_max_interval},
111 {} 107 {}
112}; 108};
113static ctl_table xpc_sys_xpc_dir[] = { 109static ctl_table xpc_sys_xpc_dir[] = {
114 { 110 {
115 .ctl_name = CTL_UNNUMBERED,
116 .procname = "hb", 111 .procname = "hb",
117 .mode = 0555, 112 .mode = 0555,
118 .child = xpc_sys_xpc_hb_dir}, 113 .child = xpc_sys_xpc_hb_dir},
119 { 114 {
120 .ctl_name = CTL_UNNUMBERED,
121 .procname = "disengage_timelimit", 115 .procname = "disengage_timelimit",
122 .data = &xpc_disengage_timelimit, 116 .data = &xpc_disengage_timelimit,
123 .maxlen = sizeof(int), 117 .maxlen = sizeof(int),
124 .mode = 0644, 118 .mode = 0644,
125 .proc_handler = &proc_dointvec_minmax, 119 .proc_handler = proc_dointvec_minmax,
126 .strategy = &sysctl_intvec,
127 .extra1 = &xpc_disengage_min_timelimit, 120 .extra1 = &xpc_disengage_min_timelimit,
128 .extra2 = &xpc_disengage_max_timelimit}, 121 .extra2 = &xpc_disengage_max_timelimit},
129 {} 122 {}
130}; 123};
131static ctl_table xpc_sys_dir[] = { 124static ctl_table xpc_sys_dir[] = {
132 { 125 {
133 .ctl_name = CTL_UNNUMBERED,
134 .procname = "xpc", 126 .procname = "xpc",
135 .mode = 0555, 127 .mode = 0555,
136 .child = xpc_sys_xpc_dir}, 128 .child = xpc_sys_xpc_dir},
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index c76677afda1b..b5bbe59f9c57 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -106,7 +106,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
106 int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); 106 int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
107 107
108#if defined CONFIG_X86_64 108#if defined CONFIG_X86_64
109 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset); 109 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
110 UV_AFFINITY_CPU);
110 if (mq->irq < 0) { 111 if (mq->irq < 0) {
111 dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", 112 dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
112 -mq->irq); 113 -mq->irq);
@@ -136,7 +137,7 @@ static void
136xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq) 137xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
137{ 138{
138#if defined CONFIG_X86_64 139#if defined CONFIG_X86_64
139 uv_teardown_irq(mq->irq, mq->mmr_blade, mq->mmr_offset); 140 uv_teardown_irq(mq->irq);
140 141
141#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV 142#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
142 int mmr_pnode; 143 int mmr_pnode;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ddf224d456b2..e6627b2320f1 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -9,7 +9,8 @@
9 * 9 *
10 * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 10 * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
11 * 11 *
12 * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell. 12 * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
13 * Grant Likely.
13 * 14 *
14 * This program is free software; you can redistribute it and/or 15 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License 16 * modify it under the terms of the GNU General Public License
@@ -82,6 +83,29 @@ struct property *of_find_property(const struct device_node *np,
82} 83}
83EXPORT_SYMBOL(of_find_property); 84EXPORT_SYMBOL(of_find_property);
84 85
86/**
87 * of_find_all_nodes - Get next node in global list
88 * @prev: Previous node or NULL to start iteration
89 * of_node_put() will be called on it
90 *
91 * Returns a node pointer with refcount incremented, use
92 * of_node_put() on it when done.
93 */
94struct device_node *of_find_all_nodes(struct device_node *prev)
95{
96 struct device_node *np;
97
98 read_lock(&devtree_lock);
99 np = prev ? prev->allnext : allnodes;
100 for (; np != NULL; np = np->allnext)
101 if (of_node_get(np))
102 break;
103 of_node_put(prev);
104 read_unlock(&devtree_lock);
105 return np;
106}
107EXPORT_SYMBOL(of_find_all_nodes);
108
85/* 109/*
86 * Find a property with a given name for a given node 110 * Find a property with a given name for a given node
87 * and return the value. 111 * and return the value.
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index 8eefe56f1cbe..3f56bc086cb5 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -233,10 +233,10 @@ static int do_hardware_modes (ctl_table *table, int write,
233 return copy_to_user(result, buffer, len) ? -EFAULT : 0; 233 return copy_to_user(result, buffer, len) ? -EFAULT : 0;
234} 234}
235 235
236#define PARPORT_PORT_DIR(CHILD) { .ctl_name = 0, .procname = NULL, .mode = 0555, .child = CHILD } 236#define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD }
237#define PARPORT_PARPORT_DIR(CHILD) { .ctl_name = DEV_PARPORT, .procname = "parport", \ 237#define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \
238 .mode = 0555, .child = CHILD } 238 .mode = 0555, .child = CHILD }
239#define PARPORT_DEV_DIR(CHILD) { .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = CHILD } 239#define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD }
240#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \ 240#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \
241 .mode = 0555, .child = NULL } 241 .mode = 0555, .child = NULL }
242 242
@@ -270,7 +270,7 @@ static const struct parport_sysctl_table parport_sysctl_template = {
270 .data = NULL, 270 .data = NULL,
271 .maxlen = sizeof(int), 271 .maxlen = sizeof(int),
272 .mode = 0644, 272 .mode = 0644,
273 .proc_handler = &proc_dointvec_minmax, 273 .proc_handler = proc_dointvec_minmax,
274 .extra1 = (void*) &parport_min_spintime_value, 274 .extra1 = (void*) &parport_min_spintime_value,
275 .extra2 = (void*) &parport_max_spintime_value 275 .extra2 = (void*) &parport_max_spintime_value
276 }, 276 },
@@ -279,28 +279,28 @@ static const struct parport_sysctl_table parport_sysctl_template = {
279 .data = NULL, 279 .data = NULL,
280 .maxlen = 0, 280 .maxlen = 0,
281 .mode = 0444, 281 .mode = 0444,
282 .proc_handler = &do_hardware_base_addr 282 .proc_handler = do_hardware_base_addr
283 }, 283 },
284 { 284 {
285 .procname = "irq", 285 .procname = "irq",
286 .data = NULL, 286 .data = NULL,
287 .maxlen = 0, 287 .maxlen = 0,
288 .mode = 0444, 288 .mode = 0444,
289 .proc_handler = &do_hardware_irq 289 .proc_handler = do_hardware_irq
290 }, 290 },
291 { 291 {
292 .procname = "dma", 292 .procname = "dma",
293 .data = NULL, 293 .data = NULL,
294 .maxlen = 0, 294 .maxlen = 0,
295 .mode = 0444, 295 .mode = 0444,
296 .proc_handler = &do_hardware_dma 296 .proc_handler = do_hardware_dma
297 }, 297 },
298 { 298 {
299 .procname = "modes", 299 .procname = "modes",
300 .data = NULL, 300 .data = NULL,
301 .maxlen = 0, 301 .maxlen = 0,
302 .mode = 0444, 302 .mode = 0444,
303 .proc_handler = &do_hardware_modes 303 .proc_handler = do_hardware_modes
304 }, 304 },
305 PARPORT_DEVICES_ROOT_DIR, 305 PARPORT_DEVICES_ROOT_DIR,
306#ifdef CONFIG_PARPORT_1284 306#ifdef CONFIG_PARPORT_1284
@@ -309,35 +309,35 @@ static const struct parport_sysctl_table parport_sysctl_template = {
309 .data = NULL, 309 .data = NULL,
310 .maxlen = 0, 310 .maxlen = 0,
311 .mode = 0444, 311 .mode = 0444,
312 .proc_handler = &do_autoprobe 312 .proc_handler = do_autoprobe
313 }, 313 },
314 { 314 {
315 .procname = "autoprobe0", 315 .procname = "autoprobe0",
316 .data = NULL, 316 .data = NULL,
317 .maxlen = 0, 317 .maxlen = 0,
318 .mode = 0444, 318 .mode = 0444,
319 .proc_handler = &do_autoprobe 319 .proc_handler = do_autoprobe
320 }, 320 },
321 { 321 {
322 .procname = "autoprobe1", 322 .procname = "autoprobe1",
323 .data = NULL, 323 .data = NULL,
324 .maxlen = 0, 324 .maxlen = 0,
325 .mode = 0444, 325 .mode = 0444,
326 .proc_handler = &do_autoprobe 326 .proc_handler = do_autoprobe
327 }, 327 },
328 { 328 {
329 .procname = "autoprobe2", 329 .procname = "autoprobe2",
330 .data = NULL, 330 .data = NULL,
331 .maxlen = 0, 331 .maxlen = 0,
332 .mode = 0444, 332 .mode = 0444,
333 .proc_handler = &do_autoprobe 333 .proc_handler = do_autoprobe
334 }, 334 },
335 { 335 {
336 .procname = "autoprobe3", 336 .procname = "autoprobe3",
337 .data = NULL, 337 .data = NULL,
338 .maxlen = 0, 338 .maxlen = 0,
339 .mode = 0444, 339 .mode = 0444,
340 .proc_handler = &do_autoprobe 340 .proc_handler = do_autoprobe
341 }, 341 },
342#endif /* IEEE 1284 support */ 342#endif /* IEEE 1284 support */
343 {} 343 {}
@@ -348,7 +348,7 @@ static const struct parport_sysctl_table parport_sysctl_template = {
348 .data = NULL, 348 .data = NULL,
349 .maxlen = 0, 349 .maxlen = 0,
350 .mode = 0444, 350 .mode = 0444,
351 .proc_handler = &do_active_device 351 .proc_handler = do_active_device
352 }, 352 },
353 {} 353 {}
354 }, 354 },
@@ -386,14 +386,13 @@ parport_device_sysctl_template = {
386 .data = NULL, 386 .data = NULL,
387 .maxlen = sizeof(unsigned long), 387 .maxlen = sizeof(unsigned long),
388 .mode = 0644, 388 .mode = 0644,
389 .proc_handler = &proc_doulongvec_ms_jiffies_minmax, 389 .proc_handler = proc_doulongvec_ms_jiffies_minmax,
390 .extra1 = (void*) &parport_min_timeslice_value, 390 .extra1 = (void*) &parport_min_timeslice_value,
391 .extra2 = (void*) &parport_max_timeslice_value 391 .extra2 = (void*) &parport_max_timeslice_value
392 }, 392 },
393 }, 393 },
394 { 394 {
395 { 395 {
396 .ctl_name = 0,
397 .procname = NULL, 396 .procname = NULL,
398 .data = NULL, 397 .data = NULL,
399 .maxlen = 0, 398 .maxlen = 0,
@@ -438,7 +437,7 @@ parport_default_sysctl_table = {
438 .data = &parport_default_timeslice, 437 .data = &parport_default_timeslice,
439 .maxlen = sizeof(parport_default_timeslice), 438 .maxlen = sizeof(parport_default_timeslice),
440 .mode = 0644, 439 .mode = 0644,
441 .proc_handler = &proc_doulongvec_ms_jiffies_minmax, 440 .proc_handler = proc_doulongvec_ms_jiffies_minmax,
442 .extra1 = (void*) &parport_min_timeslice_value, 441 .extra1 = (void*) &parport_min_timeslice_value,
443 .extra2 = (void*) &parport_max_timeslice_value 442 .extra2 = (void*) &parport_max_timeslice_value
444 }, 443 },
@@ -447,7 +446,7 @@ parport_default_sysctl_table = {
447 .data = &parport_default_spintime, 446 .data = &parport_default_spintime,
448 .maxlen = sizeof(parport_default_spintime), 447 .maxlen = sizeof(parport_default_spintime),
449 .mode = 0644, 448 .mode = 0644,
450 .proc_handler = &proc_dointvec_minmax, 449 .proc_handler = proc_dointvec_minmax,
451 .extra1 = (void*) &parport_min_spintime_value, 450 .extra1 = (void*) &parport_min_spintime_value,
452 .extra2 = (void*) &parport_max_spintime_value 451 .extra2 = (void*) &parport_max_spintime_value
453 }, 452 },
@@ -455,7 +454,6 @@ parport_default_sysctl_table = {
455 }, 454 },
456 { 455 {
457 { 456 {
458 .ctl_name = DEV_PARPORT_DEFAULT,
459 .procname = "default", 457 .procname = "default",
460 .mode = 0555, 458 .mode = 0555,
461 .child = parport_default_sysctl_table.vars 459 .child = parport_default_sysctl_table.vars
@@ -495,7 +493,6 @@ int parport_proc_register(struct parport *port)
495 t->vars[6 + i].extra2 = &port->probe_info[i]; 493 t->vars[6 + i].extra2 = &port->probe_info[i];
496 494
497 t->port_dir[0].procname = port->name; 495 t->port_dir[0].procname = port->name;
498 t->port_dir[0].ctl_name = 0;
499 496
500 t->port_dir[0].child = t->vars; 497 t->port_dir[0].child = t->vars;
501 t->parport_dir[0].child = t->port_dir; 498 t->parport_dir[0].child = t->port_dir;
@@ -534,11 +531,9 @@ int parport_device_proc_register(struct pardevice *device)
534 t->dev_dir[0].child = t->parport_dir; 531 t->dev_dir[0].child = t->parport_dir;
535 t->parport_dir[0].child = t->port_dir; 532 t->parport_dir[0].child = t->port_dir;
536 t->port_dir[0].procname = port->name; 533 t->port_dir[0].procname = port->name;
537 t->port_dir[0].ctl_name = 0;
538 t->port_dir[0].child = t->devices_root_dir; 534 t->port_dir[0].child = t->devices_root_dir;
539 t->devices_root_dir[0].child = t->device_dir; 535 t->devices_root_dir[0].child = t->device_dir;
540 536
541 t->device_dir[0].ctl_name = 0;
542 t->device_dir[0].procname = device->name; 537 t->device_dir[0].procname = device->name;
543 t->device_dir[0].child = t->vars; 538 t->device_dir[0].child = t->vars;
544 t->vars[0].data = &device->timeslice; 539 t->vars[0].data = &device->timeslice;
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index b44462a6c6d3..740fe405c395 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -101,18 +101,17 @@ static struct ctl_table callhome_table[] = {
101 .mode = 0644, 101 .mode = 0644,
102 .proc_handler = proc_handler_callhome, 102 .proc_handler = proc_handler_callhome,
103 }, 103 },
104 { .ctl_name = 0 } 104 {}
105}; 105};
106 106
107static struct ctl_table kern_dir_table[] = { 107static struct ctl_table kern_dir_table[] = {
108 { 108 {
109 .ctl_name = CTL_KERN,
110 .procname = "kernel", 109 .procname = "kernel",
111 .maxlen = 0, 110 .maxlen = 0,
112 .mode = 0555, 111 .mode = 0555,
113 .child = callhome_table, 112 .child = callhome_table,
114 }, 113 },
115 { .ctl_name = 0 } 114 {}
116}; 115};
117 116
118/* 117/*
diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c
index 63a30f566f3a..2b6b93f7d8ef 100644
--- a/drivers/scsi/scsi_sysctl.c
+++ b/drivers/scsi/scsi_sysctl.c
@@ -13,26 +13,23 @@
13 13
14 14
15static ctl_table scsi_table[] = { 15static ctl_table scsi_table[] = {
16 { .ctl_name = DEV_SCSI_LOGGING_LEVEL, 16 { .procname = "logging_level",
17 .procname = "logging_level",
18 .data = &scsi_logging_level, 17 .data = &scsi_logging_level,
19 .maxlen = sizeof(scsi_logging_level), 18 .maxlen = sizeof(scsi_logging_level),
20 .mode = 0644, 19 .mode = 0644,
21 .proc_handler = &proc_dointvec }, 20 .proc_handler = proc_dointvec },
22 { } 21 { }
23}; 22};
24 23
25static ctl_table scsi_dir_table[] = { 24static ctl_table scsi_dir_table[] = {
26 { .ctl_name = DEV_SCSI, 25 { .procname = "scsi",
27 .procname = "scsi",
28 .mode = 0555, 26 .mode = 0555,
29 .child = scsi_table }, 27 .child = scsi_table },
30 { } 28 { }
31}; 29};
32 30
33static ctl_table scsi_root_table[] = { 31static ctl_table scsi_root_table[] = {
34 { .ctl_name = CTL_DEV, 32 { .procname = "dev",
35 .procname = "dev",
36 .mode = 0555, 33 .mode = 0555,
37 .child = scsi_dir_table }, 34 .child = scsi_dir_table },
38 { } 35 { }
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e52257257279..50943ff78f4b 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1477,4 +1477,17 @@ config SERIAL_BCM63XX_CONSOLE
1477 If you have enabled the serial port on the bcm63xx CPU 1477 If you have enabled the serial port on the bcm63xx CPU
1478 you can make it the console by answering Y to this option. 1478 you can make it the console by answering Y to this option.
1479 1479
1480config SERIAL_GRLIB_GAISLER_APBUART
1481 tristate "GRLIB APBUART serial support"
1482 depends on OF
1483 ---help---
1484 Add support for the GRLIB APBUART serial port.
1485
1486config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
1487 bool "Console on GRLIB APBUART serial port"
1488 depends on SERIAL_GRLIB_GAISLER_APBUART=y
1489 select SERIAL_CORE_CONSOLE
1490 help
1491 Support for running a console on the GRLIB APBUART
1492
1480endmenu 1493endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d21d5dd5d048..5548fe7df61d 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -81,3 +81,4 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
81obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o 81obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
82obj-$(CONFIG_SERIAL_QE) += ucc_uart.o 82obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
83obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o 83obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
84obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c
new file mode 100644
index 000000000000..fe91319b5f65
--- /dev/null
+++ b/drivers/serial/apbuart.c
@@ -0,0 +1,710 @@
1/*
2 * Driver for GRLIB serial ports (APBUART)
3 *
4 * Based on linux/drivers/serial/amba.c
5 *
6 * Copyright (C) 2000 Deep Blue Solutions Ltd.
7 * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de>
8 * Copyright (C) 2006 Daniel Hellstrom <daniel@gaisler.com>, Aeroflex Gaisler AB
9 * Copyright (C) 2008 Gilead Kutnick <kutnickg@zin-tech.com>
10 * Copyright (C) 2009 Kristoffer Glembo <kristoffer@gaisler.com>, Aeroflex Gaisler AB
11 */
12
13#if defined(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
14#define SUPPORT_SYSRQ
15#endif
16
17#include <linux/module.h>
18#include <linux/tty.h>
19#include <linux/ioport.h>
20#include <linux/init.h>
21#include <linux/serial.h>
22#include <linux/console.h>
23#include <linux/sysrq.h>
24#include <linux/kthread.h>
25#include <linux/device.h>
26#include <linux/of.h>
27#include <linux/of_device.h>
28#include <linux/of_platform.h>
29#include <linux/platform_device.h>
30#include <linux/io.h>
31#include <linux/serial_core.h>
32#include <asm/irq.h>
33
34#include "apbuart.h"
35
36#define SERIAL_APBUART_MAJOR TTY_MAJOR
37#define SERIAL_APBUART_MINOR 64
38#define UART_DUMMY_RSR_RX 0x8000 /* for ignore all read */
39
40static void apbuart_tx_chars(struct uart_port *port);
41
42static void apbuart_stop_tx(struct uart_port *port)
43{
44 unsigned int cr;
45
46 cr = UART_GET_CTRL(port);
47 cr &= ~UART_CTRL_TI;
48 UART_PUT_CTRL(port, cr);
49}
50
51static void apbuart_start_tx(struct uart_port *port)
52{
53 unsigned int cr;
54
55 cr = UART_GET_CTRL(port);
56 cr |= UART_CTRL_TI;
57 UART_PUT_CTRL(port, cr);
58
59 if (UART_GET_STATUS(port) & UART_STATUS_THE)
60 apbuart_tx_chars(port);
61}
62
63static void apbuart_stop_rx(struct uart_port *port)
64{
65 unsigned int cr;
66
67 cr = UART_GET_CTRL(port);
68 cr &= ~(UART_CTRL_RI);
69 UART_PUT_CTRL(port, cr);
70}
71
72static void apbuart_enable_ms(struct uart_port *port)
73{
74 /* No modem status change interrupts for APBUART */
75}
76
77static void apbuart_rx_chars(struct uart_port *port)
78{
79 struct tty_struct *tty = port->state->port.tty;
80 unsigned int status, ch, rsr, flag;
81 unsigned int max_chars = port->fifosize;
82
83 status = UART_GET_STATUS(port);
84
85 while (UART_RX_DATA(status) && (max_chars--)) {
86
87 ch = UART_GET_CHAR(port);
88 flag = TTY_NORMAL;
89
90 port->icount.rx++;
91
92 rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
93 UART_PUT_STATUS(port, 0);
94 if (rsr & UART_STATUS_ERR) {
95
96 if (rsr & UART_STATUS_BR) {
97 rsr &= ~(UART_STATUS_FE | UART_STATUS_PE);
98 port->icount.brk++;
99 if (uart_handle_break(port))
100 goto ignore_char;
101 } else if (rsr & UART_STATUS_PE) {
102 port->icount.parity++;
103 } else if (rsr & UART_STATUS_FE) {
104 port->icount.frame++;
105 }
106 if (rsr & UART_STATUS_OE)
107 port->icount.overrun++;
108
109 rsr &= port->read_status_mask;
110
111 if (rsr & UART_STATUS_PE)
112 flag = TTY_PARITY;
113 else if (rsr & UART_STATUS_FE)
114 flag = TTY_FRAME;
115 }
116
117 if (uart_handle_sysrq_char(port, ch))
118 goto ignore_char;
119
120 uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag);
121
122
123 ignore_char:
124 status = UART_GET_STATUS(port);
125 }
126
127 tty_flip_buffer_push(tty);
128}
129
130static void apbuart_tx_chars(struct uart_port *port)
131{
132 struct circ_buf *xmit = &port->state->xmit;
133 int count;
134
135 if (port->x_char) {
136 UART_PUT_CHAR(port, port->x_char);
137 port->icount.tx++;
138 port->x_char = 0;
139 return;
140 }
141
142 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
143 apbuart_stop_tx(port);
144 return;
145 }
146
147 /* amba: fill FIFO */
148 count = port->fifosize >> 1;
149 do {
150 UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
151 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
152 port->icount.tx++;
153 if (uart_circ_empty(xmit))
154 break;
155 } while (--count > 0);
156
157 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
158 uart_write_wakeup(port);
159
160 if (uart_circ_empty(xmit))
161 apbuart_stop_tx(port);
162}
163
164static irqreturn_t apbuart_int(int irq, void *dev_id)
165{
166 struct uart_port *port = dev_id;
167 unsigned int status;
168
169 spin_lock(&port->lock);
170
171 status = UART_GET_STATUS(port);
172 if (status & UART_STATUS_DR)
173 apbuart_rx_chars(port);
174 if (status & UART_STATUS_THE)
175 apbuart_tx_chars(port);
176
177 spin_unlock(&port->lock);
178
179 return IRQ_HANDLED;
180}
181
182static unsigned int apbuart_tx_empty(struct uart_port *port)
183{
184 unsigned int status = UART_GET_STATUS(port);
185 return status & UART_STATUS_THE ? TIOCSER_TEMT : 0;
186}
187
188static unsigned int apbuart_get_mctrl(struct uart_port *port)
189{
190 /* The GRLIB APBUART handles flow control in hardware */
191 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
192}
193
194static void apbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
195{
196 /* The GRLIB APBUART handles flow control in hardware */
197}
198
199static void apbuart_break_ctl(struct uart_port *port, int break_state)
200{
201 /* We don't support sending break */
202}
203
204static int apbuart_startup(struct uart_port *port)
205{
206 int retval;
207 unsigned int cr;
208
209 /* Allocate the IRQ */
210 retval = request_irq(port->irq, apbuart_int, 0, "apbuart", port);
211 if (retval)
212 return retval;
213
214 /* Finally, enable interrupts */
215 cr = UART_GET_CTRL(port);
216 UART_PUT_CTRL(port,
217 cr | UART_CTRL_RE | UART_CTRL_TE |
218 UART_CTRL_RI | UART_CTRL_TI);
219
220 return 0;
221}
222
223static void apbuart_shutdown(struct uart_port *port)
224{
225 unsigned int cr;
226
227 /* disable all interrupts, disable the port */
228 cr = UART_GET_CTRL(port);
229 UART_PUT_CTRL(port,
230 cr & ~(UART_CTRL_RE | UART_CTRL_TE |
231 UART_CTRL_RI | UART_CTRL_TI));
232
233 /* Free the interrupt */
234 free_irq(port->irq, port);
235}
236
237static void apbuart_set_termios(struct uart_port *port,
238 struct ktermios *termios, struct ktermios *old)
239{
240 unsigned int cr;
241 unsigned long flags;
242 unsigned int baud, quot;
243
244 /* Ask the core to calculate the divisor for us. */
245 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
246 if (baud == 0)
247 panic("invalid baudrate %i\n", port->uartclk / 16);
248
249 /* uart_get_divisor calc a *16 uart freq, apbuart is *8 */
250 quot = (uart_get_divisor(port, baud)) * 2;
251 cr = UART_GET_CTRL(port);
252 cr &= ~(UART_CTRL_PE | UART_CTRL_PS);
253
254 if (termios->c_cflag & PARENB) {
255 cr |= UART_CTRL_PE;
256 if ((termios->c_cflag & PARODD))
257 cr |= UART_CTRL_PS;
258 }
259
260 /* Enable flow control. */
261 if (termios->c_cflag & CRTSCTS)
262 cr |= UART_CTRL_FL;
263
264 spin_lock_irqsave(&port->lock, flags);
265
266 /* Update the per-port timeout. */
267 uart_update_timeout(port, termios->c_cflag, baud);
268
269 port->read_status_mask = UART_STATUS_OE;
270 if (termios->c_iflag & INPCK)
271 port->read_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
272
273 /* Characters to ignore */
274 port->ignore_status_mask = 0;
275 if (termios->c_iflag & IGNPAR)
276 port->ignore_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
277
278 /* Ignore all characters if CREAD is not set. */
279 if ((termios->c_cflag & CREAD) == 0)
280 port->ignore_status_mask |= UART_DUMMY_RSR_RX;
281
282 /* Set baud rate */
283 quot -= 1;
284 UART_PUT_SCAL(port, quot);
285 UART_PUT_CTRL(port, cr);
286
287 spin_unlock_irqrestore(&port->lock, flags);
288}
289
290static const char *apbuart_type(struct uart_port *port)
291{
292 return port->type == PORT_APBUART ? "GRLIB/APBUART" : NULL;
293}
294
295static void apbuart_release_port(struct uart_port *port)
296{
297 release_mem_region(port->mapbase, 0x100);
298}
299
300static int apbuart_request_port(struct uart_port *port)
301{
302 return request_mem_region(port->mapbase, 0x100, "grlib-apbuart")
303 != NULL ? 0 : -EBUSY;
304 return 0;
305}
306
307/* Configure/autoconfigure the port */
308static void apbuart_config_port(struct uart_port *port, int flags)
309{
310 if (flags & UART_CONFIG_TYPE) {
311 port->type = PORT_APBUART;
312 apbuart_request_port(port);
313 }
314}
315
316/* Verify the new serial_struct (for TIOCSSERIAL) */
317static int apbuart_verify_port(struct uart_port *port,
318 struct serial_struct *ser)
319{
320 int ret = 0;
321 if (ser->type != PORT_UNKNOWN && ser->type != PORT_APBUART)
322 ret = -EINVAL;
323 if (ser->irq < 0 || ser->irq >= NR_IRQS)
324 ret = -EINVAL;
325 if (ser->baud_base < 9600)
326 ret = -EINVAL;
327 return ret;
328}
329
330static struct uart_ops grlib_apbuart_ops = {
331 .tx_empty = apbuart_tx_empty,
332 .set_mctrl = apbuart_set_mctrl,
333 .get_mctrl = apbuart_get_mctrl,
334 .stop_tx = apbuart_stop_tx,
335 .start_tx = apbuart_start_tx,
336 .stop_rx = apbuart_stop_rx,
337 .enable_ms = apbuart_enable_ms,
338 .break_ctl = apbuart_break_ctl,
339 .startup = apbuart_startup,
340 .shutdown = apbuart_shutdown,
341 .set_termios = apbuart_set_termios,
342 .type = apbuart_type,
343 .release_port = apbuart_release_port,
344 .request_port = apbuart_request_port,
345 .config_port = apbuart_config_port,
346 .verify_port = apbuart_verify_port,
347};
348
349static struct uart_port grlib_apbuart_ports[UART_NR];
350static struct device_node *grlib_apbuart_nodes[UART_NR];
351
352static int apbuart_scan_fifo_size(struct uart_port *port, int portnumber)
353{
354 int ctrl, loop = 0;
355 int status;
356 int fifosize;
357 unsigned long flags;
358
359 ctrl = UART_GET_CTRL(port);
360
361 /*
362 * Enable the transceiver and wait for it to be ready to send data.
363 * Clear interrupts so that this process will not be externally
364 * interrupted in the middle (which can cause the transceiver to
365 * drain prematurely).
366 */
367
368 local_irq_save(flags);
369
370 UART_PUT_CTRL(port, ctrl | UART_CTRL_TE);
371
372 while (!UART_TX_READY(UART_GET_STATUS(port)))
373 loop++;
374
375 /*
376 * Disable the transceiver so data isn't actually sent during the
377 * actual test.
378 */
379
380 UART_PUT_CTRL(port, ctrl & ~(UART_CTRL_TE));
381
382 fifosize = 1;
383 UART_PUT_CHAR(port, 0);
384
385 /*
386 * So long as transmitting a character increments the tranceivier FIFO
387 * length the FIFO must be at least that big. These bytes will
388 * automatically drain off of the FIFO.
389 */
390
391 status = UART_GET_STATUS(port);
392 while (((status >> 20) & 0x3F) == fifosize) {
393 fifosize++;
394 UART_PUT_CHAR(port, 0);
395 status = UART_GET_STATUS(port);
396 }
397
398 fifosize--;
399
400 UART_PUT_CTRL(port, ctrl);
401 local_irq_restore(flags);
402
403 if (fifosize == 0)
404 fifosize = 1;
405
406 return fifosize;
407}
408
409static void apbuart_flush_fifo(struct uart_port *port)
410{
411 int i;
412
413 for (i = 0; i < port->fifosize; i++)
414 UART_GET_CHAR(port);
415}
416
417
418/* ======================================================================== */
419/* Console driver, if enabled */
420/* ======================================================================== */
421
422#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
423
424static void apbuart_console_putchar(struct uart_port *port, int ch)
425{
426 unsigned int status;
427 do {
428 status = UART_GET_STATUS(port);
429 } while (!UART_TX_READY(status));
430 UART_PUT_CHAR(port, ch);
431}
432
433static void
434apbuart_console_write(struct console *co, const char *s, unsigned int count)
435{
436 struct uart_port *port = &grlib_apbuart_ports[co->index];
437 unsigned int status, old_cr, new_cr;
438
439 /* First save the CR then disable the interrupts */
440 old_cr = UART_GET_CTRL(port);
441 new_cr = old_cr & ~(UART_CTRL_RI | UART_CTRL_TI);
442 UART_PUT_CTRL(port, new_cr);
443
444 uart_console_write(port, s, count, apbuart_console_putchar);
445
446 /*
447 * Finally, wait for transmitter to become empty
448 * and restore the TCR
449 */
450 do {
451 status = UART_GET_STATUS(port);
452 } while (!UART_TX_READY(status));
453 UART_PUT_CTRL(port, old_cr);
454}
455
456static void __init
457apbuart_console_get_options(struct uart_port *port, int *baud,
458 int *parity, int *bits)
459{
460 if (UART_GET_CTRL(port) & (UART_CTRL_RE | UART_CTRL_TE)) {
461
462 unsigned int quot, status;
463 status = UART_GET_STATUS(port);
464
465 *parity = 'n';
466 if (status & UART_CTRL_PE) {
467 if ((status & UART_CTRL_PS) == 0)
468 *parity = 'e';
469 else
470 *parity = 'o';
471 }
472
473 *bits = 8;
474 quot = UART_GET_SCAL(port) / 8;
475 *baud = port->uartclk / (16 * (quot + 1));
476 }
477}
478
479static int __init apbuart_console_setup(struct console *co, char *options)
480{
481 struct uart_port *port;
482 int baud = 38400;
483 int bits = 8;
484 int parity = 'n';
485 int flow = 'n';
486
487 pr_debug("apbuart_console_setup co=%p, co->index=%i, options=%s\n",
488 co, co->index, options);
489
490 /*
491 * Check whether an invalid uart number has been specified, and
492 * if so, search for the first available port that does have
493 * console support.
494 */
495 if (co->index >= grlib_apbuart_port_nr)
496 co->index = 0;
497
498 port = &grlib_apbuart_ports[co->index];
499
500 spin_lock_init(&port->lock);
501
502 if (options)
503 uart_parse_options(options, &baud, &parity, &bits, &flow);
504 else
505 apbuart_console_get_options(port, &baud, &parity, &bits);
506
507 return uart_set_options(port, co, baud, parity, bits, flow);
508}
509
510static struct uart_driver grlib_apbuart_driver;
511
512static struct console grlib_apbuart_console = {
513 .name = "ttyS",
514 .write = apbuart_console_write,
515 .device = uart_console_device,
516 .setup = apbuart_console_setup,
517 .flags = CON_PRINTBUFFER,
518 .index = -1,
519 .data = &grlib_apbuart_driver,
520};
521
522
523static void grlib_apbuart_configure(void);
524
525static int __init apbuart_console_init(void)
526{
527 grlib_apbuart_configure();
528 register_console(&grlib_apbuart_console);
529 return 0;
530}
531
532console_initcall(apbuart_console_init);
533
534#define APBUART_CONSOLE (&grlib_apbuart_console)
535#else
536#define APBUART_CONSOLE NULL
537#endif
538
539static struct uart_driver grlib_apbuart_driver = {
540 .owner = THIS_MODULE,
541 .driver_name = "serial",
542 .dev_name = "ttyS",
543 .major = SERIAL_APBUART_MAJOR,
544 .minor = SERIAL_APBUART_MINOR,
545 .nr = UART_NR,
546 .cons = APBUART_CONSOLE,
547};
548
549
550/* ======================================================================== */
551/* OF Platform Driver */
552/* ======================================================================== */
553
554static int __devinit apbuart_probe(struct of_device *op,
555 const struct of_device_id *match)
556{
557 int i = -1;
558 struct uart_port *port = NULL;
559
560 i = 0;
561 for (i = 0; i < grlib_apbuart_port_nr; i++) {
562 if (op->node == grlib_apbuart_nodes[i])
563 break;
564 }
565
566 port = &grlib_apbuart_ports[i];
567 port->dev = &op->dev;
568
569 uart_add_one_port(&grlib_apbuart_driver, (struct uart_port *) port);
570
571 apbuart_flush_fifo((struct uart_port *) port);
572
573 printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
574 (unsigned long long) port->mapbase, port->irq);
575 return 0;
576
577}
578
579static struct of_device_id __initdata apbuart_match[] = {
580 {
581 .name = "GAISLER_APBUART",
582 },
583 {},
584};
585
586static struct of_platform_driver grlib_apbuart_of_driver = {
587 .match_table = apbuart_match,
588 .probe = apbuart_probe,
589 .driver = {
590 .owner = THIS_MODULE,
591 .name = "grlib-apbuart",
592 },
593};
594
595
596static void grlib_apbuart_configure(void)
597{
598 static int enum_done;
599 struct device_node *np, *rp;
600 struct uart_port *port = NULL;
601 const u32 *prop;
602 int freq_khz;
603 int v = 0, d = 0;
604 unsigned int addr;
605 int irq, line;
606 struct amba_prom_registers *regs;
607
608 if (enum_done)
609 return;
610
611 /* Get bus frequency */
612 rp = of_find_node_by_path("/");
613 rp = of_get_next_child(rp, NULL);
614 prop = of_get_property(rp, "clock-frequency", NULL);
615 freq_khz = *prop;
616
617 line = 0;
618 for_each_matching_node(np, apbuart_match) {
619
620 int *vendor = (int *) of_get_property(np, "vendor", NULL);
621 int *device = (int *) of_get_property(np, "device", NULL);
622 int *irqs = (int *) of_get_property(np, "interrupts", NULL);
623 regs = (struct amba_prom_registers *)
624 of_get_property(np, "reg", NULL);
625
626 if (vendor)
627 v = *vendor;
628 if (device)
629 d = *device;
630
631 if (!irqs || !regs)
632 return;
633
634 grlib_apbuart_nodes[line] = np;
635
636 addr = regs->phys_addr;
637 irq = *irqs;
638
639 port = &grlib_apbuart_ports[line];
640
641 port->mapbase = addr;
642 port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map));
643 port->irq = irq;
644 port->iotype = UPIO_MEM;
645 port->ops = &grlib_apbuart_ops;
646 port->flags = UPF_BOOT_AUTOCONF;
647 port->line = line;
648 port->uartclk = freq_khz * 1000;
649 port->fifosize = apbuart_scan_fifo_size((struct uart_port *) port, line);
650 line++;
651
652 /* We support maximum UART_NR uarts ... */
653 if (line == UART_NR)
654 break;
655
656 }
657
658 enum_done = 1;
659
660 grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
661}
662
663static int __init grlib_apbuart_init(void)
664{
665 int ret;
666
667 /* Find all APBUARTS in device the tree and initialize their ports */
668 grlib_apbuart_configure();
669
670 printk(KERN_INFO "Serial: GRLIB APBUART driver\n");
671
672 ret = uart_register_driver(&grlib_apbuart_driver);
673
674 if (ret) {
675 printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
676 __FILE__, ret);
677 return ret;
678 }
679
680 ret = of_register_platform_driver(&grlib_apbuart_of_driver);
681 if (ret) {
682 printk(KERN_ERR
683 "%s: of_register_platform_driver failed (%i)\n",
684 __FILE__, ret);
685 uart_unregister_driver(&grlib_apbuart_driver);
686 return ret;
687 }
688
689 return ret;
690}
691
692static void __exit grlib_apbuart_exit(void)
693{
694 int i;
695
696 for (i = 0; i < grlib_apbuart_port_nr; i++)
697 uart_remove_one_port(&grlib_apbuart_driver,
698 &grlib_apbuart_ports[i]);
699
700 uart_unregister_driver(&grlib_apbuart_driver);
701 of_unregister_platform_driver(&grlib_apbuart_of_driver);
702}
703
704module_init(grlib_apbuart_init);
705module_exit(grlib_apbuart_exit);
706
707MODULE_AUTHOR("Aeroflex Gaisler AB");
708MODULE_DESCRIPTION("GRLIB APBUART serial driver");
709MODULE_VERSION("2.1");
710MODULE_LICENSE("GPL");
diff --git a/drivers/serial/apbuart.h b/drivers/serial/apbuart.h
new file mode 100644
index 000000000000..5faf87c8d2bc
--- /dev/null
+++ b/drivers/serial/apbuart.h
@@ -0,0 +1,64 @@
1#ifndef __GRLIB_APBUART_H__
2#define __GRLIB_APBUART_H__
3
4#include <asm/io.h>
5
6#define UART_NR 8
7static int grlib_apbuart_port_nr;
8
9struct grlib_apbuart_regs_map {
10 u32 data;
11 u32 status;
12 u32 ctrl;
13 u32 scaler;
14};
15
16struct amba_prom_registers {
17 unsigned int phys_addr;
18 unsigned int reg_size;
19};
20
21/*
22 * The following defines the bits in the APBUART Status Registers.
23 */
24#define UART_STATUS_DR 0x00000001 /* Data Ready */
25#define UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
26#define UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
27#define UART_STATUS_BR 0x00000008 /* Break Error */
28#define UART_STATUS_OE 0x00000010 /* RX Overrun Error */
29#define UART_STATUS_PE 0x00000020 /* RX Parity Error */
30#define UART_STATUS_FE 0x00000040 /* RX Framing Error */
31#define UART_STATUS_ERR 0x00000078 /* Error Mask */
32
33/*
34 * The following defines the bits in the APBUART Ctrl Registers.
35 */
36#define UART_CTRL_RE 0x00000001 /* Receiver enable */
37#define UART_CTRL_TE 0x00000002 /* Transmitter enable */
38#define UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
39#define UART_CTRL_TI 0x00000008 /* Transmitter irq */
40#define UART_CTRL_PS 0x00000010 /* Parity select */
41#define UART_CTRL_PE 0x00000020 /* Parity enable */
42#define UART_CTRL_FL 0x00000040 /* Flow control enable */
43#define UART_CTRL_LB 0x00000080 /* Loopback enable */
44
45#define APBBASE(port) ((struct grlib_apbuart_regs_map *)((port)->membase))
46
47#define APBBASE_DATA_P(port) (&(APBBASE(port)->data))
48#define APBBASE_STATUS_P(port) (&(APBBASE(port)->status))
49#define APBBASE_CTRL_P(port) (&(APBBASE(port)->ctrl))
50#define APBBASE_SCALAR_P(port) (&(APBBASE(port)->scaler))
51
52#define UART_GET_CHAR(port) (__raw_readl(APBBASE_DATA_P(port)))
53#define UART_PUT_CHAR(port, v) (__raw_writel(v, APBBASE_DATA_P(port)))
54#define UART_GET_STATUS(port) (__raw_readl(APBBASE_STATUS_P(port)))
55#define UART_PUT_STATUS(port, v)(__raw_writel(v, APBBASE_STATUS_P(port)))
56#define UART_GET_CTRL(port) (__raw_readl(APBBASE_CTRL_P(port)))
57#define UART_PUT_CTRL(port, v) (__raw_writel(v, APBBASE_CTRL_P(port)))
58#define UART_GET_SCAL(port) (__raw_readl(APBBASE_SCALAR_P(port)))
59#define UART_PUT_SCAL(port, v) (__raw_writel(v, APBBASE_SCALAR_P(port)))
60
61#define UART_RX_DATA(s) (((s) & UART_STATUS_DR) != 0)
62#define UART_TX_READY(s) (((s) & UART_STATUS_THE) != 0)
63
64#endif /* __GRLIB_APBUART_H__ */
diff --git a/drivers/staging/arlan/arlan-proc.c b/drivers/staging/arlan/arlan-proc.c
index a8b689635a3b..b22983e6c0cf 100644
--- a/drivers/staging/arlan/arlan-proc.c
+++ b/drivers/staging/arlan/arlan-proc.c
@@ -816,84 +816,83 @@ static int arlan_sysctl_reset(ctl_table * ctl, int write,
816 816
817 817
818/* Place files in /proc/sys/dev/arlan */ 818/* Place files in /proc/sys/dev/arlan */
819#define CTBLN(num,card,nam) \ 819#define CTBLN(card,nam) \
820 { .ctl_name = num,\ 820 { .procname = #nam,\
821 .procname = #nam,\
822 .data = &(arlan_conf[card].nam),\ 821 .data = &(arlan_conf[card].nam),\
823 .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec} 822 .maxlen = sizeof(int), .mode = 0600, .proc_handler = proc_dointvec}
824#ifdef ARLAN_DEBUGGING 823#ifdef ARLAN_DEBUGGING
825 824
826#define ARLAN_PROC_DEBUG_ENTRIES \ 825#define ARLAN_PROC_DEBUG_ENTRIES \
827 { .ctl_name = 48, .procname = "entry_exit_debug",\ 826 { .procname = "entry_exit_debug",\
828 .data = &arlan_entry_and_exit_debug,\ 827 .data = &arlan_entry_and_exit_debug,\
829 .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec},\ 828 .maxlen = sizeof(int), .mode = 0600, .proc_handler = proc_dointvec},\
830 { .ctl_name = 49, .procname = "debug", .data = &arlan_debug,\ 829 { .procname = "debug", .data = &arlan_debug,\
831 .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec}, 830 .maxlen = sizeof(int), .mode = 0600, .proc_handler = proc_dointvec},
832#else 831#else
833#define ARLAN_PROC_DEBUG_ENTRIES 832#define ARLAN_PROC_DEBUG_ENTRIES
834#endif 833#endif
835 834
836#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\ 835#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
837 CTBLN(1,cardNo,spreadingCode),\ 836 CTBLN(cardNo,spreadingCode),\
838 CTBLN(2,cardNo, channelNumber),\ 837 CTBLN(cardNo, channelNumber),\
839 CTBLN(3,cardNo, scramblingDisable),\ 838 CTBLN(cardNo, scramblingDisable),\
840 CTBLN(4,cardNo, txAttenuation),\ 839 CTBLN(cardNo, txAttenuation),\
841 CTBLN(5,cardNo, systemId), \ 840 CTBLN(cardNo, systemId), \
842 CTBLN(6,cardNo, maxDatagramSize),\ 841 CTBLN(cardNo, maxDatagramSize),\
843 CTBLN(7,cardNo, maxFrameSize),\ 842 CTBLN(cardNo, maxFrameSize),\
844 CTBLN(8,cardNo, maxRetries),\ 843 CTBLN(cardNo, maxRetries),\
845 CTBLN(9,cardNo, receiveMode),\ 844 CTBLN(cardNo, receiveMode),\
846 CTBLN(10,cardNo, priority),\ 845 CTBLN(cardNo, priority),\
847 CTBLN(11,cardNo, rootOrRepeater),\ 846 CTBLN(cardNo, rootOrRepeater),\
848 CTBLN(12,cardNo, SID),\ 847 CTBLN(cardNo, SID),\
849 CTBLN(13,cardNo, registrationMode),\ 848 CTBLN(cardNo, registrationMode),\
850 CTBLN(14,cardNo, registrationFill),\ 849 CTBLN(cardNo, registrationFill),\
851 CTBLN(15,cardNo, localTalkAddress),\ 850 CTBLN(cardNo, localTalkAddress),\
852 CTBLN(16,cardNo, codeFormat),\ 851 CTBLN(cardNo, codeFormat),\
853 CTBLN(17,cardNo, numChannels),\ 852 CTBLN(cardNo, numChannels),\
854 CTBLN(18,cardNo, channel1),\ 853 CTBLN(cardNo, channel1),\
855 CTBLN(19,cardNo, channel2),\ 854 CTBLN(cardNo, channel2),\
856 CTBLN(20,cardNo, channel3),\ 855 CTBLN(cardNo, channel3),\
857 CTBLN(21,cardNo, channel4),\ 856 CTBLN(cardNo, channel4),\
858 CTBLN(22,cardNo, txClear),\ 857 CTBLN(cardNo, txClear),\
859 CTBLN(23,cardNo, txRetries),\ 858 CTBLN(cardNo, txRetries),\
860 CTBLN(24,cardNo, txRouting),\ 859 CTBLN(cardNo, txRouting),\
861 CTBLN(25,cardNo, txScrambled),\ 860 CTBLN(cardNo, txScrambled),\
862 CTBLN(26,cardNo, rxParameter),\ 861 CTBLN(cardNo, rxParameter),\
863 CTBLN(27,cardNo, txTimeoutMs),\ 862 CTBLN(cardNo, txTimeoutMs),\
864 CTBLN(28,cardNo, waitCardTimeout),\ 863 CTBLN(cardNo, waitCardTimeout),\
865 CTBLN(29,cardNo, channelSet), \ 864 CTBLN(cardNo, channelSet), \
866 {.ctl_name = 30, .procname = "name",\ 865 { .procname = "name",\
867 .data = arlan_conf[cardNo].siteName,\ 866 .data = arlan_conf[cardNo].siteName,\
868 .maxlen = 16, .mode = 0600, .proc_handler = &proc_dostring},\ 867 .maxlen = 16, .mode = 0600, .proc_handler = proc_dostring},\
869 CTBLN(31,cardNo,waitTime),\ 868 CTBLN(cardNo,waitTime),\
870 CTBLN(32,cardNo,lParameter),\ 869 CTBLN(cardNo,lParameter),\
871 CTBLN(33,cardNo,_15),\ 870 CTBLN(cardNo,_15),\
872 CTBLN(34,cardNo,headerSize),\ 871 CTBLN(cardNo,headerSize),\
873 CTBLN(36,cardNo,tx_delay_ms),\ 872 CTBLN(cardNo,tx_delay_ms),\
874 CTBLN(37,cardNo,retries),\ 873 CTBLN(cardNo,retries),\
875 CTBLN(38,cardNo,ReTransmitPacketMaxSize),\ 874 CTBLN(cardNo,ReTransmitPacketMaxSize),\
876 CTBLN(39,cardNo,waitReTransmitPacketMaxSize),\ 875 CTBLN(cardNo,waitReTransmitPacketMaxSize),\
877 CTBLN(40,cardNo,fastReTransCount),\ 876 CTBLN(cardNo,fastReTransCount),\
878 CTBLN(41,cardNo,driverRetransmissions),\ 877 CTBLN(cardNo,driverRetransmissions),\
879 CTBLN(42,cardNo,txAckTimeoutMs),\ 878 CTBLN(cardNo,txAckTimeoutMs),\
880 CTBLN(43,cardNo,registrationInterrupts),\ 879 CTBLN(cardNo,registrationInterrupts),\
881 CTBLN(44,cardNo,hardwareType),\ 880 CTBLN(cardNo,hardwareType),\
882 CTBLN(45,cardNo,radioType),\ 881 CTBLN(cardNo,radioType),\
883 CTBLN(46,cardNo,writeEEPROM),\ 882 CTBLN(cardNo,writeEEPROM),\
884 CTBLN(47,cardNo,writeRadioType),\ 883 CTBLN(cardNo,writeRadioType),\
885 ARLAN_PROC_DEBUG_ENTRIES\ 884 ARLAN_PROC_DEBUG_ENTRIES\
886 CTBLN(50,cardNo,in_speed),\ 885 CTBLN(cardNo,in_speed),\
887 CTBLN(51,cardNo,out_speed),\ 886 CTBLN(cardNo,out_speed),\
888 CTBLN(52,cardNo,in_speed10),\ 887 CTBLN(cardNo,in_speed10),\
889 CTBLN(53,cardNo,out_speed10),\ 888 CTBLN(cardNo,out_speed10),\
890 CTBLN(54,cardNo,in_speed_max),\ 889 CTBLN(cardNo,in_speed_max),\
891 CTBLN(55,cardNo,out_speed_max),\ 890 CTBLN(cardNo,out_speed_max),\
892 CTBLN(56,cardNo,measure_rate),\ 891 CTBLN(cardNo,measure_rate),\
893 CTBLN(57,cardNo,pre_Command_Wait),\ 892 CTBLN(cardNo,pre_Command_Wait),\
894 CTBLN(58,cardNo,rx_tweak1),\ 893 CTBLN(cardNo,rx_tweak1),\
895 CTBLN(59,cardNo,rx_tweak2),\ 894 CTBLN(cardNo,rx_tweak2),\
896 CTBLN(60,cardNo,tx_queue_len),\ 895 CTBLN(cardNo,tx_queue_len),\
897 896
898 897
899 898
@@ -903,63 +902,56 @@ static ctl_table arlan_conf_table0[] =
903 902
904#ifdef ARLAN_PROC_SHM_DUMP 903#ifdef ARLAN_PROC_SHM_DUMP
905 { 904 {
906 .ctl_name = 150,
907 .procname = "arlan0-txRing", 905 .procname = "arlan0-txRing",
908 .data = &arlan_drive_info, 906 .data = &arlan_drive_info,
909 .maxlen = ARLAN_STR_SIZE, 907 .maxlen = ARLAN_STR_SIZE,
910 .mode = 0400, 908 .mode = 0400,
911 .proc_handler = &arlan_sysctl_infotxRing, 909 .proc_handler = arlan_sysctl_infotxRing,
912 }, 910 },
913 { 911 {
914 .ctl_name = 151,
915 .procname = "arlan0-rxRing", 912 .procname = "arlan0-rxRing",
916 .data = &arlan_drive_info, 913 .data = &arlan_drive_info,
917 .maxlen = ARLAN_STR_SIZE, 914 .maxlen = ARLAN_STR_SIZE,
918 .mode = 0400, 915 .mode = 0400,
919 .proc_handler = &arlan_sysctl_inforxRing, 916 .proc_handler = arlan_sysctl_inforxRing,
920 }, 917 },
921 { 918 {
922 .ctl_name = 152,
923 .procname = "arlan0-18", 919 .procname = "arlan0-18",
924 .data = &arlan_drive_info, 920 .data = &arlan_drive_info,
925 .maxlen = ARLAN_STR_SIZE, 921 .maxlen = ARLAN_STR_SIZE,
926 .mode = 0400, 922 .mode = 0400,
927 .proc_handler = &arlan_sysctl_info18, 923 .proc_handler = arlan_sysctl_info18,
928 }, 924 },
929 { 925 {
930 .ctl_name = 153,
931 .procname = "arlan0-ring", 926 .procname = "arlan0-ring",
932 .data = &arlan_drive_info, 927 .data = &arlan_drive_info,
933 .maxlen = ARLAN_STR_SIZE, 928 .maxlen = ARLAN_STR_SIZE,
934 .mode = 0400, 929 .mode = 0400,
935 .proc_handler = &arlan_sysctl_info161719, 930 .proc_handler = arlan_sysctl_info161719,
936 }, 931 },
937 { 932 {
938 .ctl_name = 154,
939 .procname = "arlan0-shm-cpy", 933 .procname = "arlan0-shm-cpy",
940 .data = &arlan_drive_info, 934 .data = &arlan_drive_info,
941 .maxlen = ARLAN_STR_SIZE, 935 .maxlen = ARLAN_STR_SIZE,
942 .mode = 0400, 936 .mode = 0400,
943 .proc_handler = &arlan_sysctl_info, 937 .proc_handler = arlan_sysctl_info,
944 }, 938 },
945#endif 939#endif
946 { 940 {
947 .ctl_name = 155,
948 .procname = "config0", 941 .procname = "config0",
949 .data = &conf_reset_result, 942 .data = &conf_reset_result,
950 .maxlen = 100, 943 .maxlen = 100,
951 .mode = 0400, 944 .mode = 0400,
952 .proc_handler = &arlan_configure 945 .proc_handler = arlan_configure
953 }, 946 },
954 { 947 {
955 .ctl_name = 156,
956 .procname = "reset0", 948 .procname = "reset0",
957 .data = &conf_reset_result, 949 .data = &conf_reset_result,
958 .maxlen = 100, 950 .maxlen = 100,
959 .mode = 0400, 951 .mode = 0400,
960 .proc_handler = &arlan_sysctl_reset, 952 .proc_handler = arlan_sysctl_reset,
961 }, 953 },
962 { .ctl_name = 0 } 954 { }
963}; 955};
964 956
965static ctl_table arlan_conf_table1[] = 957static ctl_table arlan_conf_table1[] =
@@ -969,63 +961,56 @@ static ctl_table arlan_conf_table1[] =
969 961
970#ifdef ARLAN_PROC_SHM_DUMP 962#ifdef ARLAN_PROC_SHM_DUMP
971 { 963 {
972 .ctl_name = 150,
973 .procname = "arlan1-txRing", 964 .procname = "arlan1-txRing",
974 .data = &arlan_drive_info, 965 .data = &arlan_drive_info,
975 .maxlen = ARLAN_STR_SIZE, 966 .maxlen = ARLAN_STR_SIZE,
976 .mode = 0400, 967 .mode = 0400,
977 .proc_handler = &arlan_sysctl_infotxRing, 968 .proc_handler = arlan_sysctl_infotxRing,
978 }, 969 },
979 { 970 {
980 .ctl_name = 151,
981 .procname = "arlan1-rxRing", 971 .procname = "arlan1-rxRing",
982 .data = &arlan_drive_info, 972 .data = &arlan_drive_info,
983 .maxlen = ARLAN_STR_SIZE, 973 .maxlen = ARLAN_STR_SIZE,
984 .mode = 0400, 974 .mode = 0400,
985 .proc_handler = &arlan_sysctl_inforxRing, 975 .proc_handler = arlan_sysctl_inforxRing,
986 }, 976 },
987 { 977 {
988 .ctl_name = 152,
989 .procname = "arlan1-18", 978 .procname = "arlan1-18",
990 .data = &arlan_drive_info, 979 .data = &arlan_drive_info,
991 .maxlen = ARLAN_STR_SIZE, 980 .maxlen = ARLAN_STR_SIZE,
992 .mode = 0400, 981 .mode = 0400,
993 .proc_handler = &arlan_sysctl_info18, 982 .proc_handler = arlan_sysctl_info18,
994 }, 983 },
995 { 984 {
996 .ctl_name = 153,
997 .procname = "arlan1-ring", 985 .procname = "arlan1-ring",
998 .data = &arlan_drive_info, 986 .data = &arlan_drive_info,
999 .maxlen = ARLAN_STR_SIZE, 987 .maxlen = ARLAN_STR_SIZE,
1000 .mode = 0400, 988 .mode = 0400,
1001 .proc_handler = &arlan_sysctl_info161719, 989 .proc_handler = arlan_sysctl_info161719,
1002 }, 990 },
1003 { 991 {
1004 .ctl_name = 154,
1005 .procname = "arlan1-shm-cpy", 992 .procname = "arlan1-shm-cpy",
1006 .data = &arlan_drive_info, 993 .data = &arlan_drive_info,
1007 .maxlen = ARLAN_STR_SIZE, 994 .maxlen = ARLAN_STR_SIZE,
1008 .mode = 0400, 995 .mode = 0400,
1009 .proc_handler = &arlan_sysctl_info, 996 .proc_handler = arlan_sysctl_info,
1010 }, 997 },
1011#endif 998#endif
1012 { 999 {
1013 .ctl_name = 155,
1014 .procname = "config1", 1000 .procname = "config1",
1015 .data = &conf_reset_result, 1001 .data = &conf_reset_result,
1016 .maxlen = 100, 1002 .maxlen = 100,
1017 .mode = 0400, 1003 .mode = 0400,
1018 .proc_handler = &arlan_configure, 1004 .proc_handler = arlan_configure,
1019 }, 1005 },
1020 { 1006 {
1021 .ctl_name = 156,
1022 .procname = "reset1", 1007 .procname = "reset1",
1023 .data = &conf_reset_result, 1008 .data = &conf_reset_result,
1024 .maxlen = 100, 1009 .maxlen = 100,
1025 .mode = 0400, 1010 .mode = 0400,
1026 .proc_handler = &arlan_sysctl_reset, 1011 .proc_handler = arlan_sysctl_reset,
1027 }, 1012 },
1028 { .ctl_name = 0 } 1013 { }
1029}; 1014};
1030 1015
1031static ctl_table arlan_conf_table2[] = 1016static ctl_table arlan_conf_table2[] =
@@ -1035,63 +1020,56 @@ static ctl_table arlan_conf_table2[] =
1035 1020
1036#ifdef ARLAN_PROC_SHM_DUMP 1021#ifdef ARLAN_PROC_SHM_DUMP
1037 { 1022 {
1038 .ctl_name = 150,
1039 .procname = "arlan2-txRing", 1023 .procname = "arlan2-txRing",
1040 .data = &arlan_drive_info, 1024 .data = &arlan_drive_info,
1041 .maxlen = ARLAN_STR_SIZE, 1025 .maxlen = ARLAN_STR_SIZE,
1042 .mode = 0400, 1026 .mode = 0400,
1043 .proc_handler = &arlan_sysctl_infotxRing, 1027 .proc_handler = arlan_sysctl_infotxRing,
1044 }, 1028 },
1045 { 1029 {
1046 .ctl_name = 151,
1047 .procname = "arlan2-rxRing", 1030 .procname = "arlan2-rxRing",
1048 .data = &arlan_drive_info, 1031 .data = &arlan_drive_info,
1049 .maxlen = ARLAN_STR_SIZE, 1032 .maxlen = ARLAN_STR_SIZE,
1050 .mode = 0400, 1033 .mode = 0400,
1051 .proc_handler = &arlan_sysctl_inforxRing, 1034 .proc_handler = arlan_sysctl_inforxRing,
1052 }, 1035 },
1053 { 1036 {
1054 .ctl_name = 152,
1055 .procname = "arlan2-18", 1037 .procname = "arlan2-18",
1056 .data = &arlan_drive_info, 1038 .data = &arlan_drive_info,
1057 .maxlen = ARLAN_STR_SIZE, 1039 .maxlen = ARLAN_STR_SIZE,
1058 .mode = 0400, 1040 .mode = 0400,
1059 .proc_handler = &arlan_sysctl_info18, 1041 .proc_handler = arlan_sysctl_info18,
1060 }, 1042 },
1061 { 1043 {
1062 .ctl_name = 153,
1063 .procname = "arlan2-ring", 1044 .procname = "arlan2-ring",
1064 .data = &arlan_drive_info, 1045 .data = &arlan_drive_info,
1065 .maxlen = ARLAN_STR_SIZE, 1046 .maxlen = ARLAN_STR_SIZE,
1066 .mode = 0400, 1047 .mode = 0400,
1067 .proc_handler = &arlan_sysctl_info161719, 1048 .proc_handler = arlan_sysctl_info161719,
1068 }, 1049 },
1069 { 1050 {
1070 .ctl_name = 154,
1071 .procname = "arlan2-shm-cpy", 1051 .procname = "arlan2-shm-cpy",
1072 .data = &arlan_drive_info, 1052 .data = &arlan_drive_info,
1073 .maxlen = ARLAN_STR_SIZE, 1053 .maxlen = ARLAN_STR_SIZE,
1074 .mode = 0400, 1054 .mode = 0400,
1075 .proc_handler = &arlan_sysctl_info, 1055 .proc_handler = arlan_sysctl_info,
1076 }, 1056 },
1077#endif 1057#endif
1078 { 1058 {
1079 .ctl_name = 155,
1080 .procname = "config2", 1059 .procname = "config2",
1081 .data = &conf_reset_result, 1060 .data = &conf_reset_result,
1082 .maxlen = 100, 1061 .maxlen = 100,
1083 .mode = 0400, 1062 .mode = 0400,
1084 .proc_handler = &arlan_configure, 1063 .proc_handler = arlan_configure,
1085 }, 1064 },
1086 { 1065 {
1087 .ctl_name = 156,
1088 .procname = "reset2", 1066 .procname = "reset2",
1089 .data = &conf_reset_result, 1067 .data = &conf_reset_result,
1090 .maxlen = 100, 1068 .maxlen = 100,
1091 .mode = 0400, 1069 .mode = 0400,
1092 .proc_handler = &arlan_sysctl_reset, 1070 .proc_handler = arlan_sysctl_reset,
1093 }, 1071 },
1094 { .ctl_name = 0 } 1072 { }
1095}; 1073};
1096 1074
1097static ctl_table arlan_conf_table3[] = 1075static ctl_table arlan_conf_table3[] =
@@ -1101,63 +1079,56 @@ static ctl_table arlan_conf_table3[] =
1101 1079
1102#ifdef ARLAN_PROC_SHM_DUMP 1080#ifdef ARLAN_PROC_SHM_DUMP
1103 { 1081 {
1104 .ctl_name = 150,
1105 .procname = "arlan3-txRing", 1082 .procname = "arlan3-txRing",
1106 .data = &arlan_drive_info, 1083 .data = &arlan_drive_info,
1107 .maxlen = ARLAN_STR_SIZE, 1084 .maxlen = ARLAN_STR_SIZE,
1108 .mode = 0400, 1085 .mode = 0400,
1109 .proc_handler = &arlan_sysctl_infotxRing, 1086 .proc_handler = arlan_sysctl_infotxRing,
1110 }, 1087 },
1111 { 1088 {
1112 .ctl_name = 151,
1113 .procname = "arlan3-rxRing", 1089 .procname = "arlan3-rxRing",
1114 .data = &arlan_drive_info, 1090 .data = &arlan_drive_info,
1115 .maxlen = ARLAN_STR_SIZE, 1091 .maxlen = ARLAN_STR_SIZE,
1116 .mode = 0400, 1092 .mode = 0400,
1117 .proc_handler = &arlan_sysctl_inforxRing, 1093 .proc_handler = arlan_sysctl_inforxRing,
1118 }, 1094 },
1119 { 1095 {
1120 .ctl_name = 152,
1121 .procname = "arlan3-18", 1096 .procname = "arlan3-18",
1122 .data = &arlan_drive_info, 1097 .data = &arlan_drive_info,
1123 .maxlen = ARLAN_STR_SIZE, 1098 .maxlen = ARLAN_STR_SIZE,
1124 .mode = 0400, 1099 .mode = 0400,
1125 .proc_handler = &arlan_sysctl_info18, 1100 .proc_handler = arlan_sysctl_info18,
1126 }, 1101 },
1127 { 1102 {
1128 .ctl_name = 153,
1129 .procname = "arlan3-ring", 1103 .procname = "arlan3-ring",
1130 .data = &arlan_drive_info, 1104 .data = &arlan_drive_info,
1131 .maxlen = ARLAN_STR_SIZE, 1105 .maxlen = ARLAN_STR_SIZE,
1132 .mode = 0400, 1106 .mode = 0400,
1133 .proc_handler = &arlan_sysctl_info161719, 1107 .proc_handler = arlan_sysctl_info161719,
1134 }, 1108 },
1135 { 1109 {
1136 .ctl_name = 154,
1137 .procname = "arlan3-shm-cpy", 1110 .procname = "arlan3-shm-cpy",
1138 .data = &arlan_drive_info, 1111 .data = &arlan_drive_info,
1139 .maxlen = ARLAN_STR_SIZE, 1112 .maxlen = ARLAN_STR_SIZE,
1140 .mode = 0400, 1113 .mode = 0400,
1141 .proc_handler = &arlan_sysctl_info, 1114 .proc_handler = arlan_sysctl_info,
1142 }, 1115 },
1143#endif 1116#endif
1144 { 1117 {
1145 .ctl_name = 155,
1146 .procname = "config3", 1118 .procname = "config3",
1147 .data = &conf_reset_result, 1119 .data = &conf_reset_result,
1148 .maxlen = 100, 1120 .maxlen = 100,
1149 .mode = 0400, 1121 .mode = 0400,
1150 .proc_handler = &arlan_configure, 1122 .proc_handler = arlan_configure,
1151 }, 1123 },
1152 { 1124 {
1153 .ctl_name = 156,
1154 .procname = "reset3", 1125 .procname = "reset3",
1155 .data = &conf_reset_result, 1126 .data = &conf_reset_result,
1156 .maxlen = 100, 1127 .maxlen = 100,
1157 .mode = 0400, 1128 .mode = 0400,
1158 .proc_handler = &arlan_sysctl_reset, 1129 .proc_handler = arlan_sysctl_reset,
1159 }, 1130 },
1160 { .ctl_name = 0 } 1131 { }
1161}; 1132};
1162 1133
1163 1134
@@ -1165,41 +1136,37 @@ static ctl_table arlan_conf_table3[] =
1165static ctl_table arlan_table[] = 1136static ctl_table arlan_table[] =
1166{ 1137{
1167 { 1138 {
1168 .ctl_name = 0,
1169 .procname = "arlan0", 1139 .procname = "arlan0",
1170 .maxlen = 0, 1140 .maxlen = 0,
1171 .mode = 0600, 1141 .mode = 0600,
1172 .child = arlan_conf_table0, 1142 .child = arlan_conf_table0,
1173 }, 1143 },
1174 { 1144 {
1175 .ctl_name = 0,
1176 .procname = "arlan1", 1145 .procname = "arlan1",
1177 .maxlen = 0, 1146 .maxlen = 0,
1178 .mode = 0600, 1147 .mode = 0600,
1179 .child = arlan_conf_table1, 1148 .child = arlan_conf_table1,
1180 }, 1149 },
1181 { 1150 {
1182 .ctl_name = 0,
1183 .procname = "arlan2", 1151 .procname = "arlan2",
1184 .maxlen = 0, 1152 .maxlen = 0,
1185 .mode = 0600, 1153 .mode = 0600,
1186 .child = arlan_conf_table2, 1154 .child = arlan_conf_table2,
1187 }, 1155 },
1188 { 1156 {
1189 .ctl_name = 0,
1190 .procname = "arlan3", 1157 .procname = "arlan3",
1191 .maxlen = 0, 1158 .maxlen = 0,
1192 .mode = 0600, 1159 .mode = 0600,
1193 .child = arlan_conf_table3, 1160 .child = arlan_conf_table3,
1194 }, 1161 },
1195 { .ctl_name = 0 } 1162 { }
1196}; 1163};
1197 1164
1198#else 1165#else
1199 1166
1200static ctl_table arlan_table[MAX_ARLANS + 1] = 1167static ctl_table arlan_table[] =
1201{ 1168{
1202 { .ctl_name = 0 } 1169 { }
1203}; 1170};
1204#endif 1171#endif
1205 1172
@@ -1209,22 +1176,14 @@ static ctl_table arlan_table[MAX_ARLANS + 1] =
1209static ctl_table arlan_root_table[] = 1176static ctl_table arlan_root_table[] =
1210{ 1177{
1211 { 1178 {
1212 .ctl_name = CTL_ARLAN,
1213 .procname = "arlan", 1179 .procname = "arlan",
1214 .maxlen = 0, 1180 .maxlen = 0,
1215 .mode = 0555, 1181 .mode = 0555,
1216 .child = arlan_table, 1182 .child = arlan_table,
1217 }, 1183 },
1218 { .ctl_name = 0 } 1184 { }
1219}; 1185};
1220 1186
1221/* Make sure that /proc/sys/dev is there */
1222//static ctl_table arlan_device_root_table[] =
1223//{
1224// {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
1225// {0}
1226//};
1227
1228 1187
1229static struct ctl_table_header *arlan_device_sysctl_header; 1188static struct ctl_table_header *arlan_device_sysctl_header;
1230 1189
@@ -1234,8 +1193,6 @@ int __init init_arlan_proc(void)
1234 int i = 0; 1193 int i = 0;
1235 if (arlan_device_sysctl_header) 1194 if (arlan_device_sysctl_header)
1236 return 0; 1195 return 0;
1237 for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++)
1238 arlan_table[i].ctl_name = i + 1;
1239 arlan_device_sysctl_header = register_sysctl_table(arlan_root_table); 1196 arlan_device_sysctl_header = register_sysctl_table(arlan_root_table);
1240 if (!arlan_device_sysctl_header) 1197 if (!arlan_device_sysctl_header)
1241 return -1; 1198 return -1;
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index d3c824dc2358..c14ae8676903 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -10,7 +10,6 @@
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/miscdevice.h> 12#include <linux/miscdevice.h>
13#include <linux/smp_lock.h>
14#include <linux/watchdog.h> 13#include <linux/watchdog.h>
15#include <linux/of.h> 14#include <linux/of.h>
16#include <linux/of_device.h> 15#include <linux/of_device.h>
@@ -75,7 +74,6 @@ static void riowd_writereg(struct riowd *p, u8 val, int index)
75 74
76static int riowd_open(struct inode *inode, struct file *filp) 75static int riowd_open(struct inode *inode, struct file *filp)
77{ 76{
78 cycle_kernel_lock();
79 nonseekable_open(inode, filp); 77 nonseekable_open(inode, filp);
80 return 0; 78 return 0;
81} 79}
@@ -194,6 +192,8 @@ static int __devinit riowd_probe(struct of_device *op,
194 printk(KERN_ERR PFX "Cannot map registers.\n"); 192 printk(KERN_ERR PFX "Cannot map registers.\n");
195 goto out_free; 193 goto out_free;
196 } 194 }
195 /* Make miscdev useable right away */
196 riowd_device = p;
197 197
198 err = misc_register(&riowd_miscdev); 198 err = misc_register(&riowd_miscdev);
199 if (err) { 199 if (err) {
@@ -205,10 +205,10 @@ static int __devinit riowd_probe(struct of_device *op,
205 "regs at %p\n", riowd_timeout, p->regs); 205 "regs at %p\n", riowd_timeout, p->regs);
206 206
207 dev_set_drvdata(&op->dev, p); 207 dev_set_drvdata(&op->dev, p);
208 riowd_device = p;
209 return 0; 208 return 0;
210 209
211out_iounmap: 210out_iounmap:
211 riowd_device = NULL;
212 of_iounmap(&op->resource[0], p->regs, 2); 212 of_iounmap(&op->resource[0], p->regs, 2);
213 213
214out_free: 214out_free:
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 43c96ce29614..c6405ce3c50e 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -17,28 +17,25 @@ static struct ctl_table_header *fs_table_header;
17 17
18static ctl_table coda_table[] = { 18static ctl_table coda_table[] = {
19 { 19 {
20 .ctl_name = CTL_UNNUMBERED,
21 .procname = "timeout", 20 .procname = "timeout",
22 .data = &coda_timeout, 21 .data = &coda_timeout,
23 .maxlen = sizeof(int), 22 .maxlen = sizeof(int),
24 .mode = 0644, 23 .mode = 0644,
25 .proc_handler = &proc_dointvec 24 .proc_handler = proc_dointvec
26 }, 25 },
27 { 26 {
28 .ctl_name = CTL_UNNUMBERED,
29 .procname = "hard", 27 .procname = "hard",
30 .data = &coda_hard, 28 .data = &coda_hard,
31 .maxlen = sizeof(int), 29 .maxlen = sizeof(int),
32 .mode = 0644, 30 .mode = 0644,
33 .proc_handler = &proc_dointvec 31 .proc_handler = proc_dointvec
34 }, 32 },
35 { 33 {
36 .ctl_name = CTL_UNNUMBERED,
37 .procname = "fake_statfs", 34 .procname = "fake_statfs",
38 .data = &coda_fake_statfs, 35 .data = &coda_fake_statfs,
39 .maxlen = sizeof(int), 36 .maxlen = sizeof(int),
40 .mode = 0600, 37 .mode = 0600,
41 .proc_handler = &proc_dointvec 38 .proc_handler = proc_dointvec
42 }, 39 },
43 {} 40 {}
44}; 41};
@@ -46,7 +43,6 @@ static ctl_table coda_table[] = {
46#ifdef CONFIG_SYSCTL 43#ifdef CONFIG_SYSCTL
47static ctl_table fs_table[] = { 44static ctl_table fs_table[] = {
48 { 45 {
49 .ctl_name = CTL_UNNUMBERED,
50 .procname = "coda", 46 .procname = "coda",
51 .mode = 0555, 47 .mode = 0555,
52 .child = coda_table 48 .child = coda_table
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 085c5c063420..366c503f9657 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -251,10 +251,10 @@ ctl_table epoll_table[] = {
251 .data = &max_user_watches, 251 .data = &max_user_watches,
252 .maxlen = sizeof(int), 252 .maxlen = sizeof(int),
253 .mode = 0644, 253 .mode = 0644,
254 .proc_handler = &proc_dointvec_minmax, 254 .proc_handler = proc_dointvec_minmax,
255 .extra1 = &zero, 255 .extra1 = &zero,
256 }, 256 },
257 { .ctl_name = 0 } 257 { }
258}; 258};
259#endif /* CONFIG_SYSCTL */ 259#endif /* CONFIG_SYSCTL */
260 260
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 1a54ae14a192..e50cfa3d9654 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -371,82 +371,74 @@ EXPORT_SYMBOL_GPL(lockd_down);
371 371
372static ctl_table nlm_sysctls[] = { 372static ctl_table nlm_sysctls[] = {
373 { 373 {
374 .ctl_name = CTL_UNNUMBERED,
375 .procname = "nlm_grace_period", 374 .procname = "nlm_grace_period",
376 .data = &nlm_grace_period, 375 .data = &nlm_grace_period,
377 .maxlen = sizeof(unsigned long), 376 .maxlen = sizeof(unsigned long),
378 .mode = 0644, 377 .mode = 0644,
379 .proc_handler = &proc_doulongvec_minmax, 378 .proc_handler = proc_doulongvec_minmax,
380 .extra1 = (unsigned long *) &nlm_grace_period_min, 379 .extra1 = (unsigned long *) &nlm_grace_period_min,
381 .extra2 = (unsigned long *) &nlm_grace_period_max, 380 .extra2 = (unsigned long *) &nlm_grace_period_max,
382 }, 381 },
383 { 382 {
384 .ctl_name = CTL_UNNUMBERED,
385 .procname = "nlm_timeout", 383 .procname = "nlm_timeout",
386 .data = &nlm_timeout, 384 .data = &nlm_timeout,
387 .maxlen = sizeof(unsigned long), 385 .maxlen = sizeof(unsigned long),
388 .mode = 0644, 386 .mode = 0644,
389 .proc_handler = &proc_doulongvec_minmax, 387 .proc_handler = proc_doulongvec_minmax,
390 .extra1 = (unsigned long *) &nlm_timeout_min, 388 .extra1 = (unsigned long *) &nlm_timeout_min,
391 .extra2 = (unsigned long *) &nlm_timeout_max, 389 .extra2 = (unsigned long *) &nlm_timeout_max,
392 }, 390 },
393 { 391 {
394 .ctl_name = CTL_UNNUMBERED,
395 .procname = "nlm_udpport", 392 .procname = "nlm_udpport",
396 .data = &nlm_udpport, 393 .data = &nlm_udpport,
397 .maxlen = sizeof(int), 394 .maxlen = sizeof(int),
398 .mode = 0644, 395 .mode = 0644,
399 .proc_handler = &proc_dointvec_minmax, 396 .proc_handler = proc_dointvec_minmax,
400 .extra1 = (int *) &nlm_port_min, 397 .extra1 = (int *) &nlm_port_min,
401 .extra2 = (int *) &nlm_port_max, 398 .extra2 = (int *) &nlm_port_max,
402 }, 399 },
403 { 400 {
404 .ctl_name = CTL_UNNUMBERED,
405 .procname = "nlm_tcpport", 401 .procname = "nlm_tcpport",
406 .data = &nlm_tcpport, 402 .data = &nlm_tcpport,
407 .maxlen = sizeof(int), 403 .maxlen = sizeof(int),
408 .mode = 0644, 404 .mode = 0644,
409 .proc_handler = &proc_dointvec_minmax, 405 .proc_handler = proc_dointvec_minmax,
410 .extra1 = (int *) &nlm_port_min, 406 .extra1 = (int *) &nlm_port_min,
411 .extra2 = (int *) &nlm_port_max, 407 .extra2 = (int *) &nlm_port_max,
412 }, 408 },
413 { 409 {
414 .ctl_name = CTL_UNNUMBERED,
415 .procname = "nsm_use_hostnames", 410 .procname = "nsm_use_hostnames",
416 .data = &nsm_use_hostnames, 411 .data = &nsm_use_hostnames,
417 .maxlen = sizeof(int), 412 .maxlen = sizeof(int),
418 .mode = 0644, 413 .mode = 0644,
419 .proc_handler = &proc_dointvec, 414 .proc_handler = proc_dointvec,
420 }, 415 },
421 { 416 {
422 .ctl_name = CTL_UNNUMBERED,
423 .procname = "nsm_local_state", 417 .procname = "nsm_local_state",
424 .data = &nsm_local_state, 418 .data = &nsm_local_state,
425 .maxlen = sizeof(int), 419 .maxlen = sizeof(int),
426 .mode = 0644, 420 .mode = 0644,
427 .proc_handler = &proc_dointvec, 421 .proc_handler = proc_dointvec,
428 }, 422 },
429 { .ctl_name = 0 } 423 { }
430}; 424};
431 425
432static ctl_table nlm_sysctl_dir[] = { 426static ctl_table nlm_sysctl_dir[] = {
433 { 427 {
434 .ctl_name = CTL_UNNUMBERED,
435 .procname = "nfs", 428 .procname = "nfs",
436 .mode = 0555, 429 .mode = 0555,
437 .child = nlm_sysctls, 430 .child = nlm_sysctls,
438 }, 431 },
439 { .ctl_name = 0 } 432 { }
440}; 433};
441 434
442static ctl_table nlm_sysctl_root[] = { 435static ctl_table nlm_sysctl_root[] = {
443 { 436 {
444 .ctl_name = CTL_FS,
445 .procname = "fs", 437 .procname = "fs",
446 .mode = 0555, 438 .mode = 0555,
447 .child = nlm_sysctl_dir, 439 .child = nlm_sysctl_dir,
448 }, 440 },
449 { .ctl_name = 0 } 441 { }
450}; 442};
451 443
452#endif /* CONFIG_SYSCTL */ 444#endif /* CONFIG_SYSCTL */
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index b62481dabae9..70e1fbbaaeab 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -22,63 +22,55 @@ static struct ctl_table_header *nfs_callback_sysctl_table;
22static ctl_table nfs_cb_sysctls[] = { 22static ctl_table nfs_cb_sysctls[] = {
23#ifdef CONFIG_NFS_V4 23#ifdef CONFIG_NFS_V4
24 { 24 {
25 .ctl_name = CTL_UNNUMBERED,
26 .procname = "nfs_callback_tcpport", 25 .procname = "nfs_callback_tcpport",
27 .data = &nfs_callback_set_tcpport, 26 .data = &nfs_callback_set_tcpport,
28 .maxlen = sizeof(int), 27 .maxlen = sizeof(int),
29 .mode = 0644, 28 .mode = 0644,
30 .proc_handler = &proc_dointvec_minmax, 29 .proc_handler = proc_dointvec_minmax,
31 .extra1 = (int *)&nfs_set_port_min, 30 .extra1 = (int *)&nfs_set_port_min,
32 .extra2 = (int *)&nfs_set_port_max, 31 .extra2 = (int *)&nfs_set_port_max,
33 }, 32 },
34 { 33 {
35 .ctl_name = CTL_UNNUMBERED,
36 .procname = "idmap_cache_timeout", 34 .procname = "idmap_cache_timeout",
37 .data = &nfs_idmap_cache_timeout, 35 .data = &nfs_idmap_cache_timeout,
38 .maxlen = sizeof(int), 36 .maxlen = sizeof(int),
39 .mode = 0644, 37 .mode = 0644,
40 .proc_handler = &proc_dointvec_jiffies, 38 .proc_handler = proc_dointvec_jiffies,
41 .strategy = &sysctl_jiffies,
42 }, 39 },
43#endif 40#endif
44 { 41 {
45 .ctl_name = CTL_UNNUMBERED,
46 .procname = "nfs_mountpoint_timeout", 42 .procname = "nfs_mountpoint_timeout",
47 .data = &nfs_mountpoint_expiry_timeout, 43 .data = &nfs_mountpoint_expiry_timeout,
48 .maxlen = sizeof(nfs_mountpoint_expiry_timeout), 44 .maxlen = sizeof(nfs_mountpoint_expiry_timeout),
49 .mode = 0644, 45 .mode = 0644,
50 .proc_handler = &proc_dointvec_jiffies, 46 .proc_handler = proc_dointvec_jiffies,
51 .strategy = &sysctl_jiffies,
52 }, 47 },
53 { 48 {
54 .ctl_name = CTL_UNNUMBERED,
55 .procname = "nfs_congestion_kb", 49 .procname = "nfs_congestion_kb",
56 .data = &nfs_congestion_kb, 50 .data = &nfs_congestion_kb,
57 .maxlen = sizeof(nfs_congestion_kb), 51 .maxlen = sizeof(nfs_congestion_kb),
58 .mode = 0644, 52 .mode = 0644,
59 .proc_handler = &proc_dointvec, 53 .proc_handler = proc_dointvec,
60 }, 54 },
61 { .ctl_name = 0 } 55 { }
62}; 56};
63 57
64static ctl_table nfs_cb_sysctl_dir[] = { 58static ctl_table nfs_cb_sysctl_dir[] = {
65 { 59 {
66 .ctl_name = CTL_UNNUMBERED,
67 .procname = "nfs", 60 .procname = "nfs",
68 .mode = 0555, 61 .mode = 0555,
69 .child = nfs_cb_sysctls, 62 .child = nfs_cb_sysctls,
70 }, 63 },
71 { .ctl_name = 0 } 64 { }
72}; 65};
73 66
74static ctl_table nfs_cb_sysctl_root[] = { 67static ctl_table nfs_cb_sysctl_root[] = {
75 { 68 {
76 .ctl_name = CTL_FS,
77 .procname = "fs", 69 .procname = "fs",
78 .mode = 0555, 70 .mode = 0555,
79 .child = nfs_cb_sysctl_dir, 71 .child = nfs_cb_sysctl_dir,
80 }, 72 },
81 { .ctl_name = 0 } 73 { }
82}; 74};
83 75
84int nfs_register_sysctl(void) 76int nfs_register_sysctl(void)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index dcd2040d330c..1d1d1a2765dd 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -69,36 +69,30 @@ static int zero;
69 69
70ctl_table inotify_table[] = { 70ctl_table inotify_table[] = {
71 { 71 {
72 .ctl_name = INOTIFY_MAX_USER_INSTANCES,
73 .procname = "max_user_instances", 72 .procname = "max_user_instances",
74 .data = &inotify_max_user_instances, 73 .data = &inotify_max_user_instances,
75 .maxlen = sizeof(int), 74 .maxlen = sizeof(int),
76 .mode = 0644, 75 .mode = 0644,
77 .proc_handler = &proc_dointvec_minmax, 76 .proc_handler = proc_dointvec_minmax,
78 .strategy = &sysctl_intvec,
79 .extra1 = &zero, 77 .extra1 = &zero,
80 }, 78 },
81 { 79 {
82 .ctl_name = INOTIFY_MAX_USER_WATCHES,
83 .procname = "max_user_watches", 80 .procname = "max_user_watches",
84 .data = &inotify_max_user_watches, 81 .data = &inotify_max_user_watches,
85 .maxlen = sizeof(int), 82 .maxlen = sizeof(int),
86 .mode = 0644, 83 .mode = 0644,
87 .proc_handler = &proc_dointvec_minmax, 84 .proc_handler = proc_dointvec_minmax,
88 .strategy = &sysctl_intvec,
89 .extra1 = &zero, 85 .extra1 = &zero,
90 }, 86 },
91 { 87 {
92 .ctl_name = INOTIFY_MAX_QUEUED_EVENTS,
93 .procname = "max_queued_events", 88 .procname = "max_queued_events",
94 .data = &inotify_max_queued_events, 89 .data = &inotify_max_queued_events,
95 .maxlen = sizeof(int), 90 .maxlen = sizeof(int),
96 .mode = 0644, 91 .mode = 0644,
97 .proc_handler = &proc_dointvec_minmax, 92 .proc_handler = proc_dointvec_minmax,
98 .strategy = &sysctl_intvec,
99 .extra1 = &zero 93 .extra1 = &zero
100 }, 94 },
101 { .ctl_name = 0 } 95 { }
102}; 96};
103#endif /* CONFIG_SYSCTL */ 97#endif /* CONFIG_SYSCTL */
104 98
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c
index 9ef85e628fe1..79a89184cb5e 100644
--- a/fs/ntfs/sysctl.c
+++ b/fs/ntfs/sysctl.c
@@ -36,12 +36,11 @@
36/* Definition of the ntfs sysctl. */ 36/* Definition of the ntfs sysctl. */
37static ctl_table ntfs_sysctls[] = { 37static ctl_table ntfs_sysctls[] = {
38 { 38 {
39 .ctl_name = CTL_UNNUMBERED, /* Binary and text IDs. */
40 .procname = "ntfs-debug", 39 .procname = "ntfs-debug",
41 .data = &debug_msgs, /* Data pointer and size. */ 40 .data = &debug_msgs, /* Data pointer and size. */
42 .maxlen = sizeof(debug_msgs), 41 .maxlen = sizeof(debug_msgs),
43 .mode = 0644, /* Mode, proc handler. */ 42 .mode = 0644, /* Mode, proc handler. */
44 .proc_handler = &proc_dointvec 43 .proc_handler = proc_dointvec
45 }, 44 },
46 {} 45 {}
47}; 46};
@@ -49,7 +48,6 @@ static ctl_table ntfs_sysctls[] = {
49/* Define the parent directory /proc/sys/fs. */ 48/* Define the parent directory /proc/sys/fs. */
50static ctl_table sysctls_root[] = { 49static ctl_table sysctls_root[] = {
51 { 50 {
52 .ctl_name = CTL_FS,
53 .procname = "fs", 51 .procname = "fs",
54 .mode = 0555, 52 .mode = 0555,
55 .child = ntfs_sysctls 53 .child = ntfs_sysctls
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 3f2f1c45b7b6..f3df0baa9a48 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -620,51 +620,46 @@ error:
620 620
621static ctl_table ocfs2_nm_table[] = { 621static ctl_table ocfs2_nm_table[] = {
622 { 622 {
623 .ctl_name = 1,
624 .procname = "hb_ctl_path", 623 .procname = "hb_ctl_path",
625 .data = ocfs2_hb_ctl_path, 624 .data = ocfs2_hb_ctl_path,
626 .maxlen = OCFS2_MAX_HB_CTL_PATH, 625 .maxlen = OCFS2_MAX_HB_CTL_PATH,
627 .mode = 0644, 626 .mode = 0644,
628 .proc_handler = &proc_dostring, 627 .proc_handler = proc_dostring,
629 .strategy = &sysctl_string,
630 }, 628 },
631 { .ctl_name = 0 } 629 { }
632}; 630};
633 631
634static ctl_table ocfs2_mod_table[] = { 632static ctl_table ocfs2_mod_table[] = {
635 { 633 {
636 .ctl_name = FS_OCFS2_NM,
637 .procname = "nm", 634 .procname = "nm",
638 .data = NULL, 635 .data = NULL,
639 .maxlen = 0, 636 .maxlen = 0,
640 .mode = 0555, 637 .mode = 0555,
641 .child = ocfs2_nm_table 638 .child = ocfs2_nm_table
642 }, 639 },
643 { .ctl_name = 0} 640 { }
644}; 641};
645 642
646static ctl_table ocfs2_kern_table[] = { 643static ctl_table ocfs2_kern_table[] = {
647 { 644 {
648 .ctl_name = FS_OCFS2,
649 .procname = "ocfs2", 645 .procname = "ocfs2",
650 .data = NULL, 646 .data = NULL,
651 .maxlen = 0, 647 .maxlen = 0,
652 .mode = 0555, 648 .mode = 0555,
653 .child = ocfs2_mod_table 649 .child = ocfs2_mod_table
654 }, 650 },
655 { .ctl_name = 0} 651 { }
656}; 652};
657 653
658static ctl_table ocfs2_root_table[] = { 654static ctl_table ocfs2_root_table[] = {
659 { 655 {
660 .ctl_name = CTL_FS,
661 .procname = "fs", 656 .procname = "fs",
662 .data = NULL, 657 .data = NULL,
663 .maxlen = 0, 658 .maxlen = 0,
664 .mode = 0555, 659 .mode = 0555,
665 .child = ocfs2_kern_table 660 .child = ocfs2_kern_table
666 }, 661 },
667 { .ctl_name = 0 } 662 { }
668}; 663};
669 664
670static struct ctl_table_header *ocfs2_table_header = NULL; 665static struct ctl_table_header *ocfs2_table_header = NULL;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 822c2d506518..4badde179b18 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -410,6 +410,16 @@ static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
410} 410}
411#endif /* CONFIG_MMU */ 411#endif /* CONFIG_MMU */
412 412
413static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
414{
415 seq_printf(m, "Cpus_allowed:\t");
416 seq_cpumask(m, &task->cpus_allowed);
417 seq_printf(m, "\n");
418 seq_printf(m, "Cpus_allowed_list:\t");
419 seq_cpumask_list(m, &task->cpus_allowed);
420 seq_printf(m, "\n");
421}
422
413int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, 423int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
414 struct pid *pid, struct task_struct *task) 424 struct pid *pid, struct task_struct *task)
415{ 425{
@@ -424,6 +434,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
424 } 434 }
425 task_sig(m, task); 435 task_sig(m, task);
426 task_cap(m, task); 436 task_cap(m, task);
437 task_cpus_allowed(m, task);
427 cpuset_task_status_allowed(m, task); 438 cpuset_task_status_allowed(m, task);
428#if defined(CONFIG_S390) 439#if defined(CONFIG_S390)
429 task_show_regs(m, task); 440 task_show_regs(m, task);
@@ -495,20 +506,17 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
495 506
496 /* add up live thread stats at the group level */ 507 /* add up live thread stats at the group level */
497 if (whole) { 508 if (whole) {
498 struct task_cputime cputime;
499 struct task_struct *t = task; 509 struct task_struct *t = task;
500 do { 510 do {
501 min_flt += t->min_flt; 511 min_flt += t->min_flt;
502 maj_flt += t->maj_flt; 512 maj_flt += t->maj_flt;
503 gtime = cputime_add(gtime, task_gtime(t)); 513 gtime = cputime_add(gtime, t->gtime);
504 t = next_thread(t); 514 t = next_thread(t);
505 } while (t != task); 515 } while (t != task);
506 516
507 min_flt += sig->min_flt; 517 min_flt += sig->min_flt;
508 maj_flt += sig->maj_flt; 518 maj_flt += sig->maj_flt;
509 thread_group_cputime(task, &cputime); 519 thread_group_times(task, &utime, &stime);
510 utime = cputime.utime;
511 stime = cputime.stime;
512 gtime = cputime_add(gtime, sig->gtime); 520 gtime = cputime_add(gtime, sig->gtime);
513 } 521 }
514 522
@@ -524,9 +532,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
524 if (!whole) { 532 if (!whole) {
525 min_flt = task->min_flt; 533 min_flt = task->min_flt;
526 maj_flt = task->maj_flt; 534 maj_flt = task->maj_flt;
527 utime = task_utime(task); 535 task_times(task, &utime, &stime);
528 stime = task_stime(task); 536 gtime = task->gtime;
529 gtime = task_gtime(task);
530 } 537 }
531 538
532 /* scale priority and nice values from timeslices to -20..20 */ 539 /* scale priority and nice values from timeslices to -20..20 */
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f667e8aeabdf..6ff9981f0a18 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -48,7 +48,7 @@ out:
48static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name) 48static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name)
49{ 49{
50 int len; 50 int len;
51 for ( ; p->ctl_name || p->procname; p++) { 51 for ( ; p->procname; p++) {
52 52
53 if (!p->procname) 53 if (!p->procname)
54 continue; 54 continue;
@@ -218,7 +218,7 @@ static int scan(struct ctl_table_header *head, ctl_table *table,
218 void *dirent, filldir_t filldir) 218 void *dirent, filldir_t filldir)
219{ 219{
220 220
221 for (; table->ctl_name || table->procname; table++, (*pos)++) { 221 for (; table->procname; table++, (*pos)++) {
222 int res; 222 int res;
223 223
224 /* Can't do anything without a proc name */ 224 /* Can't do anything without a proc name */
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index 7cc726c6d70a..b9b7aad2003d 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -27,7 +27,7 @@ static int show_stat(struct seq_file *p, void *v)
27 int i, j; 27 int i, j;
28 unsigned long jif; 28 unsigned long jif;
29 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; 29 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
30 cputime64_t guest; 30 cputime64_t guest, guest_nice;
31 u64 sum = 0; 31 u64 sum = 0;
32 u64 sum_softirq = 0; 32 u64 sum_softirq = 0;
33 unsigned int per_softirq_sums[NR_SOFTIRQS] = {0}; 33 unsigned int per_softirq_sums[NR_SOFTIRQS] = {0};
@@ -36,7 +36,7 @@ static int show_stat(struct seq_file *p, void *v)
36 36
37 user = nice = system = idle = iowait = 37 user = nice = system = idle = iowait =
38 irq = softirq = steal = cputime64_zero; 38 irq = softirq = steal = cputime64_zero;
39 guest = cputime64_zero; 39 guest = guest_nice = cputime64_zero;
40 getboottime(&boottime); 40 getboottime(&boottime);
41 jif = boottime.tv_sec; 41 jif = boottime.tv_sec;
42 42
@@ -51,6 +51,8 @@ static int show_stat(struct seq_file *p, void *v)
51 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); 51 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
52 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); 52 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
53 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); 53 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
54 guest_nice = cputime64_add(guest_nice,
55 kstat_cpu(i).cpustat.guest_nice);
54 for_each_irq_nr(j) { 56 for_each_irq_nr(j) {
55 sum += kstat_irqs_cpu(j, i); 57 sum += kstat_irqs_cpu(j, i);
56 } 58 }
@@ -65,7 +67,8 @@ static int show_stat(struct seq_file *p, void *v)
65 } 67 }
66 sum += arch_irq_stat(); 68 sum += arch_irq_stat();
67 69
68 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", 70 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu "
71 "%llu\n",
69 (unsigned long long)cputime64_to_clock_t(user), 72 (unsigned long long)cputime64_to_clock_t(user),
70 (unsigned long long)cputime64_to_clock_t(nice), 73 (unsigned long long)cputime64_to_clock_t(nice),
71 (unsigned long long)cputime64_to_clock_t(system), 74 (unsigned long long)cputime64_to_clock_t(system),
@@ -74,7 +77,8 @@ static int show_stat(struct seq_file *p, void *v)
74 (unsigned long long)cputime64_to_clock_t(irq), 77 (unsigned long long)cputime64_to_clock_t(irq),
75 (unsigned long long)cputime64_to_clock_t(softirq), 78 (unsigned long long)cputime64_to_clock_t(softirq),
76 (unsigned long long)cputime64_to_clock_t(steal), 79 (unsigned long long)cputime64_to_clock_t(steal),
77 (unsigned long long)cputime64_to_clock_t(guest)); 80 (unsigned long long)cputime64_to_clock_t(guest),
81 (unsigned long long)cputime64_to_clock_t(guest_nice));
78 for_each_online_cpu(i) { 82 for_each_online_cpu(i) {
79 83
80 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ 84 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
@@ -88,8 +92,10 @@ static int show_stat(struct seq_file *p, void *v)
88 softirq = kstat_cpu(i).cpustat.softirq; 92 softirq = kstat_cpu(i).cpustat.softirq;
89 steal = kstat_cpu(i).cpustat.steal; 93 steal = kstat_cpu(i).cpustat.steal;
90 guest = kstat_cpu(i).cpustat.guest; 94 guest = kstat_cpu(i).cpustat.guest;
95 guest_nice = kstat_cpu(i).cpustat.guest_nice;
91 seq_printf(p, 96 seq_printf(p,
92 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", 97 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu "
98 "%llu\n",
93 i, 99 i,
94 (unsigned long long)cputime64_to_clock_t(user), 100 (unsigned long long)cputime64_to_clock_t(user),
95 (unsigned long long)cputime64_to_clock_t(nice), 101 (unsigned long long)cputime64_to_clock_t(nice),
@@ -99,7 +105,8 @@ static int show_stat(struct seq_file *p, void *v)
99 (unsigned long long)cputime64_to_clock_t(irq), 105 (unsigned long long)cputime64_to_clock_t(irq),
100 (unsigned long long)cputime64_to_clock_t(softirq), 106 (unsigned long long)cputime64_to_clock_t(softirq),
101 (unsigned long long)cputime64_to_clock_t(steal), 107 (unsigned long long)cputime64_to_clock_t(steal),
102 (unsigned long long)cputime64_to_clock_t(guest)); 108 (unsigned long long)cputime64_to_clock_t(guest),
109 (unsigned long long)cputime64_to_clock_t(guest_nice));
103 } 110 }
104 seq_printf(p, "intr %llu", (unsigned long long)sum); 111 seq_printf(p, "intr %llu", (unsigned long long)sum);
105 112
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 9b6ad908dcb2..eb5a755718f6 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2404,100 +2404,89 @@ const struct quotactl_ops vfs_quotactl_ops = {
2404 2404
2405static ctl_table fs_dqstats_table[] = { 2405static ctl_table fs_dqstats_table[] = {
2406 { 2406 {
2407 .ctl_name = FS_DQ_LOOKUPS,
2408 .procname = "lookups", 2407 .procname = "lookups",
2409 .data = &dqstats.lookups, 2408 .data = &dqstats.lookups,
2410 .maxlen = sizeof(int), 2409 .maxlen = sizeof(int),
2411 .mode = 0444, 2410 .mode = 0444,
2412 .proc_handler = &proc_dointvec, 2411 .proc_handler = proc_dointvec,
2413 }, 2412 },
2414 { 2413 {
2415 .ctl_name = FS_DQ_DROPS,
2416 .procname = "drops", 2414 .procname = "drops",
2417 .data = &dqstats.drops, 2415 .data = &dqstats.drops,
2418 .maxlen = sizeof(int), 2416 .maxlen = sizeof(int),
2419 .mode = 0444, 2417 .mode = 0444,
2420 .proc_handler = &proc_dointvec, 2418 .proc_handler = proc_dointvec,
2421 }, 2419 },
2422 { 2420 {
2423 .ctl_name = FS_DQ_READS,
2424 .procname = "reads", 2421 .procname = "reads",
2425 .data = &dqstats.reads, 2422 .data = &dqstats.reads,
2426 .maxlen = sizeof(int), 2423 .maxlen = sizeof(int),
2427 .mode = 0444, 2424 .mode = 0444,
2428 .proc_handler = &proc_dointvec, 2425 .proc_handler = proc_dointvec,
2429 }, 2426 },
2430 { 2427 {
2431 .ctl_name = FS_DQ_WRITES,
2432 .procname = "writes", 2428 .procname = "writes",
2433 .data = &dqstats.writes, 2429 .data = &dqstats.writes,
2434 .maxlen = sizeof(int), 2430 .maxlen = sizeof(int),
2435 .mode = 0444, 2431 .mode = 0444,
2436 .proc_handler = &proc_dointvec, 2432 .proc_handler = proc_dointvec,
2437 }, 2433 },
2438 { 2434 {
2439 .ctl_name = FS_DQ_CACHE_HITS,
2440 .procname = "cache_hits", 2435 .procname = "cache_hits",
2441 .data = &dqstats.cache_hits, 2436 .data = &dqstats.cache_hits,
2442 .maxlen = sizeof(int), 2437 .maxlen = sizeof(int),
2443 .mode = 0444, 2438 .mode = 0444,
2444 .proc_handler = &proc_dointvec, 2439 .proc_handler = proc_dointvec,
2445 }, 2440 },
2446 { 2441 {
2447 .ctl_name = FS_DQ_ALLOCATED,
2448 .procname = "allocated_dquots", 2442 .procname = "allocated_dquots",
2449 .data = &dqstats.allocated_dquots, 2443 .data = &dqstats.allocated_dquots,
2450 .maxlen = sizeof(int), 2444 .maxlen = sizeof(int),
2451 .mode = 0444, 2445 .mode = 0444,
2452 .proc_handler = &proc_dointvec, 2446 .proc_handler = proc_dointvec,
2453 }, 2447 },
2454 { 2448 {
2455 .ctl_name = FS_DQ_FREE,
2456 .procname = "free_dquots", 2449 .procname = "free_dquots",
2457 .data = &dqstats.free_dquots, 2450 .data = &dqstats.free_dquots,
2458 .maxlen = sizeof(int), 2451 .maxlen = sizeof(int),
2459 .mode = 0444, 2452 .mode = 0444,
2460 .proc_handler = &proc_dointvec, 2453 .proc_handler = proc_dointvec,
2461 }, 2454 },
2462 { 2455 {
2463 .ctl_name = FS_DQ_SYNCS,
2464 .procname = "syncs", 2456 .procname = "syncs",
2465 .data = &dqstats.syncs, 2457 .data = &dqstats.syncs,
2466 .maxlen = sizeof(int), 2458 .maxlen = sizeof(int),
2467 .mode = 0444, 2459 .mode = 0444,
2468 .proc_handler = &proc_dointvec, 2460 .proc_handler = proc_dointvec,
2469 }, 2461 },
2470#ifdef CONFIG_PRINT_QUOTA_WARNING 2462#ifdef CONFIG_PRINT_QUOTA_WARNING
2471 { 2463 {
2472 .ctl_name = FS_DQ_WARNINGS,
2473 .procname = "warnings", 2464 .procname = "warnings",
2474 .data = &flag_print_warnings, 2465 .data = &flag_print_warnings,
2475 .maxlen = sizeof(int), 2466 .maxlen = sizeof(int),
2476 .mode = 0644, 2467 .mode = 0644,
2477 .proc_handler = &proc_dointvec, 2468 .proc_handler = proc_dointvec,
2478 }, 2469 },
2479#endif 2470#endif
2480 { .ctl_name = 0 }, 2471 { },
2481}; 2472};
2482 2473
2483static ctl_table fs_table[] = { 2474static ctl_table fs_table[] = {
2484 { 2475 {
2485 .ctl_name = FS_DQSTATS,
2486 .procname = "quota", 2476 .procname = "quota",
2487 .mode = 0555, 2477 .mode = 0555,
2488 .child = fs_dqstats_table, 2478 .child = fs_dqstats_table,
2489 }, 2479 },
2490 { .ctl_name = 0 }, 2480 { },
2491}; 2481};
2492 2482
2493static ctl_table sys_table[] = { 2483static ctl_table sys_table[] = {
2494 { 2484 {
2495 .ctl_name = CTL_FS,
2496 .procname = "fs", 2485 .procname = "fs",
2497 .mode = 0555, 2486 .mode = 0555,
2498 .child = fs_table, 2487 .child = fs_table,
2499 }, 2488 },
2500 { .ctl_name = 0 }, 2489 { },
2501}; 2490};
2502 2491
2503static int __init dquot_init(void) 2492static int __init dquot_init(void)
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index c5bc67c4e3bb..7bb5092d6ae4 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -55,170 +55,140 @@ xfs_stats_clear_proc_handler(
55 55
56static ctl_table xfs_table[] = { 56static ctl_table xfs_table[] = {
57 { 57 {
58 .ctl_name = XFS_SGID_INHERIT,
59 .procname = "irix_sgid_inherit", 58 .procname = "irix_sgid_inherit",
60 .data = &xfs_params.sgid_inherit.val, 59 .data = &xfs_params.sgid_inherit.val,
61 .maxlen = sizeof(int), 60 .maxlen = sizeof(int),
62 .mode = 0644, 61 .mode = 0644,
63 .proc_handler = &proc_dointvec_minmax, 62 .proc_handler = proc_dointvec_minmax,
64 .strategy = &sysctl_intvec,
65 .extra1 = &xfs_params.sgid_inherit.min, 63 .extra1 = &xfs_params.sgid_inherit.min,
66 .extra2 = &xfs_params.sgid_inherit.max 64 .extra2 = &xfs_params.sgid_inherit.max
67 }, 65 },
68 { 66 {
69 .ctl_name = XFS_SYMLINK_MODE,
70 .procname = "irix_symlink_mode", 67 .procname = "irix_symlink_mode",
71 .data = &xfs_params.symlink_mode.val, 68 .data = &xfs_params.symlink_mode.val,
72 .maxlen = sizeof(int), 69 .maxlen = sizeof(int),
73 .mode = 0644, 70 .mode = 0644,
74 .proc_handler = &proc_dointvec_minmax, 71 .proc_handler = proc_dointvec_minmax,
75 .strategy = &sysctl_intvec,
76 .extra1 = &xfs_params.symlink_mode.min, 72 .extra1 = &xfs_params.symlink_mode.min,
77 .extra2 = &xfs_params.symlink_mode.max 73 .extra2 = &xfs_params.symlink_mode.max
78 }, 74 },
79 { 75 {
80 .ctl_name = XFS_PANIC_MASK,
81 .procname = "panic_mask", 76 .procname = "panic_mask",
82 .data = &xfs_params.panic_mask.val, 77 .data = &xfs_params.panic_mask.val,
83 .maxlen = sizeof(int), 78 .maxlen = sizeof(int),
84 .mode = 0644, 79 .mode = 0644,
85 .proc_handler = &proc_dointvec_minmax, 80 .proc_handler = proc_dointvec_minmax,
86 .strategy = &sysctl_intvec,
87 .extra1 = &xfs_params.panic_mask.min, 81 .extra1 = &xfs_params.panic_mask.min,
88 .extra2 = &xfs_params.panic_mask.max 82 .extra2 = &xfs_params.panic_mask.max
89 }, 83 },
90 84
91 { 85 {
92 .ctl_name = XFS_ERRLEVEL,
93 .procname = "error_level", 86 .procname = "error_level",
94 .data = &xfs_params.error_level.val, 87 .data = &xfs_params.error_level.val,
95 .maxlen = sizeof(int), 88 .maxlen = sizeof(int),
96 .mode = 0644, 89 .mode = 0644,
97 .proc_handler = &proc_dointvec_minmax, 90 .proc_handler = proc_dointvec_minmax,
98 .strategy = &sysctl_intvec,
99 .extra1 = &xfs_params.error_level.min, 91 .extra1 = &xfs_params.error_level.min,
100 .extra2 = &xfs_params.error_level.max 92 .extra2 = &xfs_params.error_level.max
101 }, 93 },
102 { 94 {
103 .ctl_name = XFS_SYNCD_TIMER,
104 .procname = "xfssyncd_centisecs", 95 .procname = "xfssyncd_centisecs",
105 .data = &xfs_params.syncd_timer.val, 96 .data = &xfs_params.syncd_timer.val,
106 .maxlen = sizeof(int), 97 .maxlen = sizeof(int),
107 .mode = 0644, 98 .mode = 0644,
108 .proc_handler = &proc_dointvec_minmax, 99 .proc_handler = proc_dointvec_minmax,
109 .strategy = &sysctl_intvec,
110 .extra1 = &xfs_params.syncd_timer.min, 100 .extra1 = &xfs_params.syncd_timer.min,
111 .extra2 = &xfs_params.syncd_timer.max 101 .extra2 = &xfs_params.syncd_timer.max
112 }, 102 },
113 { 103 {
114 .ctl_name = XFS_INHERIT_SYNC,
115 .procname = "inherit_sync", 104 .procname = "inherit_sync",
116 .data = &xfs_params.inherit_sync.val, 105 .data = &xfs_params.inherit_sync.val,
117 .maxlen = sizeof(int), 106 .maxlen = sizeof(int),
118 .mode = 0644, 107 .mode = 0644,
119 .proc_handler = &proc_dointvec_minmax, 108 .proc_handler = proc_dointvec_minmax,
120 .strategy = &sysctl_intvec,
121 .extra1 = &xfs_params.inherit_sync.min, 109 .extra1 = &xfs_params.inherit_sync.min,
122 .extra2 = &xfs_params.inherit_sync.max 110 .extra2 = &xfs_params.inherit_sync.max
123 }, 111 },
124 { 112 {
125 .ctl_name = XFS_INHERIT_NODUMP,
126 .procname = "inherit_nodump", 113 .procname = "inherit_nodump",
127 .data = &xfs_params.inherit_nodump.val, 114 .data = &xfs_params.inherit_nodump.val,
128 .maxlen = sizeof(int), 115 .maxlen = sizeof(int),
129 .mode = 0644, 116 .mode = 0644,
130 .proc_handler = &proc_dointvec_minmax, 117 .proc_handler = proc_dointvec_minmax,
131 .strategy = &sysctl_intvec,
132 .extra1 = &xfs_params.inherit_nodump.min, 118 .extra1 = &xfs_params.inherit_nodump.min,
133 .extra2 = &xfs_params.inherit_nodump.max 119 .extra2 = &xfs_params.inherit_nodump.max
134 }, 120 },
135 { 121 {
136 .ctl_name = XFS_INHERIT_NOATIME,
137 .procname = "inherit_noatime", 122 .procname = "inherit_noatime",
138 .data = &xfs_params.inherit_noatim.val, 123 .data = &xfs_params.inherit_noatim.val,
139 .maxlen = sizeof(int), 124 .maxlen = sizeof(int),
140 .mode = 0644, 125 .mode = 0644,
141 .proc_handler = &proc_dointvec_minmax, 126 .proc_handler = proc_dointvec_minmax,
142 .strategy = &sysctl_intvec,
143 .extra1 = &xfs_params.inherit_noatim.min, 127 .extra1 = &xfs_params.inherit_noatim.min,
144 .extra2 = &xfs_params.inherit_noatim.max 128 .extra2 = &xfs_params.inherit_noatim.max
145 }, 129 },
146 { 130 {
147 .ctl_name = XFS_BUF_TIMER,
148 .procname = "xfsbufd_centisecs", 131 .procname = "xfsbufd_centisecs",
149 .data = &xfs_params.xfs_buf_timer.val, 132 .data = &xfs_params.xfs_buf_timer.val,
150 .maxlen = sizeof(int), 133 .maxlen = sizeof(int),
151 .mode = 0644, 134 .mode = 0644,
152 .proc_handler = &proc_dointvec_minmax, 135 .proc_handler = proc_dointvec_minmax,
153 .strategy = &sysctl_intvec,
154 .extra1 = &xfs_params.xfs_buf_timer.min, 136 .extra1 = &xfs_params.xfs_buf_timer.min,
155 .extra2 = &xfs_params.xfs_buf_timer.max 137 .extra2 = &xfs_params.xfs_buf_timer.max
156 }, 138 },
157 { 139 {
158 .ctl_name = XFS_BUF_AGE,
159 .procname = "age_buffer_centisecs", 140 .procname = "age_buffer_centisecs",
160 .data = &xfs_params.xfs_buf_age.val, 141 .data = &xfs_params.xfs_buf_age.val,
161 .maxlen = sizeof(int), 142 .maxlen = sizeof(int),
162 .mode = 0644, 143 .mode = 0644,
163 .proc_handler = &proc_dointvec_minmax, 144 .proc_handler = proc_dointvec_minmax,
164 .strategy = &sysctl_intvec,
165 .extra1 = &xfs_params.xfs_buf_age.min, 145 .extra1 = &xfs_params.xfs_buf_age.min,
166 .extra2 = &xfs_params.xfs_buf_age.max 146 .extra2 = &xfs_params.xfs_buf_age.max
167 }, 147 },
168 { 148 {
169 .ctl_name = XFS_INHERIT_NOSYM,
170 .procname = "inherit_nosymlinks", 149 .procname = "inherit_nosymlinks",
171 .data = &xfs_params.inherit_nosym.val, 150 .data = &xfs_params.inherit_nosym.val,
172 .maxlen = sizeof(int), 151 .maxlen = sizeof(int),
173 .mode = 0644, 152 .mode = 0644,
174 .proc_handler = &proc_dointvec_minmax, 153 .proc_handler = proc_dointvec_minmax,
175 .strategy = &sysctl_intvec,
176 .extra1 = &xfs_params.inherit_nosym.min, 154 .extra1 = &xfs_params.inherit_nosym.min,
177 .extra2 = &xfs_params.inherit_nosym.max 155 .extra2 = &xfs_params.inherit_nosym.max
178 }, 156 },
179 { 157 {
180 .ctl_name = XFS_ROTORSTEP,
181 .procname = "rotorstep", 158 .procname = "rotorstep",
182 .data = &xfs_params.rotorstep.val, 159 .data = &xfs_params.rotorstep.val,
183 .maxlen = sizeof(int), 160 .maxlen = sizeof(int),
184 .mode = 0644, 161 .mode = 0644,
185 .proc_handler = &proc_dointvec_minmax, 162 .proc_handler = proc_dointvec_minmax,
186 .strategy = &sysctl_intvec,
187 .extra1 = &xfs_params.rotorstep.min, 163 .extra1 = &xfs_params.rotorstep.min,
188 .extra2 = &xfs_params.rotorstep.max 164 .extra2 = &xfs_params.rotorstep.max
189 }, 165 },
190 { 166 {
191 .ctl_name = XFS_INHERIT_NODFRG,
192 .procname = "inherit_nodefrag", 167 .procname = "inherit_nodefrag",
193 .data = &xfs_params.inherit_nodfrg.val, 168 .data = &xfs_params.inherit_nodfrg.val,
194 .maxlen = sizeof(int), 169 .maxlen = sizeof(int),
195 .mode = 0644, 170 .mode = 0644,
196 .proc_handler = &proc_dointvec_minmax, 171 .proc_handler = proc_dointvec_minmax,
197 .strategy = &sysctl_intvec,
198 .extra1 = &xfs_params.inherit_nodfrg.min, 172 .extra1 = &xfs_params.inherit_nodfrg.min,
199 .extra2 = &xfs_params.inherit_nodfrg.max 173 .extra2 = &xfs_params.inherit_nodfrg.max
200 }, 174 },
201 { 175 {
202 .ctl_name = XFS_FILESTREAM_TIMER,
203 .procname = "filestream_centisecs", 176 .procname = "filestream_centisecs",
204 .data = &xfs_params.fstrm_timer.val, 177 .data = &xfs_params.fstrm_timer.val,
205 .maxlen = sizeof(int), 178 .maxlen = sizeof(int),
206 .mode = 0644, 179 .mode = 0644,
207 .proc_handler = &proc_dointvec_minmax, 180 .proc_handler = proc_dointvec_minmax,
208 .strategy = &sysctl_intvec,
209 .extra1 = &xfs_params.fstrm_timer.min, 181 .extra1 = &xfs_params.fstrm_timer.min,
210 .extra2 = &xfs_params.fstrm_timer.max, 182 .extra2 = &xfs_params.fstrm_timer.max,
211 }, 183 },
212 /* please keep this the last entry */ 184 /* please keep this the last entry */
213#ifdef CONFIG_PROC_FS 185#ifdef CONFIG_PROC_FS
214 { 186 {
215 .ctl_name = XFS_STATS_CLEAR,
216 .procname = "stats_clear", 187 .procname = "stats_clear",
217 .data = &xfs_params.stats_clear.val, 188 .data = &xfs_params.stats_clear.val,
218 .maxlen = sizeof(int), 189 .maxlen = sizeof(int),
219 .mode = 0644, 190 .mode = 0644,
220 .proc_handler = &xfs_stats_clear_proc_handler, 191 .proc_handler = xfs_stats_clear_proc_handler,
221 .strategy = &sysctl_intvec,
222 .extra1 = &xfs_params.stats_clear.min, 192 .extra1 = &xfs_params.stats_clear.min,
223 .extra2 = &xfs_params.stats_clear.max 193 .extra2 = &xfs_params.stats_clear.max
224 }, 194 },
@@ -229,7 +199,6 @@ static ctl_table xfs_table[] = {
229 199
230static ctl_table xfs_dir_table[] = { 200static ctl_table xfs_dir_table[] = {
231 { 201 {
232 .ctl_name = FS_XFS,
233 .procname = "xfs", 202 .procname = "xfs",
234 .mode = 0555, 203 .mode = 0555,
235 .child = xfs_table 204 .child = xfs_table
@@ -239,7 +208,6 @@ static ctl_table xfs_dir_table[] = {
239 208
240static ctl_table xfs_root_table[] = { 209static ctl_table xfs_root_table[] = {
241 { 210 {
242 .ctl_name = CTL_FS,
243 .procname = "fs", 211 .procname = "fs",
244 .mode = 0555, 212 .mode = 0555,
245 .child = xfs_dir_table 213 .child = xfs_dir_table
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index ab3af40a53c6..94dea3ffbfa1 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -51,3 +51,11 @@
51#endif 51#endif
52 52
53#endif 53#endif
54
55#if __GNUC_MINOR__ > 0
56#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
57#endif
58#if __GNUC_MINOR__ >= 4
59#define __compiletime_warning(message) __attribute__((warning(message)))
60#define __compiletime_error(message) __attribute__((error(message)))
61#endif
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index acbd654cc850..5be3dab4a695 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -275,6 +275,17 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
275# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) 275# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
276#endif 276#endif
277 277
278/* Compile time object size, -1 for unknown */
279#ifndef __compiletime_object_size
280# define __compiletime_object_size(obj) -1
281#endif
282#ifndef __compiletime_warning
283# define __compiletime_warning(message)
284#endif
285#ifndef __compiletime_error
286# define __compiletime_error(message)
287#endif
288
278/* 289/*
279 * Prevent the compiler from merging or refetching accesses. The compiler 290 * Prevent the compiler from merging or refetching accesses. The compiler
280 * is also forbidden from reordering successive instances of ACCESS_ONCE(), 291 * is also forbidden from reordering successive instances of ACCESS_ONCE(),
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 4ec5e67e18cf..47bbdf9c38d0 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -117,12 +117,12 @@ struct ftrace_event_call {
117 struct dentry *dir; 117 struct dentry *dir;
118 struct trace_event *event; 118 struct trace_event *event;
119 int enabled; 119 int enabled;
120 int (*regfunc)(void *); 120 int (*regfunc)(struct ftrace_event_call *);
121 void (*unregfunc)(void *); 121 void (*unregfunc)(struct ftrace_event_call *);
122 int id; 122 int id;
123 int (*raw_init)(void); 123 int (*raw_init)(struct ftrace_event_call *);
124 int (*show_format)(struct ftrace_event_call *call, 124 int (*show_format)(struct ftrace_event_call *,
125 struct trace_seq *s); 125 struct trace_seq *);
126 int (*define_fields)(struct ftrace_event_call *); 126 int (*define_fields)(struct ftrace_event_call *);
127 struct list_head fields; 127 struct list_head fields;
128 int filter_active; 128 int filter_active;
@@ -131,20 +131,20 @@ struct ftrace_event_call {
131 void *data; 131 void *data;
132 132
133 atomic_t profile_count; 133 atomic_t profile_count;
134 int (*profile_enable)(void); 134 int (*profile_enable)(struct ftrace_event_call *);
135 void (*profile_disable)(void); 135 void (*profile_disable)(struct ftrace_event_call *);
136}; 136};
137 137
138#define FTRACE_MAX_PROFILE_SIZE 2048 138#define FTRACE_MAX_PROFILE_SIZE 2048
139 139
140extern char *trace_profile_buf; 140extern char *perf_trace_buf;
141extern char *trace_profile_buf_nmi; 141extern char *perf_trace_buf_nmi;
142 142
143#define MAX_FILTER_PRED 32 143#define MAX_FILTER_PRED 32
144#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ 144#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
145 145
146extern void destroy_preds(struct ftrace_event_call *call); 146extern void destroy_preds(struct ftrace_event_call *call);
147extern int filter_match_preds(struct ftrace_event_call *call, void *rec); 147extern int filter_match_preds(struct event_filter *filter, void *rec);
148extern int filter_current_check_discard(struct ring_buffer *buffer, 148extern int filter_current_check_discard(struct ring_buffer *buffer,
149 struct ftrace_event_call *call, 149 struct ftrace_event_call *call,
150 void *rec, 150 void *rec,
@@ -157,11 +157,12 @@ enum {
157 FILTER_PTR_STRING, 157 FILTER_PTR_STRING,
158}; 158};
159 159
160extern int trace_define_field(struct ftrace_event_call *call,
161 const char *type, const char *name,
162 int offset, int size, int is_signed,
163 int filter_type);
164extern int trace_define_common_fields(struct ftrace_event_call *call); 160extern int trace_define_common_fields(struct ftrace_event_call *call);
161extern int trace_define_field(struct ftrace_event_call *call, const char *type,
162 const char *name, int offset, int size,
163 int is_signed, int filter_type);
164extern int trace_add_event_call(struct ftrace_event_call *call);
165extern void trace_remove_event_call(struct ftrace_event_call *call);
165 166
166#define is_signed_type(type) (((type)(-1)) < 0) 167#define is_signed_type(type) (((type)(-1)) < 0)
167 168
@@ -186,4 +187,13 @@ do { \
186 __trace_printk(ip, fmt, ##args); \ 187 __trace_printk(ip, fmt, ##args); \
187} while (0) 188} while (0)
188 189
190#ifdef CONFIG_EVENT_PROFILE
191struct perf_event;
192extern int ftrace_profile_enable(int event_id);
193extern void ftrace_profile_disable(int event_id);
194extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
195 char *filter_str);
196extern void ftrace_profile_free_filter(struct perf_event *event);
197#endif
198
189#endif /* _LINUX_FTRACE_EVENT_H */ 199#endif /* _LINUX_FTRACE_EVENT_H */
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
new file mode 100644
index 000000000000..a03daed08c59
--- /dev/null
+++ b/include/linux/hw_breakpoint.h
@@ -0,0 +1,131 @@
1#ifndef _LINUX_HW_BREAKPOINT_H
2#define _LINUX_HW_BREAKPOINT_H
3
4enum {
5 HW_BREAKPOINT_LEN_1 = 1,
6 HW_BREAKPOINT_LEN_2 = 2,
7 HW_BREAKPOINT_LEN_4 = 4,
8 HW_BREAKPOINT_LEN_8 = 8,
9};
10
11enum {
12 HW_BREAKPOINT_R = 1,
13 HW_BREAKPOINT_W = 2,
14 HW_BREAKPOINT_X = 4,
15};
16
17#ifdef __KERNEL__
18
19#include <linux/perf_event.h>
20
21#ifdef CONFIG_HAVE_HW_BREAKPOINT
22
23/* As it's for in-kernel or ptrace use, we want it to be pinned */
24#define DEFINE_BREAKPOINT_ATTR(name) \
25struct perf_event_attr name = { \
26 .type = PERF_TYPE_BREAKPOINT, \
27 .size = sizeof(name), \
28 .pinned = 1, \
29};
30
31static inline void hw_breakpoint_init(struct perf_event_attr *attr)
32{
33 attr->type = PERF_TYPE_BREAKPOINT;
34 attr->size = sizeof(*attr);
35 attr->pinned = 1;
36}
37
38static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
39{
40 return bp->attr.bp_addr;
41}
42
43static inline int hw_breakpoint_type(struct perf_event *bp)
44{
45 return bp->attr.bp_type;
46}
47
48static inline int hw_breakpoint_len(struct perf_event *bp)
49{
50 return bp->attr.bp_len;
51}
52
53extern struct perf_event *
54register_user_hw_breakpoint(struct perf_event_attr *attr,
55 perf_callback_t triggered,
56 struct task_struct *tsk);
57
58/* FIXME: only change from the attr, and don't unregister */
59extern struct perf_event *
60modify_user_hw_breakpoint(struct perf_event *bp,
61 struct perf_event_attr *attr,
62 perf_callback_t triggered,
63 struct task_struct *tsk);
64
65/*
66 * Kernel breakpoints are not associated with any particular thread.
67 */
68extern struct perf_event *
69register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
70 perf_callback_t triggered,
71 int cpu);
72
73extern struct perf_event **
74register_wide_hw_breakpoint(struct perf_event_attr *attr,
75 perf_callback_t triggered);
76
77extern int register_perf_hw_breakpoint(struct perf_event *bp);
78extern int __register_perf_hw_breakpoint(struct perf_event *bp);
79extern void unregister_hw_breakpoint(struct perf_event *bp);
80extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
81
82extern int reserve_bp_slot(struct perf_event *bp);
83extern void release_bp_slot(struct perf_event *bp);
84
85extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
86
87static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
88{
89 return &bp->hw.info;
90}
91
92#else /* !CONFIG_HAVE_HW_BREAKPOINT */
93
94static inline struct perf_event *
95register_user_hw_breakpoint(struct perf_event_attr *attr,
96 perf_callback_t triggered,
97 struct task_struct *tsk) { return NULL; }
98static inline struct perf_event *
99modify_user_hw_breakpoint(struct perf_event *bp,
100 struct perf_event_attr *attr,
101 perf_callback_t triggered,
102 struct task_struct *tsk) { return NULL; }
103static inline struct perf_event *
104register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
105 perf_callback_t triggered,
106 int cpu) { return NULL; }
107static inline struct perf_event **
108register_wide_hw_breakpoint(struct perf_event_attr *attr,
109 perf_callback_t triggered) { return NULL; }
110static inline int
111register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
112static inline int
113__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
114static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
115static inline void
116unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { }
117static inline int
118reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
119static inline void release_bp_slot(struct perf_event *bp) { }
120
121static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
122
123static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
124{
125 return NULL;
126}
127
128#endif /* CONFIG_HAVE_HW_BREAKPOINT */
129#endif /* __KERNEL__ */
130
131#endif /* _LINUX_HW_BREAKPOINT_H */
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 508824ee35e6..5306a759cbde 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -401,6 +401,24 @@ struct twl4030_power_data {
401 401
402extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); 402extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
403 403
404struct twl4030_codec_audio_data {
405 unsigned int audio_mclk;
406 unsigned int ramp_delay_value;
407 unsigned int hs_extmute:1;
408 void (*set_hs_extmute)(int mute);
409};
410
411struct twl4030_codec_vibra_data {
412 unsigned int audio_mclk;
413 unsigned int coexist;
414};
415
416struct twl4030_codec_data {
417 unsigned int audio_mclk;
418 struct twl4030_codec_audio_data *audio;
419 struct twl4030_codec_vibra_data *vibra;
420};
421
404struct twl4030_platform_data { 422struct twl4030_platform_data {
405 unsigned irq_base, irq_end; 423 unsigned irq_base, irq_end;
406 struct twl4030_bci_platform_data *bci; 424 struct twl4030_bci_platform_data *bci;
@@ -409,6 +427,7 @@ struct twl4030_platform_data {
409 struct twl4030_keypad_data *keypad; 427 struct twl4030_keypad_data *keypad;
410 struct twl4030_usb_data *usb; 428 struct twl4030_usb_data *usb;
411 struct twl4030_power_data *power; 429 struct twl4030_power_data *power;
430 struct twl4030_codec_data *codec;
412 431
413 /* LDO regulators */ 432 /* LDO regulators */
414 struct regulator_init_data *vdac; 433 struct regulator_init_data *vdac;
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 1a9cf78bfce5..6811f4bfc6e7 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -307,6 +307,7 @@ extern clock_t jiffies_to_clock_t(long x);
307extern unsigned long clock_t_to_jiffies(unsigned long x); 307extern unsigned long clock_t_to_jiffies(unsigned long x);
308extern u64 jiffies_64_to_clock_t(u64 x); 308extern u64 jiffies_64_to_clock_t(u64 x);
309extern u64 nsec_to_clock_t(u64 x); 309extern u64 nsec_to_clock_t(u64 x);
310extern unsigned long nsecs_to_jiffies(u64 n);
310 311
311#define TIMESTAMP_SIZE 30 312#define TIMESTAMP_SIZE 30
312 313
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 348fa8874b52..c059044bc6dc 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -25,6 +25,7 @@ struct cpu_usage_stat {
25 cputime64_t iowait; 25 cputime64_t iowait;
26 cputime64_t steal; 26 cputime64_t steal;
27 cputime64_t guest; 27 cputime64_t guest;
28 cputime64_t guest_nice;
28}; 29};
29 30
30struct kernel_stat { 31struct kernel_stat {
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 3a46b7b7abb2..1b672f74a32f 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -296,6 +296,8 @@ void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
296int disable_kprobe(struct kprobe *kp); 296int disable_kprobe(struct kprobe *kp);
297int enable_kprobe(struct kprobe *kp); 297int enable_kprobe(struct kprobe *kp);
298 298
299void dump_kprobe(struct kprobe *kp);
300
299#else /* !CONFIG_KPROBES: */ 301#else /* !CONFIG_KPROBES: */
300 302
301static inline int kprobes_built_in(void) 303static inline int kprobes_built_in(void)
diff --git a/include/linux/mfd/twl4030-codec.h b/include/linux/mfd/twl4030-codec.h
new file mode 100644
index 000000000000..2ec317c68e59
--- /dev/null
+++ b/include/linux/mfd/twl4030-codec.h
@@ -0,0 +1,272 @@
1/*
2 * MFD driver for twl4030 codec submodule
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __TWL4030_CODEC_H__
25#define __TWL4030_CODEC_H__
26
27/* Codec registers */
28#define TWL4030_REG_CODEC_MODE 0x01
29#define TWL4030_REG_OPTION 0x02
30#define TWL4030_REG_UNKNOWN 0x03
31#define TWL4030_REG_MICBIAS_CTL 0x04
32#define TWL4030_REG_ANAMICL 0x05
33#define TWL4030_REG_ANAMICR 0x06
34#define TWL4030_REG_AVADC_CTL 0x07
35#define TWL4030_REG_ADCMICSEL 0x08
36#define TWL4030_REG_DIGMIXING 0x09
37#define TWL4030_REG_ATXL1PGA 0x0A
38#define TWL4030_REG_ATXR1PGA 0x0B
39#define TWL4030_REG_AVTXL2PGA 0x0C
40#define TWL4030_REG_AVTXR2PGA 0x0D
41#define TWL4030_REG_AUDIO_IF 0x0E
42#define TWL4030_REG_VOICE_IF 0x0F
43#define TWL4030_REG_ARXR1PGA 0x10
44#define TWL4030_REG_ARXL1PGA 0x11
45#define TWL4030_REG_ARXR2PGA 0x12
46#define TWL4030_REG_ARXL2PGA 0x13
47#define TWL4030_REG_VRXPGA 0x14
48#define TWL4030_REG_VSTPGA 0x15
49#define TWL4030_REG_VRX2ARXPGA 0x16
50#define TWL4030_REG_AVDAC_CTL 0x17
51#define TWL4030_REG_ARX2VTXPGA 0x18
52#define TWL4030_REG_ARXL1_APGA_CTL 0x19
53#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
54#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
55#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
56#define TWL4030_REG_ATX2ARXPGA 0x1D
57#define TWL4030_REG_BT_IF 0x1E
58#define TWL4030_REG_BTPGA 0x1F
59#define TWL4030_REG_BTSTPGA 0x20
60#define TWL4030_REG_EAR_CTL 0x21
61#define TWL4030_REG_HS_SEL 0x22
62#define TWL4030_REG_HS_GAIN_SET 0x23
63#define TWL4030_REG_HS_POPN_SET 0x24
64#define TWL4030_REG_PREDL_CTL 0x25
65#define TWL4030_REG_PREDR_CTL 0x26
66#define TWL4030_REG_PRECKL_CTL 0x27
67#define TWL4030_REG_PRECKR_CTL 0x28
68#define TWL4030_REG_HFL_CTL 0x29
69#define TWL4030_REG_HFR_CTL 0x2A
70#define TWL4030_REG_ALC_CTL 0x2B
71#define TWL4030_REG_ALC_SET1 0x2C
72#define TWL4030_REG_ALC_SET2 0x2D
73#define TWL4030_REG_BOOST_CTL 0x2E
74#define TWL4030_REG_SOFTVOL_CTL 0x2F
75#define TWL4030_REG_DTMF_FREQSEL 0x30
76#define TWL4030_REG_DTMF_TONEXT1H 0x31
77#define TWL4030_REG_DTMF_TONEXT1L 0x32
78#define TWL4030_REG_DTMF_TONEXT2H 0x33
79#define TWL4030_REG_DTMF_TONEXT2L 0x34
80#define TWL4030_REG_DTMF_TONOFF 0x35
81#define TWL4030_REG_DTMF_WANONOFF 0x36
82#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
83#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
84#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
85#define TWL4030_REG_APLL_CTL 0x3A
86#define TWL4030_REG_DTMF_CTL 0x3B
87#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
88#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
89#define TWL4030_REG_MISC_SET_1 0x3E
90#define TWL4030_REG_PCMBTMUX 0x3F
91#define TWL4030_REG_RX_PATH_SEL 0x43
92#define TWL4030_REG_VDL_APGA_CTL 0x44
93#define TWL4030_REG_VIBRA_CTL 0x45
94#define TWL4030_REG_VIBRA_SET 0x46
95#define TWL4030_REG_VIBRA_PWM_SET 0x47
96#define TWL4030_REG_ANAMIC_GAIN 0x48
97#define TWL4030_REG_MISC_SET_2 0x49
98
99/* Bitfield Definitions */
100
101/* TWL4030_CODEC_MODE (0x01) Fields */
102#define TWL4030_APLL_RATE 0xF0
103#define TWL4030_APLL_RATE_8000 0x00
104#define TWL4030_APLL_RATE_11025 0x10
105#define TWL4030_APLL_RATE_12000 0x20
106#define TWL4030_APLL_RATE_16000 0x40
107#define TWL4030_APLL_RATE_22050 0x50
108#define TWL4030_APLL_RATE_24000 0x60
109#define TWL4030_APLL_RATE_32000 0x80
110#define TWL4030_APLL_RATE_44100 0x90
111#define TWL4030_APLL_RATE_48000 0xA0
112#define TWL4030_APLL_RATE_96000 0xE0
113#define TWL4030_SEL_16K 0x08
114#define TWL4030_CODECPDZ 0x02
115#define TWL4030_OPT_MODE 0x01
116#define TWL4030_OPTION_1 (1 << 0)
117#define TWL4030_OPTION_2 (0 << 0)
118
119/* TWL4030_OPTION (0x02) Fields */
120#define TWL4030_ATXL1_EN (1 << 0)
121#define TWL4030_ATXR1_EN (1 << 1)
122#define TWL4030_ATXL2_VTXL_EN (1 << 2)
123#define TWL4030_ATXR2_VTXR_EN (1 << 3)
124#define TWL4030_ARXL1_VRX_EN (1 << 4)
125#define TWL4030_ARXR1_EN (1 << 5)
126#define TWL4030_ARXL2_EN (1 << 6)
127#define TWL4030_ARXR2_EN (1 << 7)
128
129/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
130#define TWL4030_MICBIAS2_CTL 0x40
131#define TWL4030_MICBIAS1_CTL 0x20
132#define TWL4030_HSMICBIAS_EN 0x04
133#define TWL4030_MICBIAS2_EN 0x02
134#define TWL4030_MICBIAS1_EN 0x01
135
136/* ANAMICL (0x05) Fields */
137#define TWL4030_CNCL_OFFSET_START 0x80
138#define TWL4030_OFFSET_CNCL_SEL 0x60
139#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
140#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
141#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
142#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
143#define TWL4030_MICAMPL_EN 0x10
144#define TWL4030_CKMIC_EN 0x08
145#define TWL4030_AUXL_EN 0x04
146#define TWL4030_HSMIC_EN 0x02
147#define TWL4030_MAINMIC_EN 0x01
148
149/* ANAMICR (0x06) Fields */
150#define TWL4030_MICAMPR_EN 0x10
151#define TWL4030_AUXR_EN 0x04
152#define TWL4030_SUBMIC_EN 0x01
153
154/* AVADC_CTL (0x07) Fields */
155#define TWL4030_ADCL_EN 0x08
156#define TWL4030_AVADC_CLK_PRIORITY 0x04
157#define TWL4030_ADCR_EN 0x02
158
159/* TWL4030_REG_ADCMICSEL (0x08) Fields */
160#define TWL4030_DIGMIC1_EN 0x08
161#define TWL4030_TX2IN_SEL 0x04
162#define TWL4030_DIGMIC0_EN 0x02
163#define TWL4030_TX1IN_SEL 0x01
164
165/* AUDIO_IF (0x0E) Fields */
166#define TWL4030_AIF_SLAVE_EN 0x80
167#define TWL4030_DATA_WIDTH 0x60
168#define TWL4030_DATA_WIDTH_16S_16W 0x00
169#define TWL4030_DATA_WIDTH_32S_16W 0x40
170#define TWL4030_DATA_WIDTH_32S_24W 0x60
171#define TWL4030_AIF_FORMAT 0x18
172#define TWL4030_AIF_FORMAT_CODEC 0x00
173#define TWL4030_AIF_FORMAT_LEFT 0x08
174#define TWL4030_AIF_FORMAT_RIGHT 0x10
175#define TWL4030_AIF_FORMAT_TDM 0x18
176#define TWL4030_AIF_TRI_EN 0x04
177#define TWL4030_CLK256FS_EN 0x02
178#define TWL4030_AIF_EN 0x01
179
180/* VOICE_IF (0x0F) Fields */
181#define TWL4030_VIF_SLAVE_EN 0x80
182#define TWL4030_VIF_DIN_EN 0x40
183#define TWL4030_VIF_DOUT_EN 0x20
184#define TWL4030_VIF_SWAP 0x10
185#define TWL4030_VIF_FORMAT 0x08
186#define TWL4030_VIF_TRI_EN 0x04
187#define TWL4030_VIF_SUB_EN 0x02
188#define TWL4030_VIF_EN 0x01
189
190/* EAR_CTL (0x21) */
191#define TWL4030_EAR_GAIN 0x30
192
193/* HS_GAIN_SET (0x23) Fields */
194#define TWL4030_HSR_GAIN 0x0C
195#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
196#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
197#define TWL4030_HSR_GAIN_0DB 0x08
198#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
199#define TWL4030_HSL_GAIN 0x03
200#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
201#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
202#define TWL4030_HSL_GAIN_0DB 0x02
203#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
204
205/* HS_POPN_SET (0x24) Fields */
206#define TWL4030_VMID_EN 0x40
207#define TWL4030_EXTMUTE 0x20
208#define TWL4030_RAMP_DELAY 0x1C
209#define TWL4030_RAMP_DELAY_20MS 0x00
210#define TWL4030_RAMP_DELAY_40MS 0x04
211#define TWL4030_RAMP_DELAY_81MS 0x08
212#define TWL4030_RAMP_DELAY_161MS 0x0C
213#define TWL4030_RAMP_DELAY_323MS 0x10
214#define TWL4030_RAMP_DELAY_645MS 0x14
215#define TWL4030_RAMP_DELAY_1291MS 0x18
216#define TWL4030_RAMP_DELAY_2581MS 0x1C
217#define TWL4030_RAMP_EN 0x02
218
219/* PREDL_CTL (0x25) */
220#define TWL4030_PREDL_GAIN 0x30
221
222/* PREDR_CTL (0x26) */
223#define TWL4030_PREDR_GAIN 0x30
224
225/* PRECKL_CTL (0x27) */
226#define TWL4030_PRECKL_GAIN 0x30
227
228/* PRECKR_CTL (0x28) */
229#define TWL4030_PRECKR_GAIN 0x30
230
231/* HFL_CTL (0x29, 0x2A) Fields */
232#define TWL4030_HF_CTL_HB_EN 0x04
233#define TWL4030_HF_CTL_LOOP_EN 0x08
234#define TWL4030_HF_CTL_RAMP_EN 0x10
235#define TWL4030_HF_CTL_REF_EN 0x20
236
237/* APLL_CTL (0x3A) Fields */
238#define TWL4030_APLL_EN 0x10
239#define TWL4030_APLL_INFREQ 0x0F
240#define TWL4030_APLL_INFREQ_19200KHZ 0x05
241#define TWL4030_APLL_INFREQ_26000KHZ 0x06
242#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
243
244/* REG_MISC_SET_1 (0x3E) Fields */
245#define TWL4030_CLK64_EN 0x80
246#define TWL4030_SCRAMBLE_EN 0x40
247#define TWL4030_FMLOOP_EN 0x20
248#define TWL4030_SMOOTH_ANAVOL_EN 0x02
249#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
250
251/* VIBRA_CTL (0x45) */
252#define TWL4030_VIBRA_EN 0x01
253#define TWL4030_VIBRA_DIR 0x02
254#define TWL4030_VIBRA_AUDIO_SEL_L1 (0x00 << 2)
255#define TWL4030_VIBRA_AUDIO_SEL_R1 (0x01 << 2)
256#define TWL4030_VIBRA_AUDIO_SEL_L2 (0x02 << 2)
257#define TWL4030_VIBRA_AUDIO_SEL_R2 (0x03 << 2)
258#define TWL4030_VIBRA_SEL 0x10
259#define TWL4030_VIBRA_DIR_SEL 0x20
260
261/* TWL4030 codec resource IDs */
262enum twl4030_codec_res {
263 TWL4030_CODEC_RES_POWER = 0,
264 TWL4030_CODEC_RES_APLL,
265 TWL4030_CODEC_RES_MAX,
266};
267
268int twl4030_codec_disable_resource(enum twl4030_codec_res id);
269int twl4030_codec_enable_resource(enum twl4030_codec_res id);
270unsigned int twl4030_codec_get_mclk(void);
271
272#endif /* End of __TWL4030_CODEC_H__ */
diff --git a/include/linux/of.h b/include/linux/of.h
index 7be2d1043c16..e7facd8fbce8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -17,14 +17,117 @@
17 */ 17 */
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/bitops.h> 19#include <linux/bitops.h>
20#include <linux/kref.h>
20#include <linux/mod_devicetable.h> 21#include <linux/mod_devicetable.h>
21 22
23typedef u32 phandle;
24typedef u32 ihandle;
25
26struct property {
27 char *name;
28 int length;
29 void *value;
30 struct property *next;
31 unsigned long _flags;
32 unsigned int unique_id;
33};
34
35#if defined(CONFIG_SPARC)
36struct of_irq_controller;
37#endif
38
39struct device_node {
40 const char *name;
41 const char *type;
42 phandle node;
43#if !defined(CONFIG_SPARC)
44 phandle linux_phandle;
45#endif
46 char *full_name;
47
48 struct property *properties;
49 struct property *deadprops; /* removed properties */
50 struct device_node *parent;
51 struct device_node *child;
52 struct device_node *sibling;
53 struct device_node *next; /* next device of same type */
54 struct device_node *allnext; /* next in list of all nodes */
55 struct proc_dir_entry *pde; /* this node's proc directory */
56 struct kref kref;
57 unsigned long _flags;
58 void *data;
59#if defined(CONFIG_SPARC)
60 char *path_component_name;
61 unsigned int unique_id;
62 struct of_irq_controller *irq_trans;
63#endif
64};
65
66static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
67{
68 return test_bit(flag, &n->_flags);
69}
70
71static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
72{
73 set_bit(flag, &n->_flags);
74}
75
76static inline void
77set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
78{
79 dn->pde = de;
80}
81
82extern struct device_node *of_find_all_nodes(struct device_node *prev);
83
84#if defined(CONFIG_SPARC)
85/* Dummy ref counting routines - to be implemented later */
86static inline struct device_node *of_node_get(struct device_node *node)
87{
88 return node;
89}
90static inline void of_node_put(struct device_node *node)
91{
92}
93
94#else
95extern struct device_node *of_node_get(struct device_node *node);
96extern void of_node_put(struct device_node *node);
97#endif
98
99/*
100 * OF address retreival & translation
101 */
102
103/* Helper to read a big number; size is in cells (not bytes) */
104static inline u64 of_read_number(const u32 *cell, int size)
105{
106 u64 r = 0;
107 while (size--)
108 r = (r << 32) | *(cell++);
109 return r;
110}
111
112/* Like of_read_number, but we want an unsigned long result */
113#ifdef CONFIG_PPC32
114static inline unsigned long of_read_ulong(const u32 *cell, int size)
115{
116 return cell[size-1];
117}
118#else
119#define of_read_ulong(cell, size) of_read_number(cell, size)
120#endif
121
22#include <asm/prom.h> 122#include <asm/prom.h>
23 123
24/* flag descriptions */ 124/* flag descriptions */
25#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ 125#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
26#define OF_DETACHED 2 /* node has been detached from the device tree */ 126#define OF_DETACHED 2 /* node has been detached from the device tree */
27 127
128#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
129#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
130
28#define OF_BAD_ADDR ((u64)-1) 131#define OF_BAD_ADDR ((u64)-1)
29 132
30extern struct device_node *of_find_node_by_name(struct device_node *from, 133extern struct device_node *of_find_node_by_name(struct device_node *from,
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
new file mode 100644
index 000000000000..41d432b13553
--- /dev/null
+++ b/include/linux/of_fdt.h
@@ -0,0 +1,86 @@
1/*
2 * Definitions for working with the Flattened Device Tree data format
3 *
4 * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
5 * benh@kernel.crashing.org
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 */
11
12#ifndef _LINUX_OF_FDT_H
13#define _LINUX_OF_FDT_H
14
15#include <linux/types.h>
16#include <linux/init.h>
17
18/* Definitions used by the flattened device tree */
19#define OF_DT_HEADER 0xd00dfeed /* marker */
20#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
21#define OF_DT_END_NODE 0x2 /* End node */
22#define OF_DT_PROP 0x3 /* Property: name off, size,
23 * content */
24#define OF_DT_NOP 0x4 /* nop */
25#define OF_DT_END 0x9
26
27#define OF_DT_VERSION 0x10
28
29#ifndef __ASSEMBLY__
30/*
31 * This is what gets passed to the kernel by prom_init or kexec
32 *
33 * The dt struct contains the device tree structure, full pathes and
34 * property contents. The dt strings contain a separate block with just
35 * the strings for the property names, and is fully page aligned and
36 * self contained in a page, so that it can be kept around by the kernel,
37 * each property name appears only once in this page (cheap compression)
38 *
39 * the mem_rsvmap contains a map of reserved ranges of physical memory,
40 * passing it here instead of in the device-tree itself greatly simplifies
41 * the job of everybody. It's just a list of u64 pairs (base/size) that
42 * ends when size is 0
43 */
44struct boot_param_header {
45 u32 magic; /* magic word OF_DT_HEADER */
46 u32 totalsize; /* total size of DT block */
47 u32 off_dt_struct; /* offset to structure */
48 u32 off_dt_strings; /* offset to strings */
49 u32 off_mem_rsvmap; /* offset to memory reserve map */
50 u32 version; /* format version */
51 u32 last_comp_version; /* last compatible version */
52 /* version 2 fields below */
53 u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
54 /* version 3 fields below */
55 u32 dt_strings_size; /* size of the DT strings block */
56 /* version 17 fields below */
57 u32 dt_struct_size; /* size of the DT structure block */
58};
59
60/* For scanning the flat device-tree at boot time */
61extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
62 const char *uname, int depth,
63 void *data),
64 void *data);
65extern void __init *of_get_flat_dt_prop(unsigned long node, const char *name,
66 unsigned long *size);
67extern int __init of_flat_dt_is_compatible(unsigned long node,
68 const char *name);
69extern unsigned long __init of_get_flat_dt_root(void);
70
71/* Other Prototypes */
72extern void finish_device_tree(void);
73extern void unflatten_device_tree(void);
74extern void early_init_devtree(void *);
75extern int machine_is_compatible(const char *compat);
76extern void print_properties(struct device_node *node);
77extern int prom_n_intr_cells(struct device_node* np);
78extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
79extern int prom_add_property(struct device_node* np, struct property* prop);
80extern int prom_remove_property(struct device_node *np, struct property *prop);
81extern int prom_update_property(struct device_node *np,
82 struct property *newprop,
83 struct property *oldprop);
84
85#endif /* __ASSEMBLY__ */
86#endif /* _LINUX_OF_FDT_H */
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 7b7fbf433cff..e3fb25606706 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -106,6 +106,8 @@ enum perf_sw_ids {
106 PERF_COUNT_SW_CPU_MIGRATIONS = 4, 106 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
107 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, 107 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
108 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, 108 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
109 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
110 PERF_COUNT_SW_EMULATION_FAULTS = 8,
109 111
110 PERF_COUNT_SW_MAX, /* non-ABI */ 112 PERF_COUNT_SW_MAX, /* non-ABI */
111}; 113};
@@ -225,6 +227,7 @@ struct perf_counter_attr {
225#define PERF_COUNTER_IOC_RESET _IO ('$', 3) 227#define PERF_COUNTER_IOC_RESET _IO ('$', 3)
226#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) 228#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64)
227#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) 229#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5)
230#define PERF_COUNTER_IOC_SET_FILTER _IOW('$', 6, char *)
228 231
229enum perf_counter_ioc_flags { 232enum perf_counter_ioc_flags {
230 PERF_IOC_FLAG_GROUP = 1U << 0, 233 PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 9e7012689a84..43adbd7f0010 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -18,6 +18,10 @@
18#include <linux/ioctl.h> 18#include <linux/ioctl.h>
19#include <asm/byteorder.h> 19#include <asm/byteorder.h>
20 20
21#ifdef CONFIG_HAVE_HW_BREAKPOINT
22#include <asm/hw_breakpoint.h>
23#endif
24
21/* 25/*
22 * User-space ABI bits: 26 * User-space ABI bits:
23 */ 27 */
@@ -31,6 +35,7 @@ enum perf_type_id {
31 PERF_TYPE_TRACEPOINT = 2, 35 PERF_TYPE_TRACEPOINT = 2,
32 PERF_TYPE_HW_CACHE = 3, 36 PERF_TYPE_HW_CACHE = 3,
33 PERF_TYPE_RAW = 4, 37 PERF_TYPE_RAW = 4,
38 PERF_TYPE_BREAKPOINT = 5,
34 39
35 PERF_TYPE_MAX, /* non-ABI */ 40 PERF_TYPE_MAX, /* non-ABI */
36}; 41};
@@ -102,6 +107,8 @@ enum perf_sw_ids {
102 PERF_COUNT_SW_CPU_MIGRATIONS = 4, 107 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
103 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, 108 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
104 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, 109 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
110 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
111 PERF_COUNT_SW_EMULATION_FAULTS = 8,
105 112
106 PERF_COUNT_SW_MAX, /* non-ABI */ 113 PERF_COUNT_SW_MAX, /* non-ABI */
107}; 114};
@@ -207,6 +214,15 @@ struct perf_event_attr {
207 __u32 wakeup_events; /* wakeup every n events */ 214 __u32 wakeup_events; /* wakeup every n events */
208 __u32 wakeup_watermark; /* bytes before wakeup */ 215 __u32 wakeup_watermark; /* bytes before wakeup */
209 }; 216 };
217
218 union {
219 struct { /* Hardware breakpoint info */
220 __u64 bp_addr;
221 __u32 bp_type;
222 __u32 bp_len;
223 };
224 };
225
210 __u32 __reserved_2; 226 __u32 __reserved_2;
211 227
212 __u64 __reserved_3; 228 __u64 __reserved_3;
@@ -219,8 +235,9 @@ struct perf_event_attr {
219#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) 235#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
220#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) 236#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
221#define PERF_EVENT_IOC_RESET _IO ('$', 3) 237#define PERF_EVENT_IOC_RESET _IO ('$', 3)
222#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64) 238#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
223#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) 239#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
240#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
224 241
225enum perf_event_ioc_flags { 242enum perf_event_ioc_flags {
226 PERF_IOC_FLAG_GROUP = 1U << 0, 243 PERF_IOC_FLAG_GROUP = 1U << 0,
@@ -475,6 +492,11 @@ struct hw_perf_event {
475 s64 remaining; 492 s64 remaining;
476 struct hrtimer hrtimer; 493 struct hrtimer hrtimer;
477 }; 494 };
495#ifdef CONFIG_HAVE_HW_BREAKPOINT
496 union { /* breakpoint */
497 struct arch_hw_breakpoint info;
498 };
499#endif
478 }; 500 };
479 atomic64_t prev_count; 501 atomic64_t prev_count;
480 u64 sample_period; 502 u64 sample_period;
@@ -543,6 +565,10 @@ struct perf_pending_entry {
543 void (*func)(struct perf_pending_entry *); 565 void (*func)(struct perf_pending_entry *);
544}; 566};
545 567
568typedef void (*perf_callback_t)(struct perf_event *, void *);
569
570struct perf_sample_data;
571
546/** 572/**
547 * struct perf_event - performance event kernel representation: 573 * struct perf_event - performance event kernel representation:
548 */ 574 */
@@ -585,7 +611,7 @@ struct perf_event {
585 u64 tstamp_running; 611 u64 tstamp_running;
586 u64 tstamp_stopped; 612 u64 tstamp_stopped;
587 613
588 struct perf_event_attr attr; 614 struct perf_event_attr attr;
589 struct hw_perf_event hw; 615 struct hw_perf_event hw;
590 616
591 struct perf_event_context *ctx; 617 struct perf_event_context *ctx;
@@ -633,7 +659,20 @@ struct perf_event {
633 659
634 struct pid_namespace *ns; 660 struct pid_namespace *ns;
635 u64 id; 661 u64 id;
662
663 void (*overflow_handler)(struct perf_event *event,
664 int nmi, struct perf_sample_data *data,
665 struct pt_regs *regs);
666
667#ifdef CONFIG_EVENT_PROFILE
668 struct event_filter *filter;
636#endif 669#endif
670
671 perf_callback_t callback;
672
673 perf_callback_t event_callback;
674
675#endif /* CONFIG_PERF_EVENTS */
637}; 676};
638 677
639/** 678/**
@@ -706,7 +745,6 @@ struct perf_output_handle {
706 int nmi; 745 int nmi;
707 int sample; 746 int sample;
708 int locked; 747 int locked;
709 unsigned long flags;
710}; 748};
711 749
712#ifdef CONFIG_PERF_EVENTS 750#ifdef CONFIG_PERF_EVENTS
@@ -738,6 +776,14 @@ extern int hw_perf_group_sched_in(struct perf_event *group_leader,
738 struct perf_cpu_context *cpuctx, 776 struct perf_cpu_context *cpuctx,
739 struct perf_event_context *ctx, int cpu); 777 struct perf_event_context *ctx, int cpu);
740extern void perf_event_update_userpage(struct perf_event *event); 778extern void perf_event_update_userpage(struct perf_event *event);
779extern int perf_event_release_kernel(struct perf_event *event);
780extern struct perf_event *
781perf_event_create_kernel_counter(struct perf_event_attr *attr,
782 int cpu,
783 pid_t pid,
784 perf_callback_t callback);
785extern u64 perf_event_read_value(struct perf_event *event,
786 u64 *enabled, u64 *running);
741 787
742struct perf_sample_data { 788struct perf_sample_data {
743 u64 type; 789 u64 type;
@@ -814,6 +860,7 @@ extern int sysctl_perf_event_sample_rate;
814extern void perf_event_init(void); 860extern void perf_event_init(void);
815extern void perf_tp_event(int event_id, u64 addr, u64 count, 861extern void perf_tp_event(int event_id, u64 addr, u64 count,
816 void *record, int entry_size); 862 void *record, int entry_size);
863extern void perf_bp_event(struct perf_event *event, void *data);
817 864
818#ifndef perf_misc_flags 865#ifndef perf_misc_flags
819#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \ 866#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \
@@ -827,6 +874,8 @@ extern int perf_output_begin(struct perf_output_handle *handle,
827extern void perf_output_end(struct perf_output_handle *handle); 874extern void perf_output_end(struct perf_output_handle *handle);
828extern void perf_output_copy(struct perf_output_handle *handle, 875extern void perf_output_copy(struct perf_output_handle *handle,
829 const void *buf, unsigned int len); 876 const void *buf, unsigned int len);
877extern int perf_swevent_get_recursion_context(void);
878extern void perf_swevent_put_recursion_context(int rctx);
830#else 879#else
831static inline void 880static inline void
832perf_event_task_sched_in(struct task_struct *task, int cpu) { } 881perf_event_task_sched_in(struct task_struct *task, int cpu) { }
@@ -848,11 +897,15 @@ static inline int perf_event_task_enable(void) { return -EINVAL; }
848static inline void 897static inline void
849perf_sw_event(u32 event_id, u64 nr, int nmi, 898perf_sw_event(u32 event_id, u64 nr, int nmi,
850 struct pt_regs *regs, u64 addr) { } 899 struct pt_regs *regs, u64 addr) { }
900static inline void
901perf_bp_event(struct perf_event *event, void *data) { }
851 902
852static inline void perf_event_mmap(struct vm_area_struct *vma) { } 903static inline void perf_event_mmap(struct vm_area_struct *vma) { }
853static inline void perf_event_comm(struct task_struct *tsk) { } 904static inline void perf_event_comm(struct task_struct *tsk) { }
854static inline void perf_event_fork(struct task_struct *tsk) { } 905static inline void perf_event_fork(struct task_struct *tsk) { }
855static inline void perf_event_init(void) { } 906static inline void perf_event_init(void) { }
907static inline int perf_swevent_get_recursion_context(void) { return -1; }
908static inline void perf_swevent_put_recursion_context(int rctx) { }
856 909
857#endif 910#endif
858 911
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 72b1a10a59b6..2e681d9555bd 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -105,6 +105,11 @@ struct preempt_notifier;
105 * @sched_out: we've just been preempted 105 * @sched_out: we've just been preempted
106 * notifier: struct preempt_notifier for the task being preempted 106 * notifier: struct preempt_notifier for the task being preempted
107 * next: the task that's kicking us out 107 * next: the task that's kicking us out
108 *
109 * Please note that sched_in and out are called under different
110 * contexts. sched_out is called with rq lock held and irq disabled
111 * while sched_in is called without rq lock and irq enabled. This
112 * difference is intentional and depended upon by its users.
108 */ 113 */
109struct preempt_ops { 114struct preempt_ops {
110 void (*sched_in)(struct preempt_notifier *notifier, int cpu); 115 void (*sched_in)(struct preempt_notifier *notifier, int cpu);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 882dc48163b4..89115ec7d43f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -145,7 +145,6 @@ extern unsigned long this_cpu_load(void);
145 145
146 146
147extern void calc_global_load(void); 147extern void calc_global_load(void);
148extern u64 cpu_nr_migrations(int cpu);
149 148
150extern unsigned long get_parent_ip(unsigned long addr); 149extern unsigned long get_parent_ip(unsigned long addr);
151 150
@@ -171,8 +170,6 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
171} 170}
172#endif 171#endif
173 172
174extern unsigned long long time_sync_thresh;
175
176/* 173/*
177 * Task state bitmask. NOTE! These bits are also 174 * Task state bitmask. NOTE! These bits are also
178 * encoded in fs/proc/array.c: get_task_state(). 175 * encoded in fs/proc/array.c: get_task_state().
@@ -349,7 +346,6 @@ extern signed long schedule_timeout(signed long timeout);
349extern signed long schedule_timeout_interruptible(signed long timeout); 346extern signed long schedule_timeout_interruptible(signed long timeout);
350extern signed long schedule_timeout_killable(signed long timeout); 347extern signed long schedule_timeout_killable(signed long timeout);
351extern signed long schedule_timeout_uninterruptible(signed long timeout); 348extern signed long schedule_timeout_uninterruptible(signed long timeout);
352asmlinkage void __schedule(void);
353asmlinkage void schedule(void); 349asmlinkage void schedule(void);
354extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner); 350extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner);
355 351
@@ -628,6 +624,9 @@ struct signal_struct {
628 cputime_t utime, stime, cutime, cstime; 624 cputime_t utime, stime, cutime, cstime;
629 cputime_t gtime; 625 cputime_t gtime;
630 cputime_t cgtime; 626 cputime_t cgtime;
627#ifndef CONFIG_VIRT_CPU_ACCOUNTING
628 cputime_t prev_utime, prev_stime;
629#endif
631 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; 630 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
632 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; 631 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
633 unsigned long inblock, oublock, cinblock, coublock; 632 unsigned long inblock, oublock, cinblock, coublock;
@@ -1013,9 +1012,13 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd)
1013 return to_cpumask(sd->span); 1012 return to_cpumask(sd->span);
1014} 1013}
1015 1014
1016extern void partition_sched_domains(int ndoms_new, struct cpumask *doms_new, 1015extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
1017 struct sched_domain_attr *dattr_new); 1016 struct sched_domain_attr *dattr_new);
1018 1017
1018/* Allocate an array of sched domains, for partition_sched_domains(). */
1019cpumask_var_t *alloc_sched_domains(unsigned int ndoms);
1020void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms);
1021
1019/* Test a flag in parent sched domain */ 1022/* Test a flag in parent sched domain */
1020static inline int test_sd_parent(struct sched_domain *sd, int flag) 1023static inline int test_sd_parent(struct sched_domain *sd, int flag)
1021{ 1024{
@@ -1033,7 +1036,7 @@ unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu);
1033struct sched_domain_attr; 1036struct sched_domain_attr;
1034 1037
1035static inline void 1038static inline void
1036partition_sched_domains(int ndoms_new, struct cpumask *doms_new, 1039partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
1037 struct sched_domain_attr *dattr_new) 1040 struct sched_domain_attr *dattr_new)
1038{ 1041{
1039} 1042}
@@ -1331,7 +1334,9 @@ struct task_struct {
1331 1334
1332 cputime_t utime, stime, utimescaled, stimescaled; 1335 cputime_t utime, stime, utimescaled, stimescaled;
1333 cputime_t gtime; 1336 cputime_t gtime;
1337#ifndef CONFIG_VIRT_CPU_ACCOUNTING
1334 cputime_t prev_utime, prev_stime; 1338 cputime_t prev_utime, prev_stime;
1339#endif
1335 unsigned long nvcsw, nivcsw; /* context switch counts */ 1340 unsigned long nvcsw, nivcsw; /* context switch counts */
1336 struct timespec start_time; /* monotonic time */ 1341 struct timespec start_time; /* monotonic time */
1337 struct timespec real_start_time; /* boot based time */ 1342 struct timespec real_start_time; /* boot based time */
@@ -1720,9 +1725,8 @@ static inline void put_task_struct(struct task_struct *t)
1720 __put_task_struct(t); 1725 __put_task_struct(t);
1721} 1726}
1722 1727
1723extern cputime_t task_utime(struct task_struct *p); 1728extern void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
1724extern cputime_t task_stime(struct task_struct *p); 1729extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
1725extern cputime_t task_gtime(struct task_struct *p);
1726 1730
1727/* 1731/*
1728 * Per process flags 1732 * Per process flags
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index db532ce288be..8c3dd36fe91a 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -179,6 +179,9 @@
179/* BCM63xx family SoCs */ 179/* BCM63xx family SoCs */
180#define PORT_BCM63XX 89 180#define PORT_BCM63XX 89
181 181
182/* Aeroflex Gaisler GRLIB APBUART */
183#define PORT_APBUART 90
184
182#ifdef __KERNEL__ 185#ifdef __KERNEL__
183 186
184#include <linux/compiler.h> 187#include <linux/compiler.h>
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 714f063a3e6d..bc70c5810fec 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -100,37 +100,16 @@ struct perf_event_attr;
100#define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__) 100#define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__)
101 101
102#ifdef CONFIG_EVENT_PROFILE 102#ifdef CONFIG_EVENT_PROFILE
103#define TRACE_SYS_ENTER_PROFILE(sname) \
104static int prof_sysenter_enable_##sname(void) \
105{ \
106 return reg_prof_syscall_enter("sys"#sname); \
107} \
108 \
109static void prof_sysenter_disable_##sname(void) \
110{ \
111 unreg_prof_syscall_enter("sys"#sname); \
112}
113
114#define TRACE_SYS_EXIT_PROFILE(sname) \
115static int prof_sysexit_enable_##sname(void) \
116{ \
117 return reg_prof_syscall_exit("sys"#sname); \
118} \
119 \
120static void prof_sysexit_disable_##sname(void) \
121{ \
122 unreg_prof_syscall_exit("sys"#sname); \
123}
124 103
125#define TRACE_SYS_ENTER_PROFILE_INIT(sname) \ 104#define TRACE_SYS_ENTER_PROFILE_INIT(sname) \
126 .profile_count = ATOMIC_INIT(-1), \ 105 .profile_count = ATOMIC_INIT(-1), \
127 .profile_enable = prof_sysenter_enable_##sname, \ 106 .profile_enable = prof_sysenter_enable, \
128 .profile_disable = prof_sysenter_disable_##sname, 107 .profile_disable = prof_sysenter_disable,
129 108
130#define TRACE_SYS_EXIT_PROFILE_INIT(sname) \ 109#define TRACE_SYS_EXIT_PROFILE_INIT(sname) \
131 .profile_count = ATOMIC_INIT(-1), \ 110 .profile_count = ATOMIC_INIT(-1), \
132 .profile_enable = prof_sysexit_enable_##sname, \ 111 .profile_enable = prof_sysexit_enable, \
133 .profile_disable = prof_sysexit_disable_##sname, 112 .profile_disable = prof_sysexit_disable,
134#else 113#else
135#define TRACE_SYS_ENTER_PROFILE(sname) 114#define TRACE_SYS_ENTER_PROFILE(sname)
136#define TRACE_SYS_ENTER_PROFILE_INIT(sname) 115#define TRACE_SYS_ENTER_PROFILE_INIT(sname)
@@ -154,74 +133,46 @@ static void prof_sysexit_disable_##sname(void) \
154#define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__) 133#define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__)
155 134
156#define SYSCALL_TRACE_ENTER_EVENT(sname) \ 135#define SYSCALL_TRACE_ENTER_EVENT(sname) \
136 static const struct syscall_metadata __syscall_meta_##sname; \
157 static struct ftrace_event_call event_enter_##sname; \ 137 static struct ftrace_event_call event_enter_##sname; \
158 struct trace_event enter_syscall_print_##sname = { \ 138 static struct trace_event enter_syscall_print_##sname = { \
159 .trace = print_syscall_enter, \ 139 .trace = print_syscall_enter, \
160 }; \ 140 }; \
161 static int init_enter_##sname(void) \
162 { \
163 int num, id; \
164 num = syscall_name_to_nr("sys"#sname); \
165 if (num < 0) \
166 return -ENOSYS; \
167 id = register_ftrace_event(&enter_syscall_print_##sname);\
168 if (!id) \
169 return -ENODEV; \
170 event_enter_##sname.id = id; \
171 set_syscall_enter_id(num, id); \
172 INIT_LIST_HEAD(&event_enter_##sname.fields); \
173 return 0; \
174 } \
175 TRACE_SYS_ENTER_PROFILE(sname); \
176 static struct ftrace_event_call __used \ 141 static struct ftrace_event_call __used \
177 __attribute__((__aligned__(4))) \ 142 __attribute__((__aligned__(4))) \
178 __attribute__((section("_ftrace_events"))) \ 143 __attribute__((section("_ftrace_events"))) \
179 event_enter_##sname = { \ 144 event_enter_##sname = { \
180 .name = "sys_enter"#sname, \ 145 .name = "sys_enter"#sname, \
181 .system = "syscalls", \ 146 .system = "syscalls", \
182 .event = &event_syscall_enter, \ 147 .event = &enter_syscall_print_##sname, \
183 .raw_init = init_enter_##sname, \ 148 .raw_init = init_syscall_trace, \
184 .show_format = syscall_enter_format, \ 149 .show_format = syscall_enter_format, \
185 .define_fields = syscall_enter_define_fields, \ 150 .define_fields = syscall_enter_define_fields, \
186 .regfunc = reg_event_syscall_enter, \ 151 .regfunc = reg_event_syscall_enter, \
187 .unregfunc = unreg_event_syscall_enter, \ 152 .unregfunc = unreg_event_syscall_enter, \
188 .data = "sys"#sname, \ 153 .data = (void *)&__syscall_meta_##sname,\
189 TRACE_SYS_ENTER_PROFILE_INIT(sname) \ 154 TRACE_SYS_ENTER_PROFILE_INIT(sname) \
190 } 155 }
191 156
192#define SYSCALL_TRACE_EXIT_EVENT(sname) \ 157#define SYSCALL_TRACE_EXIT_EVENT(sname) \
158 static const struct syscall_metadata __syscall_meta_##sname; \
193 static struct ftrace_event_call event_exit_##sname; \ 159 static struct ftrace_event_call event_exit_##sname; \
194 struct trace_event exit_syscall_print_##sname = { \ 160 static struct trace_event exit_syscall_print_##sname = { \
195 .trace = print_syscall_exit, \ 161 .trace = print_syscall_exit, \
196 }; \ 162 }; \
197 static int init_exit_##sname(void) \
198 { \
199 int num, id; \
200 num = syscall_name_to_nr("sys"#sname); \
201 if (num < 0) \
202 return -ENOSYS; \
203 id = register_ftrace_event(&exit_syscall_print_##sname);\
204 if (!id) \
205 return -ENODEV; \
206 event_exit_##sname.id = id; \
207 set_syscall_exit_id(num, id); \
208 INIT_LIST_HEAD(&event_exit_##sname.fields); \
209 return 0; \
210 } \
211 TRACE_SYS_EXIT_PROFILE(sname); \
212 static struct ftrace_event_call __used \ 163 static struct ftrace_event_call __used \
213 __attribute__((__aligned__(4))) \ 164 __attribute__((__aligned__(4))) \
214 __attribute__((section("_ftrace_events"))) \ 165 __attribute__((section("_ftrace_events"))) \
215 event_exit_##sname = { \ 166 event_exit_##sname = { \
216 .name = "sys_exit"#sname, \ 167 .name = "sys_exit"#sname, \
217 .system = "syscalls", \ 168 .system = "syscalls", \
218 .event = &event_syscall_exit, \ 169 .event = &exit_syscall_print_##sname, \
219 .raw_init = init_exit_##sname, \ 170 .raw_init = init_syscall_trace, \
220 .show_format = syscall_exit_format, \ 171 .show_format = syscall_exit_format, \
221 .define_fields = syscall_exit_define_fields, \ 172 .define_fields = syscall_exit_define_fields, \
222 .regfunc = reg_event_syscall_exit, \ 173 .regfunc = reg_event_syscall_exit, \
223 .unregfunc = unreg_event_syscall_exit, \ 174 .unregfunc = unreg_event_syscall_exit, \
224 .data = "sys"#sname, \ 175 .data = (void *)&__syscall_meta_##sname,\
225 TRACE_SYS_EXIT_PROFILE_INIT(sname) \ 176 TRACE_SYS_EXIT_PROFILE_INIT(sname) \
226 } 177 }
227 178
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 9f047d73a216..56af3ca75e24 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -15,9 +15,6 @@
15 ** The kernel will then return -ENOTDIR to any application using 15 ** The kernel will then return -ENOTDIR to any application using
16 ** the old binary interface. 16 ** the old binary interface.
17 ** 17 **
18 ** For new interfaces unless you really need a binary number
19 ** please use CTL_UNNUMBERED.
20 **
21 **************************************************************** 18 ****************************************************************
22 **************************************************************** 19 ****************************************************************
23 */ 20 */
@@ -50,12 +47,6 @@ struct __sysctl_args {
50 47
51/* Top-level names: */ 48/* Top-level names: */
52 49
53/* For internal pattern-matching use only: */
54#ifdef __KERNEL__
55#define CTL_NONE 0
56#define CTL_UNNUMBERED CTL_NONE /* sysctl without a binary number */
57#endif
58
59enum 50enum
60{ 51{
61 CTL_KERN=1, /* General kernel info and control */ 52 CTL_KERN=1, /* General kernel info and control */
@@ -973,10 +964,6 @@ extern int sysctl_perm(struct ctl_table_root *root,
973 964
974typedef struct ctl_table ctl_table; 965typedef struct ctl_table ctl_table;
975 966
976typedef int ctl_handler (struct ctl_table *table,
977 void __user *oldval, size_t __user *oldlenp,
978 void __user *newval, size_t newlen);
979
980typedef int proc_handler (struct ctl_table *ctl, int write, 967typedef int proc_handler (struct ctl_table *ctl, int write,
981 void __user *buffer, size_t *lenp, loff_t *ppos); 968 void __user *buffer, size_t *lenp, loff_t *ppos);
982 969
@@ -997,21 +984,10 @@ extern int proc_doulongvec_minmax(struct ctl_table *, int,
997extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int, 984extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
998 void __user *, size_t *, loff_t *); 985 void __user *, size_t *, loff_t *);
999 986
1000extern int do_sysctl (int __user *name, int nlen,
1001 void __user *oldval, size_t __user *oldlenp,
1002 void __user *newval, size_t newlen);
1003
1004extern ctl_handler sysctl_data;
1005extern ctl_handler sysctl_string;
1006extern ctl_handler sysctl_intvec;
1007extern ctl_handler sysctl_jiffies;
1008extern ctl_handler sysctl_ms_jiffies;
1009
1010
1011/* 987/*
1012 * Register a set of sysctl names by calling register_sysctl_table 988 * Register a set of sysctl names by calling register_sysctl_table
1013 * with an initialised array of struct ctl_table's. An entry with zero 989 * with an initialised array of struct ctl_table's. An entry with
1014 * ctl_name and NULL procname terminates the table. table->de will be 990 * NULL procname terminates the table. table->de will be
1015 * set up by the registration and need not be initialised in advance. 991 * set up by the registration and need not be initialised in advance.
1016 * 992 *
1017 * sysctl names can be mirrored automatically under /proc/sys. The 993 * sysctl names can be mirrored automatically under /proc/sys. The
@@ -1024,24 +1000,11 @@ extern ctl_handler sysctl_ms_jiffies;
1024 * under /proc; non-leaf nodes will be represented by directories. A 1000 * under /proc; non-leaf nodes will be represented by directories. A
1025 * null procname disables /proc mirroring at this node. 1001 * null procname disables /proc mirroring at this node.
1026 * 1002 *
1027 * sysctl entries with a zero ctl_name will not be available through
1028 * the binary sysctl interface.
1029 *
1030 * sysctl(2) can automatically manage read and write requests through 1003 * sysctl(2) can automatically manage read and write requests through
1031 * the sysctl table. The data and maxlen fields of the ctl_table 1004 * the sysctl table. The data and maxlen fields of the ctl_table
1032 * struct enable minimal validation of the values being written to be 1005 * struct enable minimal validation of the values being written to be
1033 * performed, and the mode field allows minimal authentication. 1006 * performed, and the mode field allows minimal authentication.
1034 * 1007 *
1035 * More sophisticated management can be enabled by the provision of a
1036 * strategy routine with the table entry. This will be called before
1037 * any automatic read or write of the data is performed.
1038 *
1039 * The strategy routine may return:
1040 * <0: Error occurred (error is passed to user process)
1041 * 0: OK - proceed with automatic read or write.
1042 * >0: OK - read or write has been done by the strategy routine, so
1043 * return immediately.
1044 *
1045 * There must be a proc_handler routine for any terminal nodes 1008 * There must be a proc_handler routine for any terminal nodes
1046 * mirrored under /proc/sys (non-terminals are handled by a built-in 1009 * mirrored under /proc/sys (non-terminals are handled by a built-in
1047 * directory handler). Several default handlers are available to 1010 * directory handler). Several default handlers are available to
@@ -1051,7 +1014,6 @@ extern ctl_handler sysctl_ms_jiffies;
1051/* A sysctl table is an array of struct ctl_table: */ 1014/* A sysctl table is an array of struct ctl_table: */
1052struct ctl_table 1015struct ctl_table
1053{ 1016{
1054 int ctl_name; /* Binary ID */
1055 const char *procname; /* Text ID for /proc/sys, or zero */ 1017 const char *procname; /* Text ID for /proc/sys, or zero */
1056 void *data; 1018 void *data;
1057 int maxlen; 1019 int maxlen;
@@ -1059,7 +1021,6 @@ struct ctl_table
1059 struct ctl_table *child; 1021 struct ctl_table *child;
1060 struct ctl_table *parent; /* Automatically set */ 1022 struct ctl_table *parent; /* Automatically set */
1061 proc_handler *proc_handler; /* Callback for text formatting */ 1023 proc_handler *proc_handler; /* Callback for text formatting */
1062 ctl_handler *strategy; /* Callback function for all r/w */
1063 void *extra1; 1024 void *extra1;
1064 void *extra2; 1025 void *extra2;
1065}; 1026};
@@ -1093,7 +1054,6 @@ struct ctl_table_header
1093/* struct ctl_path describes where in the hierarchy a table is added */ 1054/* struct ctl_path describes where in the hierarchy a table is added */
1094struct ctl_path { 1055struct ctl_path {
1095 const char *procname; 1056 const char *procname;
1096 int ctl_name;
1097}; 1057};
1098 1058
1099void register_sysctl_root(struct ctl_table_root *root); 1059void register_sysctl_root(struct ctl_table_root *root);
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 2aac8a83e89b..f59604ed0ec6 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -280,6 +280,12 @@ static inline void tracepoint_synchronize_unregister(void)
280 * TRACE_EVENT_FN to perform any (un)registration work. 280 * TRACE_EVENT_FN to perform any (un)registration work.
281 */ 281 */
282 282
283#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print)
284#define DEFINE_EVENT(template, name, proto, args) \
285 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
286#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
287 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
288
283#define TRACE_EVENT(name, proto, args, struct, assign, print) \ 289#define TRACE_EVENT(name, proto, args, struct, assign, print) \
284 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) 290 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
285#define TRACE_EVENT_FN(name, proto, args, struct, \ 291#define TRACE_EVENT_FN(name, proto, args, struct, \
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index 28966cae3fd7..511a459ec10f 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -75,7 +75,6 @@ struct dn_dev_parms {
75 unsigned long t3; /* Default value of t3 */ 75 unsigned long t3; /* Default value of t3 */
76 int priority; /* Priority to be a router */ 76 int priority; /* Priority to be a router */
77 char *name; /* Name for sysctl */ 77 char *name; /* Name for sysctl */
78 int ctl_name; /* Index for sysctl */
79 int (*up)(struct net_device *); 78 int (*up)(struct net_device *);
80 void (*down)(struct net_device *); 79 void (*down)(struct net_device *);
81 void (*timer3)(struct net_device *, struct dn_ifaddr *ifa); 80 void (*timer3)(struct net_device *, struct dn_ifaddr *ifa);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index db8e96dd114e..0302f31a2fb7 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -258,8 +258,7 @@ extern int neigh_sysctl_register(struct net_device *dev,
258 struct neigh_parms *p, 258 struct neigh_parms *p,
259 int p_id, int pdev_id, 259 int p_id, int pdev_id,
260 char *p_name, 260 char *p_name,
261 proc_handler *proc_handler, 261 proc_handler *proc_handler);
262 ctl_handler *strategy);
263extern void neigh_sysctl_unregister(struct neigh_parms *p); 262extern void neigh_sysctl_unregister(struct neigh_parms *p);
264 263
265static inline void __neigh_parms_put(struct neigh_parms *parms) 264static inline void __neigh_parms_put(struct neigh_parms *parms)
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index fd054a344324..e9dd9369ecb9 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -2,7 +2,6 @@ header-y += asound_fm.h
2header-y += hdsp.h 2header-y += hdsp.h
3header-y += hdspm.h 3header-y += hdspm.h
4header-y += sfnt_info.h 4header-y += sfnt_info.h
5header-y += sscape_ioctl.h
6 5
7unifdef-y += asequencer.h 6unifdef-y += asequencer.h
8unifdef-y += asound.h 7unifdef-y += asound.h
diff --git a/sound/isa/opti9xx/miro.h b/include/sound/aci.h
index 6e1385b8e07e..ee639d355ef0 100644
--- a/sound/isa/opti9xx/miro.h
+++ b/include/sound/aci.h
@@ -1,5 +1,5 @@
1#ifndef _MIRO_H_ 1#ifndef _ACI_H_
2#define _MIRO_H_ 2#define _ACI_H_
3 3
4#define ACI_REG_COMMAND 0 /* write register offset */ 4#define ACI_REG_COMMAND 0 /* write register offset */
5#define ACI_REG_STATUS 1 /* read register offset */ 5#define ACI_REG_STATUS 1 /* read register offset */
@@ -70,4 +70,21 @@
70#define ACI_SET_EQ6 0x45 70#define ACI_SET_EQ6 0x45
71#define ACI_SET_EQ7 0x46 /* ... to Treble */ 71#define ACI_SET_EQ7 0x46 /* ... to Treble */
72 72
73#endif /* _MIRO_H_ */ 73struct snd_miro_aci {
74 unsigned long aci_port;
75 int aci_vendor;
76 int aci_product;
77 int aci_version;
78 int aci_amp;
79 int aci_preamp;
80 int aci_solomode;
81
82 struct mutex aci_mutex;
83};
84
85int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3);
86
87struct snd_miro_aci *snd_aci_get_aci(void);
88
89#endif /* _ACI_H_ */
90
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h
new file mode 100644
index 000000000000..8988edae1609
--- /dev/null
+++ b/include/sound/ak4113.h
@@ -0,0 +1,321 @@
1#ifndef __SOUND_AK4113_H
2#define __SOUND_AK4113_H
3
4/*
5 * Routines for Asahi Kasei AK4113
6 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
7 * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>,
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26/* AK4113 registers */
27/* power down */
28#define AK4113_REG_PWRDN 0x00
29/* format control */
30#define AK4113_REG_FORMAT 0x01
31/* input/output control */
32#define AK4113_REG_IO0 0x02
33/* input/output control */
34#define AK4113_REG_IO1 0x03
35/* interrupt0 mask */
36#define AK4113_REG_INT0_MASK 0x04
37/* interrupt1 mask */
38#define AK4113_REG_INT1_MASK 0x05
39/* DAT mask & DTS select */
40#define AK4113_REG_DATDTS 0x06
41/* receiver status 0 */
42#define AK4113_REG_RCS0 0x07
43/* receiver status 1 */
44#define AK4113_REG_RCS1 0x08
45/* receiver status 2 */
46#define AK4113_REG_RCS2 0x09
47/* RX channel status byte 0 */
48#define AK4113_REG_RXCSB0 0x0a
49/* RX channel status byte 1 */
50#define AK4113_REG_RXCSB1 0x0b
51/* RX channel status byte 2 */
52#define AK4113_REG_RXCSB2 0x0c
53/* RX channel status byte 3 */
54#define AK4113_REG_RXCSB3 0x0d
55/* RX channel status byte 4 */
56#define AK4113_REG_RXCSB4 0x0e
57/* burst preamble Pc byte 0 */
58#define AK4113_REG_Pc0 0x0f
59/* burst preamble Pc byte 1 */
60#define AK4113_REG_Pc1 0x10
61/* burst preamble Pd byte 0 */
62#define AK4113_REG_Pd0 0x11
63/* burst preamble Pd byte 1 */
64#define AK4113_REG_Pd1 0x12
65/* Q-subcode address + control */
66#define AK4113_REG_QSUB_ADDR 0x13
67/* Q-subcode track */
68#define AK4113_REG_QSUB_TRACK 0x14
69/* Q-subcode index */
70#define AK4113_REG_QSUB_INDEX 0x15
71/* Q-subcode minute */
72#define AK4113_REG_QSUB_MINUTE 0x16
73/* Q-subcode second */
74#define AK4113_REG_QSUB_SECOND 0x17
75/* Q-subcode frame */
76#define AK4113_REG_QSUB_FRAME 0x18
77/* Q-subcode zero */
78#define AK4113_REG_QSUB_ZERO 0x19
79/* Q-subcode absolute minute */
80#define AK4113_REG_QSUB_ABSMIN 0x1a
81/* Q-subcode absolute second */
82#define AK4113_REG_QSUB_ABSSEC 0x1b
83/* Q-subcode absolute frame */
84#define AK4113_REG_QSUB_ABSFRM 0x1c
85
86/* sizes */
87#define AK4113_REG_RXCSB_SIZE ((AK4113_REG_RXCSB4-AK4113_REG_RXCSB0)+1)
88#define AK4113_REG_QSUB_SIZE ((AK4113_REG_QSUB_ABSFRM-AK4113_REG_QSUB_ADDR)\
89 +1)
90
91#define AK4113_WRITABLE_REGS (AK4113_REG_DATDTS + 1)
92
93/* AK4113_REG_PWRDN bits */
94/* Channel Status Select */
95#define AK4113_CS12 (1<<7)
96/* Block Start & C/U Output Mode */
97#define AK4113_BCU (1<<6)
98/* Master Clock Operation Select */
99#define AK4113_CM1 (1<<5)
100/* Master Clock Operation Select */
101#define AK4113_CM0 (1<<4)
102/* Master Clock Frequency Select */
103#define AK4113_OCKS1 (1<<3)
104/* Master Clock Frequency Select */
105#define AK4113_OCKS0 (1<<2)
106/* 0 = power down, 1 = normal operation */
107#define AK4113_PWN (1<<1)
108/* 0 = reset & initialize (except thisregister), 1 = normal operation */
109#define AK4113_RST (1<<0)
110
111/* AK4113_REQ_FORMAT bits */
112/* V/TX Output select: 0 = Validity Flag Output, 1 = TX */
113#define AK4113_VTX (1<<7)
114/* Audio Data Control */
115#define AK4113_DIF2 (1<<6)
116/* Audio Data Control */
117#define AK4113_DIF1 (1<<5)
118/* Audio Data Control */
119#define AK4113_DIF0 (1<<4)
120/* Deemphasis Autodetect Enable (1 = enable) */
121#define AK4113_DEAU (1<<3)
122/* 32kHz-48kHz Deemphasis Control */
123#define AK4113_DEM1 (1<<2)
124/* 32kHz-48kHz Deemphasis Control */
125#define AK4113_DEM0 (1<<1)
126#define AK4113_DEM_OFF (AK4113_DEM0)
127#define AK4113_DEM_44KHZ (0)
128#define AK4113_DEM_48KHZ (AK4113_DEM1)
129#define AK4113_DEM_32KHZ (AK4113_DEM0|AK4113_DEM1)
130/* STDO: 16-bit, right justified */
131#define AK4113_DIF_16R (0)
132/* STDO: 18-bit, right justified */
133#define AK4113_DIF_18R (AK4113_DIF0)
134/* STDO: 20-bit, right justified */
135#define AK4113_DIF_20R (AK4113_DIF1)
136/* STDO: 24-bit, right justified */
137#define AK4113_DIF_24R (AK4113_DIF1|AK4113_DIF0)
138/* STDO: 24-bit, left justified */
139#define AK4113_DIF_24L (AK4113_DIF2)
140/* STDO: I2S */
141#define AK4113_DIF_24I2S (AK4113_DIF2|AK4113_DIF0)
142/* STDO: 24-bit, left justified; LRCLK, BICK = Input */
143#define AK4113_DIF_I24L (AK4113_DIF2|AK4113_DIF1)
144/* STDO: I2S; LRCLK, BICK = Input */
145#define AK4113_DIF_I24I2S (AK4113_DIF2|AK4113_DIF1|AK4113_DIF0)
146
147/* AK4113_REG_IO0 */
148/* XTL1=0,XTL0=0 -> 11.2896Mhz; XTL1=0,XTL0=1 -> 12.288Mhz */
149#define AK4113_XTL1 (1<<6)
150/* XTL1=1,XTL0=0 -> 24.576Mhz; XTL1=1,XTL0=1 -> use channel status */
151#define AK4113_XTL0 (1<<5)
152/* Block Start Signal Output: 0 = U-bit, 1 = C-bit (req. BCU = 1) */
153#define AK4113_UCE (1<<4)
154/* TX Output Enable (1 = enable) */
155#define AK4113_TXE (1<<3)
156/* Output Through Data Selector for TX pin */
157#define AK4113_OPS2 (1<<2)
158/* Output Through Data Selector for TX pin */
159#define AK4113_OPS1 (1<<1)
160/* Output Through Data Selector for TX pin */
161#define AK4113_OPS0 (1<<0)
162/* 11.2896 MHz ref. Xtal freq. */
163#define AK4113_XTL_11_2896M (0)
164/* 12.288 MHz ref. Xtal freq. */
165#define AK4113_XTL_12_288M (AK4113_XTL0)
166/* 24.576 MHz ref. Xtal freq. */
167#define AK4113_XTL_24_576M (AK4113_XTL1)
168
169/* AK4113_REG_IO1 */
170/* Interrupt 0 pin Hold */
171#define AK4113_EFH1 (1<<7)
172/* Interrupt 0 pin Hold */
173#define AK4113_EFH0 (1<<6)
174#define AK4113_EFH_512LRCLK (0)
175#define AK4113_EFH_1024LRCLK (AK4113_EFH0)
176#define AK4113_EFH_2048LRCLK (AK4113_EFH1)
177#define AK4113_EFH_4096LRCLK (AK4113_EFH1|AK4113_EFH0)
178/* PLL Lock Time: 0 = 384/fs, 1 = 1/fs */
179#define AK4113_FAST (1<<5)
180/* MCKO2 Output Select: 0 = CMx/OCKSx, 1 = Xtal */
181#define AK4113_XMCK (1<<4)
182/* MCKO2 Output Freq. Select: 0 = x1, 1 = x0.5 (req. XMCK = 1) */
183#define AK4113_DIV (1<<3)
184/* Input Recovery Data Select */
185#define AK4113_IPS2 (1<<2)
186/* Input Recovery Data Select */
187#define AK4113_IPS1 (1<<1)
188/* Input Recovery Data Select */
189#define AK4113_IPS0 (1<<0)
190#define AK4113_IPS(x) ((x)&7)
191
192/* AK4113_REG_INT0_MASK && AK4113_REG_INT1_MASK*/
193/* mask enable for QINT bit */
194#define AK4113_MQI (1<<7)
195/* mask enable for AUTO bit */
196#define AK4113_MAUT (1<<6)
197/* mask enable for CINT bit */
198#define AK4113_MCIT (1<<5)
199/* mask enable for UNLOCK bit */
200#define AK4113_MULK (1<<4)
201/* mask enable for V bit */
202#define AK4113_V (1<<3)
203/* mask enable for STC bit */
204#define AK4113_STC (1<<2)
205/* mask enable for AUDN bit */
206#define AK4113_MAN (1<<1)
207/* mask enable for PAR bit */
208#define AK4113_MPR (1<<0)
209
210/* AK4113_REG_DATDTS */
211/* DAT Start ID Counter */
212#define AK4113_DCNT (1<<4)
213/* DTS-CD 16-bit Sync Word Detect */
214#define AK4113_DTS16 (1<<3)
215/* DTS-CD 14-bit Sync Word Detect */
216#define AK4113_DTS14 (1<<2)
217/* mask enable for DAT bit (if 1, no INT1 effect */
218#define AK4113_MDAT1 (1<<1)
219/* mask enable for DAT bit (if 1, no INT0 effect */
220#define AK4113_MDAT0 (1<<0)
221
222/* AK4113_REG_RCS0 */
223/* Q-subcode buffer interrupt, 0 = no change, 1 = changed */
224#define AK4113_QINT (1<<7)
225/* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */
226#define AK4113_AUTO (1<<6)
227/* channel status buffer interrupt, 0 = no change, 1 = change */
228#define AK4113_CINT (1<<5)
229/* PLL lock status, 0 = lock, 1 = unlock */
230#define AK4113_UNLCK (1<<4)
231/* Validity bit, 0 = valid, 1 = invalid */
232#define AK4113_V (1<<3)
233/* sampling frequency or Pre-emphasis change, 0 = no detect, 1 = detect */
234#define AK4113_STC (1<<2)
235/* audio bit output, 0 = audio, 1 = non-audio */
236#define AK4113_AUDION (1<<1)
237/* parity error or biphase error status, 0 = no error, 1 = error */
238#define AK4113_PAR (1<<0)
239
240/* AK4113_REG_RCS1 */
241/* sampling frequency detection */
242#define AK4113_FS3 (1<<7)
243#define AK4113_FS2 (1<<6)
244#define AK4113_FS1 (1<<5)
245#define AK4113_FS0 (1<<4)
246/* Pre-emphasis detect, 0 = OFF, 1 = ON */
247#define AK4113_PEM (1<<3)
248/* DAT Start ID Detect, 0 = no detect, 1 = detect */
249#define AK4113_DAT (1<<2)
250/* DTS-CD bit audio stream detect, 0 = no detect, 1 = detect */
251#define AK4113_DTSCD (1<<1)
252/* Non-PCM bit stream detection, 0 = no detect, 1 = detect */
253#define AK4113_NPCM (1<<0)
254#define AK4113_FS_8000HZ (AK4113_FS3|AK4113_FS0)
255#define AK4113_FS_11025HZ (AK4113_FS2|AK4113_FS0)
256#define AK4113_FS_16000HZ (AK4113_FS2|AK4113_FS1|AK4113_FS0)
257#define AK4113_FS_22050HZ (AK4113_FS2)
258#define AK4113_FS_24000HZ (AK4113_FS2|AK4113_FS1)
259#define AK4113_FS_32000HZ (AK4113_FS1|AK4113_FS0)
260#define AK4113_FS_44100HZ (0)
261#define AK4113_FS_48000HZ (AK4113_FS1)
262#define AK4113_FS_64000HZ (AK4113_FS3|AK4113_FS1|AK4113_FS0)
263#define AK4113_FS_88200HZ (AK4113_FS3)
264#define AK4113_FS_96000HZ (AK4113_FS3|AK4113_FS1)
265#define AK4113_FS_176400HZ (AK4113_FS3|AK4113_FS2)
266#define AK4113_FS_192000HZ (AK4113_FS3|AK4113_FS2|AK4113_FS1)
267
268/* AK4113_REG_RCS2 */
269/* CRC for Q-subcode, 0 = no error, 1 = error */
270#define AK4113_QCRC (1<<1)
271/* CRC for channel status, 0 = no error, 1 = error */
272#define AK4113_CCRC (1<<0)
273
274/* flags for snd_ak4113_check_rate_and_errors() */
275#define AK4113_CHECK_NO_STAT (1<<0) /* no statistics */
276#define AK4113_CHECK_NO_RATE (1<<1) /* no rate check */
277
278#define AK4113_CONTROLS 13
279
280typedef void (ak4113_write_t)(void *private_data, unsigned char addr,
281 unsigned char data);
282typedef unsigned char (ak4113_read_t)(void *private_data, unsigned char addr);
283
284struct ak4113 {
285 struct snd_card *card;
286 ak4113_write_t *write;
287 ak4113_read_t *read;
288 void *private_data;
289 unsigned int init:1;
290 spinlock_t lock;
291 unsigned char regmap[AK4113_WRITABLE_REGS];
292 struct snd_kcontrol *kctls[AK4113_CONTROLS];
293 struct snd_pcm_substream *substream;
294 unsigned long parity_errors;
295 unsigned long v_bit_errors;
296 unsigned long qcrc_errors;
297 unsigned long ccrc_errors;
298 unsigned char rcs0;
299 unsigned char rcs1;
300 unsigned char rcs2;
301 struct delayed_work work;
302 unsigned int check_flags;
303 void *change_callback_private;
304 void (*change_callback)(struct ak4113 *ak4113, unsigned char c0,
305 unsigned char c1);
306};
307
308int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
309 ak4113_write_t *write,
310 const unsigned char pgm[AK4113_WRITABLE_REGS],
311 void *private_data, struct ak4113 **r_ak4113);
312void snd_ak4113_reg_write(struct ak4113 *ak4113, unsigned char reg,
313 unsigned char mask, unsigned char val);
314void snd_ak4113_reinit(struct ak4113 *ak4113);
315int snd_ak4113_build(struct ak4113 *ak4113,
316 struct snd_pcm_substream *capture_substream);
317int snd_ak4113_external_rate(struct ak4113 *ak4113);
318int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags);
319
320#endif /* __SOUND_AK4113_H */
321
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index d293d36a66b8..3ce69fd92523 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -95,13 +95,13 @@
95 95
96/* AK4114_REG_IO0 */ 96/* AK4114_REG_IO0 */
97#define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */ 97#define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */
98#define AK4114_OPS12 (1<<2) /* Output Though Data Selector for TX1 pin */ 98#define AK4114_OPS12 (1<<6) /* Output Data Selector for TX1 pin */
99#define AK4114_OPS11 (1<<1) /* Output Though Data Selector for TX1 pin */ 99#define AK4114_OPS11 (1<<5) /* Output Data Selector for TX1 pin */
100#define AK4114_OPS10 (1<<0) /* Output Though Data Selector for TX1 pin */ 100#define AK4114_OPS10 (1<<4) /* Output Data Selector for TX1 pin */
101#define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */ 101#define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */
102#define AK4114_OPS02 (1<<2) /* Output Though Data Selector for TX0 pin */ 102#define AK4114_OPS02 (1<<2) /* Output Data Selector for TX0 pin */
103#define AK4114_OPS01 (1<<1) /* Output Though Data Selector for TX0 pin */ 103#define AK4114_OPS01 (1<<1) /* Output Data Selector for TX0 pin */
104#define AK4114_OPS00 (1<<0) /* Output Though Data Selector for TX0 pin */ 104#define AK4114_OPS00 (1<<0) /* Output Data Selector for TX0 pin */
105 105
106/* AK4114_REG_IO1 */ 106/* AK4114_REG_IO1 */
107#define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */ 107#define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 891cf1aea8b1..030b87c2f6d4 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -68,7 +68,7 @@ struct snd_akm4xxx {
68 enum { 68 enum {
69 SND_AK4524, SND_AK4528, SND_AK4529, 69 SND_AK4524, SND_AK4528, SND_AK4529,
70 SND_AK4355, SND_AK4358, SND_AK4381, 70 SND_AK4355, SND_AK4358, SND_AK4381,
71 SND_AK5365 71 SND_AK5365, SND_AK4620,
72 } type; 72 } type;
73 73
74 /* (array) information of combined codecs */ 74 /* (array) information of combined codecs */
@@ -76,6 +76,9 @@ struct snd_akm4xxx {
76 const struct snd_akm4xxx_adc_channel *adc_info; 76 const struct snd_akm4xxx_adc_channel *adc_info;
77 77
78 struct snd_ak4xxx_ops ops; 78 struct snd_ak4xxx_ops ops;
79 unsigned int num_chips;
80 unsigned int total_regs;
81 const char *name;
79}; 82};
80 83
81void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, 84void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg,
diff --git a/include/sound/control.h b/include/sound/control.h
index ef96f07aa03b..112374dc0c58 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -56,7 +56,6 @@ struct snd_kcontrol_new {
56 56
57struct snd_kcontrol_volatile { 57struct snd_kcontrol_volatile {
58 struct snd_ctl_file *owner; /* locked */ 58 struct snd_ctl_file *owner; /* locked */
59 pid_t owner_pid;
60 unsigned int access; /* access rights */ 59 unsigned int access; /* access rights */
61}; 60};
62 61
@@ -87,10 +86,12 @@ struct snd_kctl_event {
87 86
88#define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list) 87#define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list)
89 88
89struct pid;
90
90struct snd_ctl_file { 91struct snd_ctl_file {
91 struct list_head list; /* list of all control files */ 92 struct list_head list; /* list of all control files */
92 struct snd_card *card; 93 struct snd_card *card;
93 pid_t pid; 94 struct pid *pid;
94 int prefer_pcm_subdevice; 95 int prefer_pcm_subdevice;
95 int prefer_rawmidi_subdevice; 96 int prefer_rawmidi_subdevice;
96 wait_queue_head_t change_sleep; 97 wait_queue_head_t change_sleep;
diff --git a/include/sound/cs4231-regs.h b/include/sound/cs4231-regs.h
index 92647532c454..66d28c2cb53d 100644
--- a/include/sound/cs4231-regs.h
+++ b/include/sound/cs4231-regs.h
@@ -70,7 +70,6 @@
70#define AD1845_PWR_DOWN 0x1b /* power down control */ 70#define AD1845_PWR_DOWN 0x1b /* power down control */
71#define CS4235_LEFT_MASTER 0x1b /* left master output control */ 71#define CS4235_LEFT_MASTER 0x1b /* left master output control */
72#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */ 72#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
73#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
74#define AD1845_CLOCK 0x1d /* crystal clock select and total power down */ 73#define AD1845_CLOCK 0x1d /* crystal clock select and total power down */
75#define CS4235_RIGHT_MASTER 0x1d /* right master output control */ 74#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
76#define CS4231_REC_UPR_CNT 0x1e /* record upper count */ 75#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index de6d981de5d6..c83a4a79f16b 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -348,6 +348,8 @@ struct snd_pcm_group { /* keep linked substreams */
348 int count; 348 int count;
349}; 349};
350 350
351struct pid;
352
351struct snd_pcm_substream { 353struct snd_pcm_substream {
352 struct snd_pcm *pcm; 354 struct snd_pcm *pcm;
353 struct snd_pcm_str *pstr; 355 struct snd_pcm_str *pstr;
@@ -379,6 +381,7 @@ struct snd_pcm_substream {
379 atomic_t mmap_count; 381 atomic_t mmap_count;
380 unsigned int f_flags; 382 unsigned int f_flags;
381 void (*pcm_release)(struct snd_pcm_substream *); 383 void (*pcm_release)(struct snd_pcm_substream *);
384 struct pid *pid;
382#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) 385#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
383 /* -- OSS things -- */ 386 /* -- OSS things -- */
384 struct snd_pcm_oss_substream oss; 387 struct snd_pcm_oss_substream oss;
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index c23c26585700..2480e7d10dcf 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -46,6 +46,7 @@
46struct snd_rawmidi; 46struct snd_rawmidi;
47struct snd_rawmidi_substream; 47struct snd_rawmidi_substream;
48struct snd_seq_port_info; 48struct snd_seq_port_info;
49struct pid;
49 50
50struct snd_rawmidi_ops { 51struct snd_rawmidi_ops {
51 int (*open) (struct snd_rawmidi_substream * substream); 52 int (*open) (struct snd_rawmidi_substream * substream);
@@ -97,6 +98,7 @@ struct snd_rawmidi_substream {
97 struct snd_rawmidi_str *pstr; 98 struct snd_rawmidi_str *pstr;
98 char name[32]; 99 char name[32];
99 struct snd_rawmidi_runtime *runtime; 100 struct snd_rawmidi_runtime *runtime;
101 struct pid *pid;
100 /* hardware layer */ 102 /* hardware layer */
101 struct snd_rawmidi_ops *ops; 103 struct snd_rawmidi_ops *ops;
102}; 104};
diff --git a/include/sound/sh_dac_audio.h b/include/sound/sh_dac_audio.h
new file mode 100644
index 000000000000..f5deaf1ddb9f
--- /dev/null
+++ b/include/sound/sh_dac_audio.h
@@ -0,0 +1,21 @@
1/*
2 * SH_DAC specific configuration, for the dac_audio platform_device
3 *
4 * Copyright (C) 2009 Rafael Ignacio Zurita <rizurita@yahoo.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11#ifndef __INCLUDE_SH_DAC_AUDIO_H
12#define __INCLUDE_SH_DAC_AUDIO_H
13
14struct dac_audio_pdata {
15 int buffer_size;
16 int channel;
17 void (*start)(struct dac_audio_pdata *pd);
18 void (*stop)(struct dac_audio_pdata *pd);
19};
20
21#endif /* __INCLUDE_SH_DAC_AUDIO_H */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 97ca9af414dc..ca24e7f7a3f5 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -30,6 +30,7 @@ struct snd_pcm_substream;
30#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */ 30#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */
31#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */ 31#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */
32#define SND_SOC_DAIFMT_AC97 5 /* AC97 */ 32#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
33#define SND_SOC_DAIFMT_PDM 6 /* Pulse density modulation */
33 34
34/* left and right justified also known as MSB and LSB respectively */ 35/* left and right justified also known as MSB and LSB respectively */
35#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J 36#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
@@ -106,7 +107,7 @@ int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
106 int div_id, int div); 107 int div_id, int div);
107 108
108int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 109int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
109 int pll_id, unsigned int freq_in, unsigned int freq_out); 110 int pll_id, int source, unsigned int freq_in, unsigned int freq_out);
110 111
111/* Digital Audio interface formatting */ 112/* Digital Audio interface formatting */
112int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); 113int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
@@ -114,6 +115,10 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
114int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 115int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
115 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); 116 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width);
116 117
118int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
119 unsigned int tx_num, unsigned int *tx_slot,
120 unsigned int rx_num, unsigned int *rx_slot);
121
117int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); 122int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
118 123
119/* Digital Audio Interface mute */ 124/* Digital Audio Interface mute */
@@ -136,8 +141,8 @@ struct snd_soc_dai_ops {
136 */ 141 */
137 int (*set_sysclk)(struct snd_soc_dai *dai, 142 int (*set_sysclk)(struct snd_soc_dai *dai,
138 int clk_id, unsigned int freq, int dir); 143 int clk_id, unsigned int freq, int dir);
139 int (*set_pll)(struct snd_soc_dai *dai, 144 int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
140 int pll_id, unsigned int freq_in, unsigned int freq_out); 145 unsigned int freq_in, unsigned int freq_out);
141 int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div); 146 int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
142 147
143 /* 148 /*
@@ -148,6 +153,9 @@ struct snd_soc_dai_ops {
148 int (*set_tdm_slot)(struct snd_soc_dai *dai, 153 int (*set_tdm_slot)(struct snd_soc_dai *dai,
149 unsigned int tx_mask, unsigned int rx_mask, 154 unsigned int tx_mask, unsigned int rx_mask,
150 int slots, int slot_width); 155 int slots, int slot_width);
156 int (*set_channel_map)(struct snd_soc_dai *dai,
157 unsigned int tx_num, unsigned int *tx_slot,
158 unsigned int rx_num, unsigned int *rx_slot);
151 int (*set_tristate)(struct snd_soc_dai *dai, int tristate); 159 int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
152 160
153 /* 161 /*
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index c1410e3191e3..c5c95e1da65b 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -206,6 +206,12 @@
206 .get = snd_soc_dapm_get_enum_double, \ 206 .get = snd_soc_dapm_get_enum_double, \
207 .put = snd_soc_dapm_put_enum_double, \ 207 .put = snd_soc_dapm_put_enum_double, \
208 .private_value = (unsigned long)&xenum } 208 .private_value = (unsigned long)&xenum }
209#define SOC_DAPM_ENUM_VIRT(xname, xenum) \
210{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
211 .info = snd_soc_info_enum_double, \
212 .get = snd_soc_dapm_get_enum_virt, \
213 .put = snd_soc_dapm_put_enum_virt, \
214 .private_value = (unsigned long)&xenum }
209#define SOC_DAPM_VALUE_ENUM(xname, xenum) \ 215#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
210{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 216{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
211 .info = snd_soc_info_enum_double, \ 217 .info = snd_soc_info_enum_double, \
@@ -260,6 +266,10 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
260 struct snd_ctl_elem_value *ucontrol); 266 struct snd_ctl_elem_value *ucontrol);
261int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 267int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_value *ucontrol); 268 struct snd_ctl_elem_value *ucontrol);
269int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
270 struct snd_ctl_elem_value *ucontrol);
271int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
272 struct snd_ctl_elem_value *ucontrol);
263int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, 273int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
264 struct snd_ctl_elem_value *ucontrol); 274 struct snd_ctl_elem_value *ucontrol);
265int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 275int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
@@ -333,6 +343,10 @@ struct snd_soc_dapm_route {
333 const char *sink; 343 const char *sink;
334 const char *control; 344 const char *control;
335 const char *source; 345 const char *source;
346
347 /* Note: currently only supported for links where source is a supply */
348 int (*connected)(struct snd_soc_dapm_widget *source,
349 struct snd_soc_dapm_widget *sink);
336}; 350};
337 351
338/* dapm audio path between two widgets */ 352/* dapm audio path between two widgets */
@@ -349,6 +363,9 @@ struct snd_soc_dapm_path {
349 u32 connect:1; /* source and sink widgets are connected */ 363 u32 connect:1; /* source and sink widgets are connected */
350 u32 walked:1; /* path has been walked */ 364 u32 walked:1; /* path has been walked */
351 365
366 int (*connected)(struct snd_soc_dapm_widget *source,
367 struct snd_soc_dapm_widget *sink);
368
352 struct list_head list_source; 369 struct list_head list_source;
353 struct list_head list_sink; 370 struct list_head list_sink;
354 struct list_head list; 371 struct list_head list;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 475cb7ed6bec..0d7718f9280d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -223,15 +223,15 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
223 int addr_bits, int data_bits, 223 int addr_bits, int data_bits,
224 enum snd_soc_control_type control); 224 enum snd_soc_control_type control);
225 225
226#ifdef CONFIG_PM
227int snd_soc_suspend_device(struct device *dev);
228int snd_soc_resume_device(struct device *dev);
229#endif
230
231/* pcm <-> DAI connect */ 226/* pcm <-> DAI connect */
232void snd_soc_free_pcms(struct snd_soc_device *socdev); 227void snd_soc_free_pcms(struct snd_soc_device *socdev);
233int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); 228int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
234int snd_soc_init_card(struct snd_soc_device *socdev); 229
230/* Utility functions to get clock rates from various things */
231int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
232int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
233int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots);
234int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms);
235 235
236/* set runtime hw params */ 236/* set runtime hw params */
237int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, 237int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
@@ -333,6 +333,8 @@ struct snd_soc_jack_gpio {
333 int debounce_time; 333 int debounce_time;
334 struct snd_soc_jack *jack; 334 struct snd_soc_jack *jack;
335 struct work_struct work; 335 struct work_struct work;
336
337 int (*jack_status_check)(void);
336}; 338};
337#endif 339#endif
338 340
@@ -413,6 +415,7 @@ struct snd_soc_codec {
413 unsigned int num_dai; 415 unsigned int num_dai;
414 416
415#ifdef CONFIG_DEBUG_FS 417#ifdef CONFIG_DEBUG_FS
418 struct dentry *debugfs_codec_root;
416 struct dentry *debugfs_reg; 419 struct dentry *debugfs_reg;
417 struct dentry *debugfs_pop_time; 420 struct dentry *debugfs_pop_time;
418 struct dentry *debugfs_dapm; 421 struct dentry *debugfs_dapm;
diff --git a/include/sound/sscape_ioctl.h b/include/sound/sscape_ioctl.h
deleted file mode 100644
index 0d8885969c64..000000000000
--- a/include/sound/sscape_ioctl.h
+++ /dev/null
@@ -1,21 +0,0 @@
1#ifndef SSCAPE_IOCTL_H
2#define SSCAPE_IOCTL_H
3
4
5struct sscape_bootblock
6{
7 unsigned char code[256];
8 unsigned version;
9};
10
11#define SSCAPE_MICROCODE_SIZE 65536
12
13struct sscape_microcode
14{
15 unsigned char __user *code;
16};
17
18#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock)
19#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode)
20
21#endif
diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h
new file mode 100644
index 000000000000..5858d06a7ffa
--- /dev/null
+++ b/include/sound/tlv320dac33-plat.h
@@ -0,0 +1,20 @@
1/*
2 * Platform header for Texas Instruments TLV320DAC33 codec driver
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __TLV320DAC33_PLAT_H
14#define __TLV320DAC33_PLAT_H
15
16struct tlv320dac33_platform_data {
17 int power_gpio;
18};
19
20#endif /* __TLV320DAC33_PLAT_H */
diff --git a/include/sound/tpa6130a2-plat.h b/include/sound/tpa6130a2-plat.h
new file mode 100644
index 000000000000..e8c901e749d8
--- /dev/null
+++ b/include/sound/tpa6130a2-plat.h
@@ -0,0 +1,30 @@
1/*
2 * TPA6130A2 driver platform header
3 *
4 * Copyright (C) Nokia Corporation
5 *
6 * Written by Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#ifndef TPA6130A2_PLAT_H
24#define TPA6130A2_PLAT_H
25
26struct tpa6130a2_platform_data {
27 int power_gpio;
28};
29
30#endif
diff --git a/include/sound/wss.h b/include/sound/wss.h
index 6d65f322f1d5..fd01f22825cd 100644
--- a/include/sound/wss.h
+++ b/include/sound/wss.h
@@ -154,7 +154,6 @@ int snd_wss_create(struct snd_card *card,
154 unsigned short hardware, 154 unsigned short hardware,
155 unsigned short hwshare, 155 unsigned short hwshare,
156 struct snd_wss **rchip); 156 struct snd_wss **rchip);
157int snd_wss_free(struct snd_wss *chip);
158int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); 157int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
159int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); 158int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
160int snd_wss_mixer(struct snd_wss *chip); 159int snd_wss_mixer(struct snd_wss *chip);
diff --git a/include/trace/define_trace.h b/include/trace/define_trace.h
index 2a4b3bf74033..5acfb1eb4df9 100644
--- a/include/trace/define_trace.h
+++ b/include/trace/define_trace.h
@@ -31,6 +31,14 @@
31 assign, print, reg, unreg) \ 31 assign, print, reg, unreg) \
32 DEFINE_TRACE_FN(name, reg, unreg) 32 DEFINE_TRACE_FN(name, reg, unreg)
33 33
34#undef DEFINE_EVENT
35#define DEFINE_EVENT(template, name, proto, args) \
36 DEFINE_TRACE(name)
37
38#undef DEFINE_EVENT_PRINT
39#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
40 DEFINE_TRACE(name)
41
34#undef DECLARE_TRACE 42#undef DECLARE_TRACE
35#define DECLARE_TRACE(name, proto, args) \ 43#define DECLARE_TRACE(name, proto, args) \
36 DEFINE_TRACE(name) 44 DEFINE_TRACE(name)
@@ -63,6 +71,9 @@
63 71
64#undef TRACE_EVENT 72#undef TRACE_EVENT
65#undef TRACE_EVENT_FN 73#undef TRACE_EVENT_FN
74#undef DECLARE_EVENT_CLASS
75#undef DEFINE_EVENT
76#undef DEFINE_EVENT_PRINT
66#undef TRACE_HEADER_MULTI_READ 77#undef TRACE_HEADER_MULTI_READ
67 78
68/* Only undef what we defined in this file */ 79/* Only undef what we defined in this file */
diff --git a/include/trace/events/bkl.h b/include/trace/events/bkl.h
index 8abd620a490e..1af72dc24278 100644
--- a/include/trace/events/bkl.h
+++ b/include/trace/events/bkl.h
@@ -13,7 +13,7 @@ TRACE_EVENT(lock_kernel,
13 TP_ARGS(func, file, line), 13 TP_ARGS(func, file, line),
14 14
15 TP_STRUCT__entry( 15 TP_STRUCT__entry(
16 __field( int, lock_depth ) 16 __field( int, depth )
17 __field_ext( const char *, func, FILTER_PTR_STRING ) 17 __field_ext( const char *, func, FILTER_PTR_STRING )
18 __field_ext( const char *, file, FILTER_PTR_STRING ) 18 __field_ext( const char *, file, FILTER_PTR_STRING )
19 __field( int, line ) 19 __field( int, line )
@@ -21,13 +21,13 @@ TRACE_EVENT(lock_kernel,
21 21
22 TP_fast_assign( 22 TP_fast_assign(
23 /* We want to record the lock_depth after lock is acquired */ 23 /* We want to record the lock_depth after lock is acquired */
24 __entry->lock_depth = current->lock_depth + 1; 24 __entry->depth = current->lock_depth + 1;
25 __entry->func = func; 25 __entry->func = func;
26 __entry->file = file; 26 __entry->file = file;
27 __entry->line = line; 27 __entry->line = line;
28 ), 28 ),
29 29
30 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth, 30 TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
31 __entry->file, __entry->line, __entry->func) 31 __entry->file, __entry->line, __entry->func)
32); 32);
33 33
@@ -38,20 +38,20 @@ TRACE_EVENT(unlock_kernel,
38 TP_ARGS(func, file, line), 38 TP_ARGS(func, file, line),
39 39
40 TP_STRUCT__entry( 40 TP_STRUCT__entry(
41 __field(int, lock_depth) 41 __field(int, depth )
42 __field(const char *, func) 42 __field(const char *, func )
43 __field(const char *, file) 43 __field(const char *, file )
44 __field(int, line) 44 __field(int, line )
45 ), 45 ),
46 46
47 TP_fast_assign( 47 TP_fast_assign(
48 __entry->lock_depth = current->lock_depth; 48 __entry->depth = current->lock_depth;
49 __entry->func = func; 49 __entry->func = func;
50 __entry->file = file; 50 __entry->file = file;
51 __entry->line = line; 51 __entry->line = line;
52 ), 52 ),
53 53
54 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth, 54 TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
55 __entry->file, __entry->line, __entry->func) 55 __entry->file, __entry->line, __entry->func)
56); 56);
57 57
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 00405b5f624a..5fb72733331e 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -8,7 +8,7 @@
8#include <linux/blkdev.h> 8#include <linux/blkdev.h>
9#include <linux/tracepoint.h> 9#include <linux/tracepoint.h>
10 10
11TRACE_EVENT(block_rq_abort, 11DECLARE_EVENT_CLASS(block_rq_with_error,
12 12
13 TP_PROTO(struct request_queue *q, struct request *rq), 13 TP_PROTO(struct request_queue *q, struct request *rq),
14 14
@@ -40,41 +40,28 @@ TRACE_EVENT(block_rq_abort,
40 __entry->nr_sector, __entry->errors) 40 __entry->nr_sector, __entry->errors)
41); 41);
42 42
43TRACE_EVENT(block_rq_insert, 43DEFINE_EVENT(block_rq_with_error, block_rq_abort,
44 44
45 TP_PROTO(struct request_queue *q, struct request *rq), 45 TP_PROTO(struct request_queue *q, struct request *rq),
46 46
47 TP_ARGS(q, rq), 47 TP_ARGS(q, rq)
48);
48 49
49 TP_STRUCT__entry( 50DEFINE_EVENT(block_rq_with_error, block_rq_requeue,
50 __field( dev_t, dev )
51 __field( sector_t, sector )
52 __field( unsigned int, nr_sector )
53 __field( unsigned int, bytes )
54 __array( char, rwbs, 6 )
55 __array( char, comm, TASK_COMM_LEN )
56 __dynamic_array( char, cmd, blk_cmd_buf_len(rq) )
57 ),
58 51
59 TP_fast_assign( 52 TP_PROTO(struct request_queue *q, struct request *rq),
60 __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0;
61 __entry->sector = blk_pc_request(rq) ? 0 : blk_rq_pos(rq);
62 __entry->nr_sector = blk_pc_request(rq) ? 0 : blk_rq_sectors(rq);
63 __entry->bytes = blk_pc_request(rq) ? blk_rq_bytes(rq) : 0;
64 53
65 blk_fill_rwbs_rq(__entry->rwbs, rq); 54 TP_ARGS(q, rq)
66 blk_dump_cmd(__get_str(cmd), rq); 55);
67 memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
68 ),
69 56
70 TP_printk("%d,%d %s %u (%s) %llu + %u [%s]", 57DEFINE_EVENT(block_rq_with_error, block_rq_complete,
71 MAJOR(__entry->dev), MINOR(__entry->dev), 58
72 __entry->rwbs, __entry->bytes, __get_str(cmd), 59 TP_PROTO(struct request_queue *q, struct request *rq),
73 (unsigned long long)__entry->sector, 60
74 __entry->nr_sector, __entry->comm) 61 TP_ARGS(q, rq)
75); 62);
76 63
77TRACE_EVENT(block_rq_issue, 64DECLARE_EVENT_CLASS(block_rq,
78 65
79 TP_PROTO(struct request_queue *q, struct request *rq), 66 TP_PROTO(struct request_queue *q, struct request *rq),
80 67
@@ -86,7 +73,7 @@ TRACE_EVENT(block_rq_issue,
86 __field( unsigned int, nr_sector ) 73 __field( unsigned int, nr_sector )
87 __field( unsigned int, bytes ) 74 __field( unsigned int, bytes )
88 __array( char, rwbs, 6 ) 75 __array( char, rwbs, 6 )
89 __array( char, comm, TASK_COMM_LEN ) 76 __array( char, comm, TASK_COMM_LEN )
90 __dynamic_array( char, cmd, blk_cmd_buf_len(rq) ) 77 __dynamic_array( char, cmd, blk_cmd_buf_len(rq) )
91 ), 78 ),
92 79
@@ -108,68 +95,18 @@ TRACE_EVENT(block_rq_issue,
108 __entry->nr_sector, __entry->comm) 95 __entry->nr_sector, __entry->comm)
109); 96);
110 97
111TRACE_EVENT(block_rq_requeue, 98DEFINE_EVENT(block_rq, block_rq_insert,
112 99
113 TP_PROTO(struct request_queue *q, struct request *rq), 100 TP_PROTO(struct request_queue *q, struct request *rq),
114 101
115 TP_ARGS(q, rq), 102 TP_ARGS(q, rq)
116
117 TP_STRUCT__entry(
118 __field( dev_t, dev )
119 __field( sector_t, sector )
120 __field( unsigned int, nr_sector )
121 __field( int, errors )
122 __array( char, rwbs, 6 )
123 __dynamic_array( char, cmd, blk_cmd_buf_len(rq) )
124 ),
125
126 TP_fast_assign(
127 __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0;
128 __entry->sector = blk_pc_request(rq) ? 0 : blk_rq_pos(rq);
129 __entry->nr_sector = blk_pc_request(rq) ? 0 : blk_rq_sectors(rq);
130 __entry->errors = rq->errors;
131
132 blk_fill_rwbs_rq(__entry->rwbs, rq);
133 blk_dump_cmd(__get_str(cmd), rq);
134 ),
135
136 TP_printk("%d,%d %s (%s) %llu + %u [%d]",
137 MAJOR(__entry->dev), MINOR(__entry->dev),
138 __entry->rwbs, __get_str(cmd),
139 (unsigned long long)__entry->sector,
140 __entry->nr_sector, __entry->errors)
141); 103);
142 104
143TRACE_EVENT(block_rq_complete, 105DEFINE_EVENT(block_rq, block_rq_issue,
144 106
145 TP_PROTO(struct request_queue *q, struct request *rq), 107 TP_PROTO(struct request_queue *q, struct request *rq),
146 108
147 TP_ARGS(q, rq), 109 TP_ARGS(q, rq)
148
149 TP_STRUCT__entry(
150 __field( dev_t, dev )
151 __field( sector_t, sector )
152 __field( unsigned int, nr_sector )
153 __field( int, errors )
154 __array( char, rwbs, 6 )
155 __dynamic_array( char, cmd, blk_cmd_buf_len(rq) )
156 ),
157
158 TP_fast_assign(
159 __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0;
160 __entry->sector = blk_pc_request(rq) ? 0 : blk_rq_pos(rq);
161 __entry->nr_sector = blk_pc_request(rq) ? 0 : blk_rq_sectors(rq);
162 __entry->errors = rq->errors;
163
164 blk_fill_rwbs_rq(__entry->rwbs, rq);
165 blk_dump_cmd(__get_str(cmd), rq);
166 ),
167
168 TP_printk("%d,%d %s (%s) %llu + %u [%d]",
169 MAJOR(__entry->dev), MINOR(__entry->dev),
170 __entry->rwbs, __get_str(cmd),
171 (unsigned long long)__entry->sector,
172 __entry->nr_sector, __entry->errors)
173); 110);
174 111
175TRACE_EVENT(block_bio_bounce, 112TRACE_EVENT(block_bio_bounce,
@@ -228,7 +165,7 @@ TRACE_EVENT(block_bio_complete,
228 __entry->nr_sector, __entry->error) 165 __entry->nr_sector, __entry->error)
229); 166);
230 167
231TRACE_EVENT(block_bio_backmerge, 168DECLARE_EVENT_CLASS(block_bio,
232 169
233 TP_PROTO(struct request_queue *q, struct bio *bio), 170 TP_PROTO(struct request_queue *q, struct bio *bio),
234 171
@@ -256,63 +193,28 @@ TRACE_EVENT(block_bio_backmerge,
256 __entry->nr_sector, __entry->comm) 193 __entry->nr_sector, __entry->comm)
257); 194);
258 195
259TRACE_EVENT(block_bio_frontmerge, 196DEFINE_EVENT(block_bio, block_bio_backmerge,
260 197
261 TP_PROTO(struct request_queue *q, struct bio *bio), 198 TP_PROTO(struct request_queue *q, struct bio *bio),
262 199
263 TP_ARGS(q, bio), 200 TP_ARGS(q, bio)
264
265 TP_STRUCT__entry(
266 __field( dev_t, dev )
267 __field( sector_t, sector )
268 __field( unsigned, nr_sector )
269 __array( char, rwbs, 6 )
270 __array( char, comm, TASK_COMM_LEN )
271 ),
272
273 TP_fast_assign(
274 __entry->dev = bio->bi_bdev->bd_dev;
275 __entry->sector = bio->bi_sector;
276 __entry->nr_sector = bio->bi_size >> 9;
277 blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
278 memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
279 ),
280
281 TP_printk("%d,%d %s %llu + %u [%s]",
282 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs,
283 (unsigned long long)__entry->sector,
284 __entry->nr_sector, __entry->comm)
285); 201);
286 202
287TRACE_EVENT(block_bio_queue, 203DEFINE_EVENT(block_bio, block_bio_frontmerge,
288 204
289 TP_PROTO(struct request_queue *q, struct bio *bio), 205 TP_PROTO(struct request_queue *q, struct bio *bio),
290 206
291 TP_ARGS(q, bio), 207 TP_ARGS(q, bio)
208);
292 209
293 TP_STRUCT__entry( 210DEFINE_EVENT(block_bio, block_bio_queue,
294 __field( dev_t, dev )
295 __field( sector_t, sector )
296 __field( unsigned int, nr_sector )
297 __array( char, rwbs, 6 )
298 __array( char, comm, TASK_COMM_LEN )
299 ),
300 211
301 TP_fast_assign( 212 TP_PROTO(struct request_queue *q, struct bio *bio),
302 __entry->dev = bio->bi_bdev->bd_dev;
303 __entry->sector = bio->bi_sector;
304 __entry->nr_sector = bio->bi_size >> 9;
305 blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
306 memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
307 ),
308 213
309 TP_printk("%d,%d %s %llu + %u [%s]", 214 TP_ARGS(q, bio)
310 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs,
311 (unsigned long long)__entry->sector,
312 __entry->nr_sector, __entry->comm)
313); 215);
314 216
315TRACE_EVENT(block_getrq, 217DECLARE_EVENT_CLASS(block_get_rq,
316 218
317 TP_PROTO(struct request_queue *q, struct bio *bio, int rw), 219 TP_PROTO(struct request_queue *q, struct bio *bio, int rw),
318 220
@@ -341,33 +243,18 @@ TRACE_EVENT(block_getrq,
341 __entry->nr_sector, __entry->comm) 243 __entry->nr_sector, __entry->comm)
342); 244);
343 245
344TRACE_EVENT(block_sleeprq, 246DEFINE_EVENT(block_get_rq, block_getrq,
345 247
346 TP_PROTO(struct request_queue *q, struct bio *bio, int rw), 248 TP_PROTO(struct request_queue *q, struct bio *bio, int rw),
347 249
348 TP_ARGS(q, bio, rw), 250 TP_ARGS(q, bio, rw)
251);
349 252
350 TP_STRUCT__entry( 253DEFINE_EVENT(block_get_rq, block_sleeprq,
351 __field( dev_t, dev )
352 __field( sector_t, sector )
353 __field( unsigned int, nr_sector )
354 __array( char, rwbs, 6 )
355 __array( char, comm, TASK_COMM_LEN )
356 ),
357 254
358 TP_fast_assign( 255 TP_PROTO(struct request_queue *q, struct bio *bio, int rw),
359 __entry->dev = bio ? bio->bi_bdev->bd_dev : 0;
360 __entry->sector = bio ? bio->bi_sector : 0;
361 __entry->nr_sector = bio ? bio->bi_size >> 9 : 0;
362 blk_fill_rwbs(__entry->rwbs,
363 bio ? bio->bi_rw : 0, __entry->nr_sector);
364 memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
365 ),
366 256
367 TP_printk("%d,%d %s %llu + %u [%s]", 257 TP_ARGS(q, bio, rw)
368 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs,
369 (unsigned long long)__entry->sector,
370 __entry->nr_sector, __entry->comm)
371); 258);
372 259
373TRACE_EVENT(block_plug, 260TRACE_EVENT(block_plug,
@@ -387,7 +274,7 @@ TRACE_EVENT(block_plug,
387 TP_printk("[%s]", __entry->comm) 274 TP_printk("[%s]", __entry->comm)
388); 275);
389 276
390TRACE_EVENT(block_unplug_timer, 277DECLARE_EVENT_CLASS(block_unplug,
391 278
392 TP_PROTO(struct request_queue *q), 279 TP_PROTO(struct request_queue *q),
393 280
@@ -406,23 +293,18 @@ TRACE_EVENT(block_unplug_timer,
406 TP_printk("[%s] %d", __entry->comm, __entry->nr_rq) 293 TP_printk("[%s] %d", __entry->comm, __entry->nr_rq)
407); 294);
408 295
409TRACE_EVENT(block_unplug_io, 296DEFINE_EVENT(block_unplug, block_unplug_timer,
410 297
411 TP_PROTO(struct request_queue *q), 298 TP_PROTO(struct request_queue *q),
412 299
413 TP_ARGS(q), 300 TP_ARGS(q)
301);
414 302
415 TP_STRUCT__entry( 303DEFINE_EVENT(block_unplug, block_unplug_io,
416 __field( int, nr_rq )
417 __array( char, comm, TASK_COMM_LEN )
418 ),
419 304
420 TP_fast_assign( 305 TP_PROTO(struct request_queue *q),
421 __entry->nr_rq = q->rq.count[READ] + q->rq.count[WRITE];
422 memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
423 ),
424 306
425 TP_printk("[%s] %d", __entry->comm, __entry->nr_rq) 307 TP_ARGS(q)
426); 308);
427 309
428TRACE_EVENT(block_split, 310TRACE_EVENT(block_split,
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index d09550bf3f95..318f76535bd4 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -90,7 +90,7 @@ TRACE_EVENT(ext4_allocate_inode,
90 (unsigned long) __entry->dir, __entry->mode) 90 (unsigned long) __entry->dir, __entry->mode)
91); 91);
92 92
93TRACE_EVENT(ext4_write_begin, 93DECLARE_EVENT_CLASS(ext4__write_begin,
94 94
95 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, 95 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
96 unsigned int flags), 96 unsigned int flags),
@@ -118,7 +118,23 @@ TRACE_EVENT(ext4_write_begin,
118 __entry->pos, __entry->len, __entry->flags) 118 __entry->pos, __entry->len, __entry->flags)
119); 119);
120 120
121TRACE_EVENT(ext4_ordered_write_end, 121DEFINE_EVENT(ext4__write_begin, ext4_write_begin,
122
123 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
124 unsigned int flags),
125
126 TP_ARGS(inode, pos, len, flags)
127);
128
129DEFINE_EVENT(ext4__write_begin, ext4_da_write_begin,
130
131 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
132 unsigned int flags),
133
134 TP_ARGS(inode, pos, len, flags)
135);
136
137DECLARE_EVENT_CLASS(ext4__write_end,
122 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, 138 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
123 unsigned int copied), 139 unsigned int copied),
124 140
@@ -145,57 +161,36 @@ TRACE_EVENT(ext4_ordered_write_end,
145 __entry->pos, __entry->len, __entry->copied) 161 __entry->pos, __entry->len, __entry->copied)
146); 162);
147 163
148TRACE_EVENT(ext4_writeback_write_end, 164DEFINE_EVENT(ext4__write_end, ext4_ordered_write_end,
165
149 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, 166 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
150 unsigned int copied), 167 unsigned int copied),
151 168
152 TP_ARGS(inode, pos, len, copied), 169 TP_ARGS(inode, pos, len, copied)
170);
153 171
154 TP_STRUCT__entry( 172DEFINE_EVENT(ext4__write_end, ext4_writeback_write_end,
155 __field( dev_t, dev )
156 __field( ino_t, ino )
157 __field( loff_t, pos )
158 __field( unsigned int, len )
159 __field( unsigned int, copied )
160 ),
161 173
162 TP_fast_assign( 174 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
163 __entry->dev = inode->i_sb->s_dev; 175 unsigned int copied),
164 __entry->ino = inode->i_ino;
165 __entry->pos = pos;
166 __entry->len = len;
167 __entry->copied = copied;
168 ),
169 176
170 TP_printk("dev %s ino %lu pos %llu len %u copied %u", 177 TP_ARGS(inode, pos, len, copied)
171 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
172 __entry->pos, __entry->len, __entry->copied)
173); 178);
174 179
175TRACE_EVENT(ext4_journalled_write_end, 180DEFINE_EVENT(ext4__write_end, ext4_journalled_write_end,
181
176 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, 182 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
177 unsigned int copied), 183 unsigned int copied),
178 TP_ARGS(inode, pos, len, copied),
179 184
180 TP_STRUCT__entry( 185 TP_ARGS(inode, pos, len, copied)
181 __field( dev_t, dev ) 186);
182 __field( ino_t, ino )
183 __field( loff_t, pos )
184 __field( unsigned int, len )
185 __field( unsigned int, copied )
186 ),
187 187
188 TP_fast_assign( 188DEFINE_EVENT(ext4__write_end, ext4_da_write_end,
189 __entry->dev = inode->i_sb->s_dev;
190 __entry->ino = inode->i_ino;
191 __entry->pos = pos;
192 __entry->len = len;
193 __entry->copied = copied;
194 ),
195 189
196 TP_printk("dev %s ino %lu pos %llu len %u copied %u", 190 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
197 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, 191 unsigned int copied),
198 __entry->pos, __entry->len, __entry->copied) 192
193 TP_ARGS(inode, pos, len, copied)
199); 194);
200 195
201TRACE_EVENT(ext4_writepage, 196TRACE_EVENT(ext4_writepage,
@@ -337,60 +332,6 @@ TRACE_EVENT(ext4_da_writepages_result,
337 (unsigned long) __entry->writeback_index) 332 (unsigned long) __entry->writeback_index)
338); 333);
339 334
340TRACE_EVENT(ext4_da_write_begin,
341 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
342 unsigned int flags),
343
344 TP_ARGS(inode, pos, len, flags),
345
346 TP_STRUCT__entry(
347 __field( dev_t, dev )
348 __field( ino_t, ino )
349 __field( loff_t, pos )
350 __field( unsigned int, len )
351 __field( unsigned int, flags )
352 ),
353
354 TP_fast_assign(
355 __entry->dev = inode->i_sb->s_dev;
356 __entry->ino = inode->i_ino;
357 __entry->pos = pos;
358 __entry->len = len;
359 __entry->flags = flags;
360 ),
361
362 TP_printk("dev %s ino %lu pos %llu len %u flags %u",
363 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
364 __entry->pos, __entry->len, __entry->flags)
365);
366
367TRACE_EVENT(ext4_da_write_end,
368 TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
369 unsigned int copied),
370
371 TP_ARGS(inode, pos, len, copied),
372
373 TP_STRUCT__entry(
374 __field( dev_t, dev )
375 __field( ino_t, ino )
376 __field( loff_t, pos )
377 __field( unsigned int, len )
378 __field( unsigned int, copied )
379 ),
380
381 TP_fast_assign(
382 __entry->dev = inode->i_sb->s_dev;
383 __entry->ino = inode->i_ino;
384 __entry->pos = pos;
385 __entry->len = len;
386 __entry->copied = copied;
387 ),
388
389 TP_printk("dev %s ino %lu pos %llu len %u copied %u",
390 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
391 __entry->pos, __entry->len, __entry->copied)
392);
393
394TRACE_EVENT(ext4_discard_blocks, 335TRACE_EVENT(ext4_discard_blocks,
395 TP_PROTO(struct super_block *sb, unsigned long long blk, 336 TP_PROTO(struct super_block *sb, unsigned long long blk,
396 unsigned long long count), 337 unsigned long long count),
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index b89f9db4a404..0e4cfb694fe7 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -48,7 +48,7 @@ TRACE_EVENT(irq_handler_entry,
48 __assign_str(name, action->name); 48 __assign_str(name, action->name);
49 ), 49 ),
50 50
51 TP_printk("irq=%d handler=%s", __entry->irq, __get_str(name)) 51 TP_printk("irq=%d name=%s", __entry->irq, __get_str(name))
52); 52);
53 53
54/** 54/**
@@ -78,22 +78,11 @@ TRACE_EVENT(irq_handler_exit,
78 __entry->ret = ret; 78 __entry->ret = ret;
79 ), 79 ),
80 80
81 TP_printk("irq=%d return=%s", 81 TP_printk("irq=%d ret=%s",
82 __entry->irq, __entry->ret ? "handled" : "unhandled") 82 __entry->irq, __entry->ret ? "handled" : "unhandled")
83); 83);
84 84
85/** 85DECLARE_EVENT_CLASS(softirq,
86 * softirq_entry - called immediately before the softirq handler
87 * @h: pointer to struct softirq_action
88 * @vec: pointer to first struct softirq_action in softirq_vec array
89 *
90 * The @h parameter, contains a pointer to the struct softirq_action
91 * which has a pointer to the action handler that is called. By subtracting
92 * the @vec pointer from the @h pointer, we can determine the softirq
93 * number. Also, when used in combination with the softirq_exit tracepoint
94 * we can determine the softirq latency.
95 */
96TRACE_EVENT(softirq_entry,
97 86
98 TP_PROTO(struct softirq_action *h, struct softirq_action *vec), 87 TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
99 88
@@ -107,11 +96,29 @@ TRACE_EVENT(softirq_entry,
107 __entry->vec = (int)(h - vec); 96 __entry->vec = (int)(h - vec);
108 ), 97 ),
109 98
110 TP_printk("softirq=%d action=%s", __entry->vec, 99 TP_printk("vec=%d [action=%s]", __entry->vec,
111 show_softirq_name(__entry->vec)) 100 show_softirq_name(__entry->vec))
112); 101);
113 102
114/** 103/**
104 * softirq_entry - called immediately before the softirq handler
105 * @h: pointer to struct softirq_action
106 * @vec: pointer to first struct softirq_action in softirq_vec array
107 *
108 * The @h parameter, contains a pointer to the struct softirq_action
109 * which has a pointer to the action handler that is called. By subtracting
110 * the @vec pointer from the @h pointer, we can determine the softirq
111 * number. Also, when used in combination with the softirq_exit tracepoint
112 * we can determine the softirq latency.
113 */
114DEFINE_EVENT(softirq, softirq_entry,
115
116 TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
117
118 TP_ARGS(h, vec)
119);
120
121/**
115 * softirq_exit - called immediately after the softirq handler returns 122 * softirq_exit - called immediately after the softirq handler returns
116 * @h: pointer to struct softirq_action 123 * @h: pointer to struct softirq_action
117 * @vec: pointer to first struct softirq_action in softirq_vec array 124 * @vec: pointer to first struct softirq_action in softirq_vec array
@@ -122,22 +129,11 @@ TRACE_EVENT(softirq_entry,
122 * combination with the softirq_entry tracepoint we can determine the softirq 129 * combination with the softirq_entry tracepoint we can determine the softirq
123 * latency. 130 * latency.
124 */ 131 */
125TRACE_EVENT(softirq_exit, 132DEFINE_EVENT(softirq, softirq_exit,
126 133
127 TP_PROTO(struct softirq_action *h, struct softirq_action *vec), 134 TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
128 135
129 TP_ARGS(h, vec), 136 TP_ARGS(h, vec)
130
131 TP_STRUCT__entry(
132 __field( int, vec )
133 ),
134
135 TP_fast_assign(
136 __entry->vec = (int)(h - vec);
137 ),
138
139 TP_printk("softirq=%d action=%s", __entry->vec,
140 show_softirq_name(__entry->vec))
141); 137);
142 138
143#endif /* _TRACE_IRQ_H */ 139#endif /* _TRACE_IRQ_H */
diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
index 3c60b75adb9e..96b370a050de 100644
--- a/include/trace/events/jbd2.h
+++ b/include/trace/events/jbd2.h
@@ -30,7 +30,7 @@ TRACE_EVENT(jbd2_checkpoint,
30 jbd2_dev_to_name(__entry->dev), __entry->result) 30 jbd2_dev_to_name(__entry->dev), __entry->result)
31); 31);
32 32
33TRACE_EVENT(jbd2_start_commit, 33DECLARE_EVENT_CLASS(jbd2_commit,
34 34
35 TP_PROTO(journal_t *journal, transaction_t *commit_transaction), 35 TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
36 36
@@ -53,73 +53,32 @@ TRACE_EVENT(jbd2_start_commit,
53 __entry->sync_commit) 53 __entry->sync_commit)
54); 54);
55 55
56TRACE_EVENT(jbd2_commit_locking, 56DEFINE_EVENT(jbd2_commit, jbd2_start_commit,
57 57
58 TP_PROTO(journal_t *journal, transaction_t *commit_transaction), 58 TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
59 59
60 TP_ARGS(journal, commit_transaction), 60 TP_ARGS(journal, commit_transaction)
61
62 TP_STRUCT__entry(
63 __field( dev_t, dev )
64 __field( char, sync_commit )
65 __field( int, transaction )
66 ),
67
68 TP_fast_assign(
69 __entry->dev = journal->j_fs_dev->bd_dev;
70 __entry->sync_commit = commit_transaction->t_synchronous_commit;
71 __entry->transaction = commit_transaction->t_tid;
72 ),
73
74 TP_printk("dev %s transaction %d sync %d",
75 jbd2_dev_to_name(__entry->dev), __entry->transaction,
76 __entry->sync_commit)
77); 61);
78 62
79TRACE_EVENT(jbd2_commit_flushing, 63DEFINE_EVENT(jbd2_commit, jbd2_commit_locking,
80 64
81 TP_PROTO(journal_t *journal, transaction_t *commit_transaction), 65 TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
82 66
83 TP_ARGS(journal, commit_transaction), 67 TP_ARGS(journal, commit_transaction)
84
85 TP_STRUCT__entry(
86 __field( dev_t, dev )
87 __field( char, sync_commit )
88 __field( int, transaction )
89 ),
90
91 TP_fast_assign(
92 __entry->dev = journal->j_fs_dev->bd_dev;
93 __entry->sync_commit = commit_transaction->t_synchronous_commit;
94 __entry->transaction = commit_transaction->t_tid;
95 ),
96
97 TP_printk("dev %s transaction %d sync %d",
98 jbd2_dev_to_name(__entry->dev), __entry->transaction,
99 __entry->sync_commit)
100); 68);
101 69
102TRACE_EVENT(jbd2_commit_logging, 70DEFINE_EVENT(jbd2_commit, jbd2_commit_flushing,
103 71
104 TP_PROTO(journal_t *journal, transaction_t *commit_transaction), 72 TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
105 73
106 TP_ARGS(journal, commit_transaction), 74 TP_ARGS(journal, commit_transaction)
75);
107 76
108 TP_STRUCT__entry( 77DEFINE_EVENT(jbd2_commit, jbd2_commit_logging,
109 __field( dev_t, dev )
110 __field( char, sync_commit )
111 __field( int, transaction )
112 ),
113 78
114 TP_fast_assign( 79 TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
115 __entry->dev = journal->j_fs_dev->bd_dev;
116 __entry->sync_commit = commit_transaction->t_synchronous_commit;
117 __entry->transaction = commit_transaction->t_tid;
118 ),
119 80
120 TP_printk("dev %s transaction %d sync %d", 81 TP_ARGS(journal, commit_transaction)
121 jbd2_dev_to_name(__entry->dev), __entry->transaction,
122 __entry->sync_commit)
123); 82);
124 83
125TRACE_EVENT(jbd2_end_commit, 84TRACE_EVENT(jbd2_end_commit,
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index eaf46bdd18a5..3adca0ca9dbe 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -44,7 +44,7 @@
44 {(unsigned long)__GFP_MOVABLE, "GFP_MOVABLE"} \ 44 {(unsigned long)__GFP_MOVABLE, "GFP_MOVABLE"} \
45 ) : "GFP_NOWAIT" 45 ) : "GFP_NOWAIT"
46 46
47TRACE_EVENT(kmalloc, 47DECLARE_EVENT_CLASS(kmem_alloc,
48 48
49 TP_PROTO(unsigned long call_site, 49 TP_PROTO(unsigned long call_site,
50 const void *ptr, 50 const void *ptr,
@@ -78,41 +78,23 @@ TRACE_EVENT(kmalloc,
78 show_gfp_flags(__entry->gfp_flags)) 78 show_gfp_flags(__entry->gfp_flags))
79); 79);
80 80
81TRACE_EVENT(kmem_cache_alloc, 81DEFINE_EVENT(kmem_alloc, kmalloc,
82 82
83 TP_PROTO(unsigned long call_site, 83 TP_PROTO(unsigned long call_site, const void *ptr,
84 const void *ptr, 84 size_t bytes_req, size_t bytes_alloc, gfp_t gfp_flags),
85 size_t bytes_req,
86 size_t bytes_alloc,
87 gfp_t gfp_flags),
88 85
89 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags), 86 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags)
87);
90 88
91 TP_STRUCT__entry( 89DEFINE_EVENT(kmem_alloc, kmem_cache_alloc,
92 __field( unsigned long, call_site )
93 __field( const void *, ptr )
94 __field( size_t, bytes_req )
95 __field( size_t, bytes_alloc )
96 __field( gfp_t, gfp_flags )
97 ),
98 90
99 TP_fast_assign( 91 TP_PROTO(unsigned long call_site, const void *ptr,
100 __entry->call_site = call_site; 92 size_t bytes_req, size_t bytes_alloc, gfp_t gfp_flags),
101 __entry->ptr = ptr;
102 __entry->bytes_req = bytes_req;
103 __entry->bytes_alloc = bytes_alloc;
104 __entry->gfp_flags = gfp_flags;
105 ),
106 93
107 TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%s", 94 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags)
108 __entry->call_site,
109 __entry->ptr,
110 __entry->bytes_req,
111 __entry->bytes_alloc,
112 show_gfp_flags(__entry->gfp_flags))
113); 95);
114 96
115TRACE_EVENT(kmalloc_node, 97DECLARE_EVENT_CLASS(kmem_alloc_node,
116 98
117 TP_PROTO(unsigned long call_site, 99 TP_PROTO(unsigned long call_site,
118 const void *ptr, 100 const void *ptr,
@@ -150,45 +132,25 @@ TRACE_EVENT(kmalloc_node,
150 __entry->node) 132 __entry->node)
151); 133);
152 134
153TRACE_EVENT(kmem_cache_alloc_node, 135DEFINE_EVENT(kmem_alloc_node, kmalloc_node,
154 136
155 TP_PROTO(unsigned long call_site, 137 TP_PROTO(unsigned long call_site, const void *ptr,
156 const void *ptr, 138 size_t bytes_req, size_t bytes_alloc,
157 size_t bytes_req, 139 gfp_t gfp_flags, int node),
158 size_t bytes_alloc,
159 gfp_t gfp_flags,
160 int node),
161 140
162 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node), 141 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node)
142);
163 143
164 TP_STRUCT__entry( 144DEFINE_EVENT(kmem_alloc_node, kmem_cache_alloc_node,
165 __field( unsigned long, call_site )
166 __field( const void *, ptr )
167 __field( size_t, bytes_req )
168 __field( size_t, bytes_alloc )
169 __field( gfp_t, gfp_flags )
170 __field( int, node )
171 ),
172 145
173 TP_fast_assign( 146 TP_PROTO(unsigned long call_site, const void *ptr,
174 __entry->call_site = call_site; 147 size_t bytes_req, size_t bytes_alloc,
175 __entry->ptr = ptr; 148 gfp_t gfp_flags, int node),
176 __entry->bytes_req = bytes_req;
177 __entry->bytes_alloc = bytes_alloc;
178 __entry->gfp_flags = gfp_flags;
179 __entry->node = node;
180 ),
181 149
182 TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%s node=%d", 150 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node)
183 __entry->call_site,
184 __entry->ptr,
185 __entry->bytes_req,
186 __entry->bytes_alloc,
187 show_gfp_flags(__entry->gfp_flags),
188 __entry->node)
189); 151);
190 152
191TRACE_EVENT(kfree, 153DECLARE_EVENT_CLASS(kmem_free,
192 154
193 TP_PROTO(unsigned long call_site, const void *ptr), 155 TP_PROTO(unsigned long call_site, const void *ptr),
194 156
@@ -207,23 +169,18 @@ TRACE_EVENT(kfree,
207 TP_printk("call_site=%lx ptr=%p", __entry->call_site, __entry->ptr) 169 TP_printk("call_site=%lx ptr=%p", __entry->call_site, __entry->ptr)
208); 170);
209 171
210TRACE_EVENT(kmem_cache_free, 172DEFINE_EVENT(kmem_free, kfree,
211 173
212 TP_PROTO(unsigned long call_site, const void *ptr), 174 TP_PROTO(unsigned long call_site, const void *ptr),
213 175
214 TP_ARGS(call_site, ptr), 176 TP_ARGS(call_site, ptr)
177);
215 178
216 TP_STRUCT__entry( 179DEFINE_EVENT(kmem_free, kmem_cache_free,
217 __field( unsigned long, call_site )
218 __field( const void *, ptr )
219 ),
220 180
221 TP_fast_assign( 181 TP_PROTO(unsigned long call_site, const void *ptr),
222 __entry->call_site = call_site;
223 __entry->ptr = ptr;
224 ),
225 182
226 TP_printk("call_site=%lx ptr=%p", __entry->call_site, __entry->ptr) 183 TP_ARGS(call_site, ptr)
227); 184);
228 185
229TRACE_EVENT(mm_page_free_direct, 186TRACE_EVENT(mm_page_free_direct,
@@ -299,7 +256,7 @@ TRACE_EVENT(mm_page_alloc,
299 show_gfp_flags(__entry->gfp_flags)) 256 show_gfp_flags(__entry->gfp_flags))
300); 257);
301 258
302TRACE_EVENT(mm_page_alloc_zone_locked, 259DECLARE_EVENT_CLASS(mm_page,
303 260
304 TP_PROTO(struct page *page, unsigned int order, int migratetype), 261 TP_PROTO(struct page *page, unsigned int order, int migratetype),
305 262
@@ -325,29 +282,22 @@ TRACE_EVENT(mm_page_alloc_zone_locked,
325 __entry->order == 0) 282 __entry->order == 0)
326); 283);
327 284
328TRACE_EVENT(mm_page_pcpu_drain, 285DEFINE_EVENT(mm_page, mm_page_alloc_zone_locked,
329 286
330 TP_PROTO(struct page *page, int order, int migratetype), 287 TP_PROTO(struct page *page, unsigned int order, int migratetype),
331 288
332 TP_ARGS(page, order, migratetype), 289 TP_ARGS(page, order, migratetype)
290);
333 291
334 TP_STRUCT__entry( 292DEFINE_EVENT_PRINT(mm_page, mm_page_pcpu_drain,
335 __field( struct page *, page )
336 __field( int, order )
337 __field( int, migratetype )
338 ),
339 293
340 TP_fast_assign( 294 TP_PROTO(struct page *page, unsigned int order, int migratetype),
341 __entry->page = page; 295
342 __entry->order = order; 296 TP_ARGS(page, order, migratetype),
343 __entry->migratetype = migratetype;
344 ),
345 297
346 TP_printk("page=%p pfn=%lu order=%d migratetype=%d", 298 TP_printk("page=%p pfn=%lu order=%d migratetype=%d",
347 __entry->page, 299 __entry->page, page_to_pfn(__entry->page),
348 page_to_pfn(__entry->page), 300 __entry->order, __entry->migratetype)
349 __entry->order,
350 __entry->migratetype)
351); 301);
352 302
353TRACE_EVENT(mm_page_alloc_extfrag, 303TRACE_EVENT(mm_page_alloc_extfrag,
diff --git a/include/trace/events/lockdep.h b/include/trace/events/lock.h
index bcf1d209a00d..a870ba125aa8 100644
--- a/include/trace/events/lockdep.h
+++ b/include/trace/events/lock.h
@@ -1,8 +1,8 @@
1#undef TRACE_SYSTEM 1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM lockdep 2#define TRACE_SYSTEM lock
3 3
4#if !defined(_TRACE_LOCKDEP_H) || defined(TRACE_HEADER_MULTI_READ) 4#if !defined(_TRACE_LOCK_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_LOCKDEP_H 5#define _TRACE_LOCK_H
6 6
7#include <linux/lockdep.h> 7#include <linux/lockdep.h>
8#include <linux/tracepoint.h> 8#include <linux/tracepoint.h>
@@ -90,7 +90,7 @@ TRACE_EVENT(lock_acquired,
90#endif 90#endif
91#endif 91#endif
92 92
93#endif /* _TRACE_LOCKDEP_H */ 93#endif /* _TRACE_LOCK_H */
94 94
95/* This part must be outside protection */ 95/* This part must be outside protection */
96#include <trace/define_trace.h> 96#include <trace/define_trace.h>
diff --git a/include/trace/events/mce.h b/include/trace/events/mce.h
new file mode 100644
index 000000000000..7eee77895cb3
--- /dev/null
+++ b/include/trace/events/mce.h
@@ -0,0 +1,69 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM mce
3
4#if !defined(_TRACE_MCE_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_MCE_H
6
7#include <linux/ktime.h>
8#include <linux/tracepoint.h>
9#include <asm/mce.h>
10
11TRACE_EVENT(mce_record,
12
13 TP_PROTO(struct mce *m),
14
15 TP_ARGS(m),
16
17 TP_STRUCT__entry(
18 __field( u64, mcgcap )
19 __field( u64, mcgstatus )
20 __field( u8, bank )
21 __field( u64, status )
22 __field( u64, addr )
23 __field( u64, misc )
24 __field( u64, ip )
25 __field( u8, cs )
26 __field( u64, tsc )
27 __field( u64, walltime )
28 __field( u32, cpu )
29 __field( u32, cpuid )
30 __field( u32, apicid )
31 __field( u32, socketid )
32 __field( u8, cpuvendor )
33 ),
34
35 TP_fast_assign(
36 __entry->mcgcap = m->mcgcap;
37 __entry->mcgstatus = m->mcgstatus;
38 __entry->bank = m->bank;
39 __entry->status = m->status;
40 __entry->addr = m->addr;
41 __entry->misc = m->misc;
42 __entry->ip = m->ip;
43 __entry->cs = m->cs;
44 __entry->tsc = m->tsc;
45 __entry->walltime = m->time;
46 __entry->cpu = m->extcpu;
47 __entry->cpuid = m->cpuid;
48 __entry->apicid = m->apicid;
49 __entry->socketid = m->socketid;
50 __entry->cpuvendor = m->cpuvendor;
51 ),
52
53 TP_printk("CPU: %d, MCGc/s: %llx/%llx, MC%d: %016Lx, ADDR/MISC: %016Lx/%016Lx, RIP: %02x:<%016Lx>, TSC: %llx, PROCESSOR: %u:%x, TIME: %llu, SOCKET: %u, APIC: %x",
54 __entry->cpu,
55 __entry->mcgcap, __entry->mcgstatus,
56 __entry->bank, __entry->status,
57 __entry->addr, __entry->misc,
58 __entry->cs, __entry->ip,
59 __entry->tsc,
60 __entry->cpuvendor, __entry->cpuid,
61 __entry->walltime,
62 __entry->socketid,
63 __entry->apicid)
64);
65
66#endif /* _TRACE_MCE_H */
67
68/* This part must be outside protection */
69#include <trace/define_trace.h>
diff --git a/include/trace/events/module.h b/include/trace/events/module.h
index 84160fb18478..4b0f48ba16a6 100644
--- a/include/trace/events/module.h
+++ b/include/trace/events/module.h
@@ -51,7 +51,7 @@ TRACE_EVENT(module_free,
51 TP_printk("%s", __get_str(name)) 51 TP_printk("%s", __get_str(name))
52); 52);
53 53
54TRACE_EVENT(module_get, 54DECLARE_EVENT_CLASS(module_refcnt,
55 55
56 TP_PROTO(struct module *mod, unsigned long ip, int refcnt), 56 TP_PROTO(struct module *mod, unsigned long ip, int refcnt),
57 57
@@ -73,26 +73,18 @@ TRACE_EVENT(module_get,
73 __get_str(name), (void *)__entry->ip, __entry->refcnt) 73 __get_str(name), (void *)__entry->ip, __entry->refcnt)
74); 74);
75 75
76TRACE_EVENT(module_put, 76DEFINE_EVENT(module_refcnt, module_get,
77 77
78 TP_PROTO(struct module *mod, unsigned long ip, int refcnt), 78 TP_PROTO(struct module *mod, unsigned long ip, int refcnt),
79 79
80 TP_ARGS(mod, ip, refcnt), 80 TP_ARGS(mod, ip, refcnt)
81);
81 82
82 TP_STRUCT__entry( 83DEFINE_EVENT(module_refcnt, module_put,
83 __field( unsigned long, ip )
84 __field( int, refcnt )
85 __string( name, mod->name )
86 ),
87 84
88 TP_fast_assign( 85 TP_PROTO(struct module *mod, unsigned long ip, int refcnt),
89 __entry->ip = ip;
90 __entry->refcnt = refcnt;
91 __assign_str(name, mod->name);
92 ),
93 86
94 TP_printk("%s call_site=%pf refcnt=%d", 87 TP_ARGS(mod, ip, refcnt)
95 __get_str(name), (void *)__entry->ip, __entry->refcnt)
96); 88);
97 89
98TRACE_EVENT(module_request, 90TRACE_EVENT(module_request,
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index ea6d579261ad..c4efe9b8280d 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -16,9 +16,7 @@ enum {
16}; 16};
17#endif 17#endif
18 18
19 19DECLARE_EVENT_CLASS(power,
20
21TRACE_EVENT(power_start,
22 20
23 TP_PROTO(unsigned int type, unsigned int state), 21 TP_PROTO(unsigned int type, unsigned int state),
24 22
@@ -37,42 +35,36 @@ TRACE_EVENT(power_start,
37 TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long)__entry->state) 35 TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long)__entry->state)
38); 36);
39 37
40TRACE_EVENT(power_end, 38DEFINE_EVENT(power, power_start,
41
42 TP_PROTO(int dummy),
43 39
44 TP_ARGS(dummy), 40 TP_PROTO(unsigned int type, unsigned int state),
45 41
46 TP_STRUCT__entry( 42 TP_ARGS(type, state)
47 __field( u64, dummy ) 43);
48 ),
49 44
50 TP_fast_assign( 45DEFINE_EVENT(power, power_frequency,
51 __entry->dummy = 0xffff;
52 ),
53 46
54 TP_printk("dummy=%lu", (unsigned long)__entry->dummy) 47 TP_PROTO(unsigned int type, unsigned int state),
55 48
49 TP_ARGS(type, state)
56); 50);
57 51
52TRACE_EVENT(power_end,
58 53
59TRACE_EVENT(power_frequency, 54 TP_PROTO(int dummy),
60
61 TP_PROTO(unsigned int type, unsigned int state),
62 55
63 TP_ARGS(type, state), 56 TP_ARGS(dummy),
64 57
65 TP_STRUCT__entry( 58 TP_STRUCT__entry(
66 __field( u64, type ) 59 __field( u64, dummy )
67 __field( u64, state )
68 ), 60 ),
69 61
70 TP_fast_assign( 62 TP_fast_assign(
71 __entry->type = type; 63 __entry->dummy = 0xffff;
72 __entry->state = state;
73 ), 64 ),
74 65
75 TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long) __entry->state) 66 TP_printk("dummy=%lu", (unsigned long)__entry->dummy)
67
76); 68);
77 69
78#endif /* _TRACE_POWER_H */ 70#endif /* _TRACE_POWER_H */
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 4069c43f4187..cfceb0b73e20 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -26,7 +26,7 @@ TRACE_EVENT(sched_kthread_stop,
26 __entry->pid = t->pid; 26 __entry->pid = t->pid;
27 ), 27 ),
28 28
29 TP_printk("task %s:%d", __entry->comm, __entry->pid) 29 TP_printk("comm=%s pid=%d", __entry->comm, __entry->pid)
30); 30);
31 31
32/* 32/*
@@ -46,7 +46,7 @@ TRACE_EVENT(sched_kthread_stop_ret,
46 __entry->ret = ret; 46 __entry->ret = ret;
47 ), 47 ),
48 48
49 TP_printk("ret %d", __entry->ret) 49 TP_printk("ret=%d", __entry->ret)
50); 50);
51 51
52/* 52/*
@@ -73,7 +73,7 @@ TRACE_EVENT(sched_wait_task,
73 __entry->prio = p->prio; 73 __entry->prio = p->prio;
74 ), 74 ),
75 75
76 TP_printk("task %s:%d [%d]", 76 TP_printk("comm=%s pid=%d prio=%d",
77 __entry->comm, __entry->pid, __entry->prio) 77 __entry->comm, __entry->pid, __entry->prio)
78); 78);
79 79
@@ -83,7 +83,7 @@ TRACE_EVENT(sched_wait_task,
83 * (NOTE: the 'rq' argument is not used by generic trace events, 83 * (NOTE: the 'rq' argument is not used by generic trace events,
84 * but used by the latency tracer plugin. ) 84 * but used by the latency tracer plugin. )
85 */ 85 */
86TRACE_EVENT(sched_wakeup, 86DECLARE_EVENT_CLASS(sched_wakeup_template,
87 87
88 TP_PROTO(struct rq *rq, struct task_struct *p, int success), 88 TP_PROTO(struct rq *rq, struct task_struct *p, int success),
89 89
@@ -94,7 +94,7 @@ TRACE_EVENT(sched_wakeup,
94 __field( pid_t, pid ) 94 __field( pid_t, pid )
95 __field( int, prio ) 95 __field( int, prio )
96 __field( int, success ) 96 __field( int, success )
97 __field( int, cpu ) 97 __field( int, target_cpu )
98 ), 98 ),
99 99
100 TP_fast_assign( 100 TP_fast_assign(
@@ -102,46 +102,27 @@ TRACE_EVENT(sched_wakeup,
102 __entry->pid = p->pid; 102 __entry->pid = p->pid;
103 __entry->prio = p->prio; 103 __entry->prio = p->prio;
104 __entry->success = success; 104 __entry->success = success;
105 __entry->cpu = task_cpu(p); 105 __entry->target_cpu = task_cpu(p);
106 ), 106 ),
107 107
108 TP_printk("task %s:%d [%d] success=%d [%03d]", 108 TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d",
109 __entry->comm, __entry->pid, __entry->prio, 109 __entry->comm, __entry->pid, __entry->prio,
110 __entry->success, __entry->cpu) 110 __entry->success, __entry->target_cpu)
111); 111);
112 112
113DEFINE_EVENT(sched_wakeup_template, sched_wakeup,
114 TP_PROTO(struct rq *rq, struct task_struct *p, int success),
115 TP_ARGS(rq, p, success));
116
113/* 117/*
114 * Tracepoint for waking up a new task: 118 * Tracepoint for waking up a new task:
115 * 119 *
116 * (NOTE: the 'rq' argument is not used by generic trace events, 120 * (NOTE: the 'rq' argument is not used by generic trace events,
117 * but used by the latency tracer plugin. ) 121 * but used by the latency tracer plugin. )
118 */ 122 */
119TRACE_EVENT(sched_wakeup_new, 123DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new,
120 124 TP_PROTO(struct rq *rq, struct task_struct *p, int success),
121 TP_PROTO(struct rq *rq, struct task_struct *p, int success), 125 TP_ARGS(rq, p, success));
122
123 TP_ARGS(rq, p, success),
124
125 TP_STRUCT__entry(
126 __array( char, comm, TASK_COMM_LEN )
127 __field( pid_t, pid )
128 __field( int, prio )
129 __field( int, success )
130 __field( int, cpu )
131 ),
132
133 TP_fast_assign(
134 memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
135 __entry->pid = p->pid;
136 __entry->prio = p->prio;
137 __entry->success = success;
138 __entry->cpu = task_cpu(p);
139 ),
140
141 TP_printk("task %s:%d [%d] success=%d [%03d]",
142 __entry->comm, __entry->pid, __entry->prio,
143 __entry->success, __entry->cpu)
144);
145 126
146/* 127/*
147 * Tracepoint for task switches, performed by the scheduler: 128 * Tracepoint for task switches, performed by the scheduler:
@@ -176,7 +157,7 @@ TRACE_EVENT(sched_switch,
176 __entry->next_prio = next->prio; 157 __entry->next_prio = next->prio;
177 ), 158 ),
178 159
179 TP_printk("task %s:%d [%d] (%s) ==> %s:%d [%d]", 160 TP_printk("prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d",
180 __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, 161 __entry->prev_comm, __entry->prev_pid, __entry->prev_prio,
181 __entry->prev_state ? 162 __entry->prev_state ?
182 __print_flags(__entry->prev_state, "|", 163 __print_flags(__entry->prev_state, "|",
@@ -211,15 +192,12 @@ TRACE_EVENT(sched_migrate_task,
211 __entry->dest_cpu = dest_cpu; 192 __entry->dest_cpu = dest_cpu;
212 ), 193 ),
213 194
214 TP_printk("task %s:%d [%d] from: %d to: %d", 195 TP_printk("comm=%s pid=%d prio=%d orig_cpu=%d dest_cpu=%d",
215 __entry->comm, __entry->pid, __entry->prio, 196 __entry->comm, __entry->pid, __entry->prio,
216 __entry->orig_cpu, __entry->dest_cpu) 197 __entry->orig_cpu, __entry->dest_cpu)
217); 198);
218 199
219/* 200DECLARE_EVENT_CLASS(sched_process_template,
220 * Tracepoint for freeing a task:
221 */
222TRACE_EVENT(sched_process_free,
223 201
224 TP_PROTO(struct task_struct *p), 202 TP_PROTO(struct task_struct *p),
225 203
@@ -237,34 +215,24 @@ TRACE_EVENT(sched_process_free,
237 __entry->prio = p->prio; 215 __entry->prio = p->prio;
238 ), 216 ),
239 217
240 TP_printk("task %s:%d [%d]", 218 TP_printk("comm=%s pid=%d prio=%d",
241 __entry->comm, __entry->pid, __entry->prio) 219 __entry->comm, __entry->pid, __entry->prio)
242); 220);
243 221
244/* 222/*
245 * Tracepoint for a task exiting: 223 * Tracepoint for freeing a task:
246 */ 224 */
247TRACE_EVENT(sched_process_exit, 225DEFINE_EVENT(sched_process_template, sched_process_free,
226 TP_PROTO(struct task_struct *p),
227 TP_ARGS(p));
228
248 229
249 TP_PROTO(struct task_struct *p), 230/*
250 231 * Tracepoint for a task exiting:
251 TP_ARGS(p), 232 */
252 233DEFINE_EVENT(sched_process_template, sched_process_exit,
253 TP_STRUCT__entry( 234 TP_PROTO(struct task_struct *p),
254 __array( char, comm, TASK_COMM_LEN ) 235 TP_ARGS(p));
255 __field( pid_t, pid )
256 __field( int, prio )
257 ),
258
259 TP_fast_assign(
260 memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
261 __entry->pid = p->pid;
262 __entry->prio = p->prio;
263 ),
264
265 TP_printk("task %s:%d [%d]",
266 __entry->comm, __entry->pid, __entry->prio)
267);
268 236
269/* 237/*
270 * Tracepoint for a waiting task: 238 * Tracepoint for a waiting task:
@@ -287,7 +255,7 @@ TRACE_EVENT(sched_process_wait,
287 __entry->prio = current->prio; 255 __entry->prio = current->prio;
288 ), 256 ),
289 257
290 TP_printk("task %s:%d [%d]", 258 TP_printk("comm=%s pid=%d prio=%d",
291 __entry->comm, __entry->pid, __entry->prio) 259 __entry->comm, __entry->pid, __entry->prio)
292); 260);
293 261
@@ -314,46 +282,16 @@ TRACE_EVENT(sched_process_fork,
314 __entry->child_pid = child->pid; 282 __entry->child_pid = child->pid;
315 ), 283 ),
316 284
317 TP_printk("parent %s:%d child %s:%d", 285 TP_printk("comm=%s pid=%d child_comm=%s child_pid=%d",
318 __entry->parent_comm, __entry->parent_pid, 286 __entry->parent_comm, __entry->parent_pid,
319 __entry->child_comm, __entry->child_pid) 287 __entry->child_comm, __entry->child_pid)
320); 288);
321 289
322/* 290/*
323 * Tracepoint for sending a signal:
324 */
325TRACE_EVENT(sched_signal_send,
326
327 TP_PROTO(int sig, struct task_struct *p),
328
329 TP_ARGS(sig, p),
330
331 TP_STRUCT__entry(
332 __field( int, sig )
333 __array( char, comm, TASK_COMM_LEN )
334 __field( pid_t, pid )
335 ),
336
337 TP_fast_assign(
338 memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
339 __entry->pid = p->pid;
340 __entry->sig = sig;
341 ),
342
343 TP_printk("sig: %d task %s:%d",
344 __entry->sig, __entry->comm, __entry->pid)
345);
346
347/*
348 * XXX the below sched_stat tracepoints only apply to SCHED_OTHER/BATCH/IDLE 291 * XXX the below sched_stat tracepoints only apply to SCHED_OTHER/BATCH/IDLE
349 * adding sched_stat support to SCHED_FIFO/RR would be welcome. 292 * adding sched_stat support to SCHED_FIFO/RR would be welcome.
350 */ 293 */
351 294DECLARE_EVENT_CLASS(sched_stat_template,
352/*
353 * Tracepoint for accounting wait time (time the task is runnable
354 * but not actually running due to scheduler contention).
355 */
356TRACE_EVENT(sched_stat_wait,
357 295
358 TP_PROTO(struct task_struct *tsk, u64 delay), 296 TP_PROTO(struct task_struct *tsk, u64 delay),
359 297
@@ -374,11 +312,36 @@ TRACE_EVENT(sched_stat_wait,
374 __perf_count(delay); 312 __perf_count(delay);
375 ), 313 ),
376 314
377 TP_printk("task: %s:%d wait: %Lu [ns]", 315 TP_printk("comm=%s pid=%d delay=%Lu [ns]",
378 __entry->comm, __entry->pid, 316 __entry->comm, __entry->pid,
379 (unsigned long long)__entry->delay) 317 (unsigned long long)__entry->delay)
380); 318);
381 319
320
321/*
322 * Tracepoint for accounting wait time (time the task is runnable
323 * but not actually running due to scheduler contention).
324 */
325DEFINE_EVENT(sched_stat_template, sched_stat_wait,
326 TP_PROTO(struct task_struct *tsk, u64 delay),
327 TP_ARGS(tsk, delay));
328
329/*
330 * Tracepoint for accounting sleep time (time the task is not runnable,
331 * including iowait, see below).
332 */
333DEFINE_EVENT(sched_stat_template, sched_stat_sleep,
334 TP_PROTO(struct task_struct *tsk, u64 delay),
335 TP_ARGS(tsk, delay));
336
337/*
338 * Tracepoint for accounting iowait time (time the task is not runnable
339 * due to waiting on IO to complete).
340 */
341DEFINE_EVENT(sched_stat_template, sched_stat_iowait,
342 TP_PROTO(struct task_struct *tsk, u64 delay),
343 TP_ARGS(tsk, delay));
344
382/* 345/*
383 * Tracepoint for accounting runtime (time the task is executing 346 * Tracepoint for accounting runtime (time the task is executing
384 * on a CPU). 347 * on a CPU).
@@ -406,72 +369,12 @@ TRACE_EVENT(sched_stat_runtime,
406 __perf_count(runtime); 369 __perf_count(runtime);
407 ), 370 ),
408 371
409 TP_printk("task: %s:%d runtime: %Lu [ns], vruntime: %Lu [ns]", 372 TP_printk("comm=%s pid=%d runtime=%Lu [ns] vruntime=%Lu [ns]",
410 __entry->comm, __entry->pid, 373 __entry->comm, __entry->pid,
411 (unsigned long long)__entry->runtime, 374 (unsigned long long)__entry->runtime,
412 (unsigned long long)__entry->vruntime) 375 (unsigned long long)__entry->vruntime)
413); 376);
414 377
415/*
416 * Tracepoint for accounting sleep time (time the task is not runnable,
417 * including iowait, see below).
418 */
419TRACE_EVENT(sched_stat_sleep,
420
421 TP_PROTO(struct task_struct *tsk, u64 delay),
422
423 TP_ARGS(tsk, delay),
424
425 TP_STRUCT__entry(
426 __array( char, comm, TASK_COMM_LEN )
427 __field( pid_t, pid )
428 __field( u64, delay )
429 ),
430
431 TP_fast_assign(
432 memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
433 __entry->pid = tsk->pid;
434 __entry->delay = delay;
435 )
436 TP_perf_assign(
437 __perf_count(delay);
438 ),
439
440 TP_printk("task: %s:%d sleep: %Lu [ns]",
441 __entry->comm, __entry->pid,
442 (unsigned long long)__entry->delay)
443);
444
445/*
446 * Tracepoint for accounting iowait time (time the task is not runnable
447 * due to waiting on IO to complete).
448 */
449TRACE_EVENT(sched_stat_iowait,
450
451 TP_PROTO(struct task_struct *tsk, u64 delay),
452
453 TP_ARGS(tsk, delay),
454
455 TP_STRUCT__entry(
456 __array( char, comm, TASK_COMM_LEN )
457 __field( pid_t, pid )
458 __field( u64, delay )
459 ),
460
461 TP_fast_assign(
462 memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
463 __entry->pid = tsk->pid;
464 __entry->delay = delay;
465 )
466 TP_perf_assign(
467 __perf_count(delay);
468 ),
469
470 TP_printk("task: %s:%d iowait: %Lu [ns]",
471 __entry->comm, __entry->pid,
472 (unsigned long long)__entry->delay)
473);
474
475#endif /* _TRACE_SCHED_H */ 378#endif /* _TRACE_SCHED_H */
476 379
477/* This part must be outside protection */ 380/* This part must be outside protection */
diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h
new file mode 100644
index 000000000000..a510b75ac304
--- /dev/null
+++ b/include/trace/events/signal.h
@@ -0,0 +1,173 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM signal
3
4#if !defined(_TRACE_SIGNAL_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_SIGNAL_H
6
7#include <linux/signal.h>
8#include <linux/sched.h>
9#include <linux/tracepoint.h>
10
11#define TP_STORE_SIGINFO(__entry, info) \
12 do { \
13 if (info == SEND_SIG_NOINFO) { \
14 __entry->errno = 0; \
15 __entry->code = SI_USER; \
16 } else if (info == SEND_SIG_PRIV) { \
17 __entry->errno = 0; \
18 __entry->code = SI_KERNEL; \
19 } else { \
20 __entry->errno = info->si_errno; \
21 __entry->code = info->si_code; \
22 } \
23 } while (0)
24
25/**
26 * signal_generate - called when a signal is generated
27 * @sig: signal number
28 * @info: pointer to struct siginfo
29 * @task: pointer to struct task_struct
30 *
31 * Current process sends a 'sig' signal to 'task' process with
32 * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV,
33 * 'info' is not a pointer and you can't access its field. Instead,
34 * SEND_SIG_NOINFO means that si_code is SI_USER, and SEND_SIG_PRIV
35 * means that si_code is SI_KERNEL.
36 */
37TRACE_EVENT(signal_generate,
38
39 TP_PROTO(int sig, struct siginfo *info, struct task_struct *task),
40
41 TP_ARGS(sig, info, task),
42
43 TP_STRUCT__entry(
44 __field( int, sig )
45 __field( int, errno )
46 __field( int, code )
47 __array( char, comm, TASK_COMM_LEN )
48 __field( pid_t, pid )
49 ),
50
51 TP_fast_assign(
52 __entry->sig = sig;
53 TP_STORE_SIGINFO(__entry, info);
54 memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
55 __entry->pid = task->pid;
56 ),
57
58 TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d",
59 __entry->sig, __entry->errno, __entry->code,
60 __entry->comm, __entry->pid)
61);
62
63/**
64 * signal_deliver - called when a signal is delivered
65 * @sig: signal number
66 * @info: pointer to struct siginfo
67 * @ka: pointer to struct k_sigaction
68 *
69 * A 'sig' signal is delivered to current process with 'info' siginfo,
70 * and it will be handled by 'ka'. ka->sa.sa_handler can be SIG_IGN or
71 * SIG_DFL.
72 * Note that some signals reported by signal_generate tracepoint can be
73 * lost, ignored or modified (by debugger) before hitting this tracepoint.
74 * This means, this can show which signals are actually delivered, but
75 * matching generated signals and delivered signals may not be correct.
76 */
77TRACE_EVENT(signal_deliver,
78
79 TP_PROTO(int sig, struct siginfo *info, struct k_sigaction *ka),
80
81 TP_ARGS(sig, info, ka),
82
83 TP_STRUCT__entry(
84 __field( int, sig )
85 __field( int, errno )
86 __field( int, code )
87 __field( unsigned long, sa_handler )
88 __field( unsigned long, sa_flags )
89 ),
90
91 TP_fast_assign(
92 __entry->sig = sig;
93 TP_STORE_SIGINFO(__entry, info);
94 __entry->sa_handler = (unsigned long)ka->sa.sa_handler;
95 __entry->sa_flags = ka->sa.sa_flags;
96 ),
97
98 TP_printk("sig=%d errno=%d code=%d sa_handler=%lx sa_flags=%lx",
99 __entry->sig, __entry->errno, __entry->code,
100 __entry->sa_handler, __entry->sa_flags)
101);
102
103/**
104 * signal_overflow_fail - called when signal queue is overflow
105 * @sig: signal number
106 * @group: signal to process group or not (bool)
107 * @info: pointer to struct siginfo
108 *
109 * Kernel fails to generate 'sig' signal with 'info' siginfo, because
110 * siginfo queue is overflow, and the signal is dropped.
111 * 'group' is not 0 if the signal will be sent to a process group.
112 * 'sig' is always one of RT signals.
113 */
114TRACE_EVENT(signal_overflow_fail,
115
116 TP_PROTO(int sig, int group, struct siginfo *info),
117
118 TP_ARGS(sig, group, info),
119
120 TP_STRUCT__entry(
121 __field( int, sig )
122 __field( int, group )
123 __field( int, errno )
124 __field( int, code )
125 ),
126
127 TP_fast_assign(
128 __entry->sig = sig;
129 __entry->group = group;
130 TP_STORE_SIGINFO(__entry, info);
131 ),
132
133 TP_printk("sig=%d group=%d errno=%d code=%d",
134 __entry->sig, __entry->group, __entry->errno, __entry->code)
135);
136
137/**
138 * signal_lose_info - called when siginfo is lost
139 * @sig: signal number
140 * @group: signal to process group or not (bool)
141 * @info: pointer to struct siginfo
142 *
143 * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo
144 * queue is overflow.
145 * 'group' is not 0 if the signal will be sent to a process group.
146 * 'sig' is always one of non-RT signals.
147 */
148TRACE_EVENT(signal_lose_info,
149
150 TP_PROTO(int sig, int group, struct siginfo *info),
151
152 TP_ARGS(sig, group, info),
153
154 TP_STRUCT__entry(
155 __field( int, sig )
156 __field( int, group )
157 __field( int, errno )
158 __field( int, code )
159 ),
160
161 TP_fast_assign(
162 __entry->sig = sig;
163 __entry->group = group;
164 TP_STORE_SIGINFO(__entry, info);
165 ),
166
167 TP_printk("sig=%d group=%d errno=%d code=%d",
168 __entry->sig, __entry->group, __entry->errno, __entry->code)
169);
170#endif /* _TRACE_SIGNAL_H */
171
172/* This part must be outside protection */
173#include <trace/define_trace.h>
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 1844c48d640e..e5ce87a0498d 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -26,7 +26,7 @@ TRACE_EVENT(timer_init,
26 __entry->timer = timer; 26 __entry->timer = timer;
27 ), 27 ),
28 28
29 TP_printk("timer %p", __entry->timer) 29 TP_printk("timer=%p", __entry->timer)
30); 30);
31 31
32/** 32/**
@@ -54,7 +54,7 @@ TRACE_EVENT(timer_start,
54 __entry->now = jiffies; 54 __entry->now = jiffies;
55 ), 55 ),
56 56
57 TP_printk("timer %p: func %pf, expires %lu, timeout %ld", 57 TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld]",
58 __entry->timer, __entry->function, __entry->expires, 58 __entry->timer, __entry->function, __entry->expires,
59 (long)__entry->expires - __entry->now) 59 (long)__entry->expires - __entry->now)
60); 60);
@@ -81,7 +81,7 @@ TRACE_EVENT(timer_expire_entry,
81 __entry->now = jiffies; 81 __entry->now = jiffies;
82 ), 82 ),
83 83
84 TP_printk("timer %p: now %lu", __entry->timer, __entry->now) 84 TP_printk("timer=%p now=%lu", __entry->timer, __entry->now)
85); 85);
86 86
87/** 87/**
@@ -108,7 +108,7 @@ TRACE_EVENT(timer_expire_exit,
108 __entry->timer = timer; 108 __entry->timer = timer;
109 ), 109 ),
110 110
111 TP_printk("timer %p", __entry->timer) 111 TP_printk("timer=%p", __entry->timer)
112); 112);
113 113
114/** 114/**
@@ -129,7 +129,7 @@ TRACE_EVENT(timer_cancel,
129 __entry->timer = timer; 129 __entry->timer = timer;
130 ), 130 ),
131 131
132 TP_printk("timer %p", __entry->timer) 132 TP_printk("timer=%p", __entry->timer)
133); 133);
134 134
135/** 135/**
@@ -140,24 +140,24 @@ TRACE_EVENT(timer_cancel,
140 */ 140 */
141TRACE_EVENT(hrtimer_init, 141TRACE_EVENT(hrtimer_init,
142 142
143 TP_PROTO(struct hrtimer *timer, clockid_t clockid, 143 TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid,
144 enum hrtimer_mode mode), 144 enum hrtimer_mode mode),
145 145
146 TP_ARGS(timer, clockid, mode), 146 TP_ARGS(hrtimer, clockid, mode),
147 147
148 TP_STRUCT__entry( 148 TP_STRUCT__entry(
149 __field( void *, timer ) 149 __field( void *, hrtimer )
150 __field( clockid_t, clockid ) 150 __field( clockid_t, clockid )
151 __field( enum hrtimer_mode, mode ) 151 __field( enum hrtimer_mode, mode )
152 ), 152 ),
153 153
154 TP_fast_assign( 154 TP_fast_assign(
155 __entry->timer = timer; 155 __entry->hrtimer = hrtimer;
156 __entry->clockid = clockid; 156 __entry->clockid = clockid;
157 __entry->mode = mode; 157 __entry->mode = mode;
158 ), 158 ),
159 159
160 TP_printk("hrtimer %p, clockid %s, mode %s", __entry->timer, 160 TP_printk("hrtimer=%p clockid=%s mode=%s", __entry->hrtimer,
161 __entry->clockid == CLOCK_REALTIME ? 161 __entry->clockid == CLOCK_REALTIME ?
162 "CLOCK_REALTIME" : "CLOCK_MONOTONIC", 162 "CLOCK_REALTIME" : "CLOCK_MONOTONIC",
163 __entry->mode == HRTIMER_MODE_ABS ? 163 __entry->mode == HRTIMER_MODE_ABS ?
@@ -170,26 +170,26 @@ TRACE_EVENT(hrtimer_init,
170 */ 170 */
171TRACE_EVENT(hrtimer_start, 171TRACE_EVENT(hrtimer_start,
172 172
173 TP_PROTO(struct hrtimer *timer), 173 TP_PROTO(struct hrtimer *hrtimer),
174 174
175 TP_ARGS(timer), 175 TP_ARGS(hrtimer),
176 176
177 TP_STRUCT__entry( 177 TP_STRUCT__entry(
178 __field( void *, timer ) 178 __field( void *, hrtimer )
179 __field( void *, function ) 179 __field( void *, function )
180 __field( s64, expires ) 180 __field( s64, expires )
181 __field( s64, softexpires ) 181 __field( s64, softexpires )
182 ), 182 ),
183 183
184 TP_fast_assign( 184 TP_fast_assign(
185 __entry->timer = timer; 185 __entry->hrtimer = hrtimer;
186 __entry->function = timer->function; 186 __entry->function = hrtimer->function;
187 __entry->expires = hrtimer_get_expires(timer).tv64; 187 __entry->expires = hrtimer_get_expires(hrtimer).tv64;
188 __entry->softexpires = hrtimer_get_softexpires(timer).tv64; 188 __entry->softexpires = hrtimer_get_softexpires(hrtimer).tv64;
189 ), 189 ),
190 190
191 TP_printk("hrtimer %p, func %pf, expires %llu, softexpires %llu", 191 TP_printk("hrtimer=%p function=%pf expires=%llu softexpires=%llu",
192 __entry->timer, __entry->function, 192 __entry->hrtimer, __entry->function,
193 (unsigned long long)ktime_to_ns((ktime_t) { 193 (unsigned long long)ktime_to_ns((ktime_t) {
194 .tv64 = __entry->expires }), 194 .tv64 = __entry->expires }),
195 (unsigned long long)ktime_to_ns((ktime_t) { 195 (unsigned long long)ktime_to_ns((ktime_t) {
@@ -206,23 +206,22 @@ TRACE_EVENT(hrtimer_start,
206 */ 206 */
207TRACE_EVENT(hrtimer_expire_entry, 207TRACE_EVENT(hrtimer_expire_entry,
208 208
209 TP_PROTO(struct hrtimer *timer, ktime_t *now), 209 TP_PROTO(struct hrtimer *hrtimer, ktime_t *now),
210 210
211 TP_ARGS(timer, now), 211 TP_ARGS(hrtimer, now),
212 212
213 TP_STRUCT__entry( 213 TP_STRUCT__entry(
214 __field( void *, timer ) 214 __field( void *, hrtimer )
215 __field( s64, now ) 215 __field( s64, now )
216 ), 216 ),
217 217
218 TP_fast_assign( 218 TP_fast_assign(
219 __entry->timer = timer; 219 __entry->hrtimer = hrtimer;
220 __entry->now = now->tv64; 220 __entry->now = now->tv64;
221 ), 221 ),
222 222
223 TP_printk("hrtimer %p, now %llu", __entry->timer, 223 TP_printk("hrtimer=%p now=%llu", __entry->hrtimer,
224 (unsigned long long)ktime_to_ns((ktime_t) { 224 (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now }))
225 .tv64 = __entry->now }))
226 ); 225 );
227 226
228/** 227/**
@@ -234,40 +233,40 @@ TRACE_EVENT(hrtimer_expire_entry,
234 */ 233 */
235TRACE_EVENT(hrtimer_expire_exit, 234TRACE_EVENT(hrtimer_expire_exit,
236 235
237 TP_PROTO(struct hrtimer *timer), 236 TP_PROTO(struct hrtimer *hrtimer),
238 237
239 TP_ARGS(timer), 238 TP_ARGS(hrtimer),
240 239
241 TP_STRUCT__entry( 240 TP_STRUCT__entry(
242 __field( void *, timer ) 241 __field( void *, hrtimer )
243 ), 242 ),
244 243
245 TP_fast_assign( 244 TP_fast_assign(
246 __entry->timer = timer; 245 __entry->hrtimer = hrtimer;
247 ), 246 ),
248 247
249 TP_printk("hrtimer %p", __entry->timer) 248 TP_printk("hrtimer=%p", __entry->hrtimer)
250); 249);
251 250
252/** 251/**
253 * hrtimer_cancel - called when the hrtimer is canceled 252 * hrtimer_cancel - called when the hrtimer is canceled
254 * @timer: pointer to struct hrtimer 253 * @hrtimer: pointer to struct hrtimer
255 */ 254 */
256TRACE_EVENT(hrtimer_cancel, 255TRACE_EVENT(hrtimer_cancel,
257 256
258 TP_PROTO(struct hrtimer *timer), 257 TP_PROTO(struct hrtimer *hrtimer),
259 258
260 TP_ARGS(timer), 259 TP_ARGS(hrtimer),
261 260
262 TP_STRUCT__entry( 261 TP_STRUCT__entry(
263 __field( void *, timer ) 262 __field( void *, hrtimer )
264 ), 263 ),
265 264
266 TP_fast_assign( 265 TP_fast_assign(
267 __entry->timer = timer; 266 __entry->hrtimer = hrtimer;
268 ), 267 ),
269 268
270 TP_printk("hrtimer %p", __entry->timer) 269 TP_printk("hrtimer=%p", __entry->hrtimer)
271); 270);
272 271
273/** 272/**
@@ -302,7 +301,7 @@ TRACE_EVENT(itimer_state,
302 __entry->interval_usec = value->it_interval.tv_usec; 301 __entry->interval_usec = value->it_interval.tv_usec;
303 ), 302 ),
304 303
305 TP_printk("which %d, expires %lu, it_value %lu.%lu, it_interval %lu.%lu", 304 TP_printk("which=%d expires=%lu it_value=%lu.%lu it_interval=%lu.%lu",
306 __entry->which, __entry->expires, 305 __entry->which, __entry->expires,
307 __entry->value_sec, __entry->value_usec, 306 __entry->value_sec, __entry->value_usec,
308 __entry->interval_sec, __entry->interval_usec) 307 __entry->interval_sec, __entry->interval_usec)
@@ -332,7 +331,7 @@ TRACE_EVENT(itimer_expire,
332 __entry->pid = pid_nr(pid); 331 __entry->pid = pid_nr(pid);
333 ), 332 ),
334 333
335 TP_printk("which %d, pid %d, now %lu", __entry->which, 334 TP_printk("which=%d pid=%d now=%lu", __entry->which,
336 (int) __entry->pid, __entry->now) 335 (int) __entry->pid, __entry->now)
337); 336);
338 337
diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h
index e4612dbd7ba6..d6c974474e70 100644
--- a/include/trace/events/workqueue.h
+++ b/include/trace/events/workqueue.h
@@ -8,7 +8,7 @@
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/tracepoint.h> 9#include <linux/tracepoint.h>
10 10
11TRACE_EVENT(workqueue_insertion, 11DECLARE_EVENT_CLASS(workqueue,
12 12
13 TP_PROTO(struct task_struct *wq_thread, struct work_struct *work), 13 TP_PROTO(struct task_struct *wq_thread, struct work_struct *work),
14 14
@@ -30,26 +30,18 @@ TRACE_EVENT(workqueue_insertion,
30 __entry->thread_pid, __entry->func) 30 __entry->thread_pid, __entry->func)
31); 31);
32 32
33TRACE_EVENT(workqueue_execution, 33DEFINE_EVENT(workqueue, workqueue_insertion,
34 34
35 TP_PROTO(struct task_struct *wq_thread, struct work_struct *work), 35 TP_PROTO(struct task_struct *wq_thread, struct work_struct *work),
36 36
37 TP_ARGS(wq_thread, work), 37 TP_ARGS(wq_thread, work)
38);
38 39
39 TP_STRUCT__entry( 40DEFINE_EVENT(workqueue, workqueue_execution,
40 __array(char, thread_comm, TASK_COMM_LEN)
41 __field(pid_t, thread_pid)
42 __field(work_func_t, func)
43 ),
44 41
45 TP_fast_assign( 42 TP_PROTO(struct task_struct *wq_thread, struct work_struct *work),
46 memcpy(__entry->thread_comm, wq_thread->comm, TASK_COMM_LEN);
47 __entry->thread_pid = wq_thread->pid;
48 __entry->func = work->func;
49 ),
50 43
51 TP_printk("thread=%s:%d func=%pf", __entry->thread_comm, 44 TP_ARGS(wq_thread, work)
52 __entry->thread_pid, __entry->func)
53); 45);
54 46
55/* Trace the creation of one workqueue thread on a cpu */ 47/* Trace the creation of one workqueue thread on a cpu */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index dacb8ef67000..d1b3de9c1a71 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -18,6 +18,26 @@
18 18
19#include <linux/ftrace_event.h> 19#include <linux/ftrace_event.h>
20 20
21/*
22 * DECLARE_EVENT_CLASS can be used to add a generic function
23 * handlers for events. That is, if all events have the same
24 * parameters and just have distinct trace points.
25 * Each tracepoint can be defined with DEFINE_EVENT and that
26 * will map the DECLARE_EVENT_CLASS to the tracepoint.
27 *
28 * TRACE_EVENT is a one to one mapping between tracepoint and template.
29 */
30#undef TRACE_EVENT
31#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
32 DECLARE_EVENT_CLASS(name, \
33 PARAMS(proto), \
34 PARAMS(args), \
35 PARAMS(tstruct), \
36 PARAMS(assign), \
37 PARAMS(print)); \
38 DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
39
40
21#undef __field 41#undef __field
22#define __field(type, item) type item; 42#define __field(type, item) type item;
23 43
@@ -36,15 +56,21 @@
36#undef TP_STRUCT__entry 56#undef TP_STRUCT__entry
37#define TP_STRUCT__entry(args...) args 57#define TP_STRUCT__entry(args...) args
38 58
39#undef TRACE_EVENT 59#undef DECLARE_EVENT_CLASS
40#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ 60#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
41 struct ftrace_raw_##name { \ 61 struct ftrace_raw_##name { \
42 struct trace_entry ent; \ 62 struct trace_entry ent; \
43 tstruct \ 63 tstruct \
44 char __data[0]; \ 64 char __data[0]; \
45 }; \ 65 };
66#undef DEFINE_EVENT
67#define DEFINE_EVENT(template, name, proto, args) \
46 static struct ftrace_event_call event_##name 68 static struct ftrace_event_call event_##name
47 69
70#undef DEFINE_EVENT_PRINT
71#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
72 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
73
48#undef __cpparg 74#undef __cpparg
49#define __cpparg(arg...) arg 75#define __cpparg(arg...) arg
50 76
@@ -89,12 +115,19 @@
89#undef __string 115#undef __string
90#define __string(item, src) __dynamic_array(char, item, -1) 116#define __string(item, src) __dynamic_array(char, item, -1)
91 117
92#undef TRACE_EVENT 118#undef DECLARE_EVENT_CLASS
93#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 119#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
94 struct ftrace_data_offsets_##call { \ 120 struct ftrace_data_offsets_##call { \
95 tstruct; \ 121 tstruct; \
96 }; 122 };
97 123
124#undef DEFINE_EVENT
125#define DEFINE_EVENT(template, name, proto, args)
126
127#undef DEFINE_EVENT_PRINT
128#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
129 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
130
98#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 131#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
99 132
100/* 133/*
@@ -120,9 +153,10 @@
120#undef __field 153#undef __field
121#define __field(type, item) \ 154#define __field(type, item) \
122 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 155 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
123 "offset:%u;\tsize:%u;\n", \ 156 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
124 (unsigned int)offsetof(typeof(field), item), \ 157 (unsigned int)offsetof(typeof(field), item), \
125 (unsigned int)sizeof(field.item)); \ 158 (unsigned int)sizeof(field.item), \
159 (unsigned int)is_signed_type(type)); \
126 if (!ret) \ 160 if (!ret) \
127 return 0; 161 return 0;
128 162
@@ -132,19 +166,21 @@
132#undef __array 166#undef __array
133#define __array(type, item, len) \ 167#define __array(type, item, len) \
134 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 168 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
135 "offset:%u;\tsize:%u;\n", \ 169 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
136 (unsigned int)offsetof(typeof(field), item), \ 170 (unsigned int)offsetof(typeof(field), item), \
137 (unsigned int)sizeof(field.item)); \ 171 (unsigned int)sizeof(field.item), \
172 (unsigned int)is_signed_type(type)); \
138 if (!ret) \ 173 if (!ret) \
139 return 0; 174 return 0;
140 175
141#undef __dynamic_array 176#undef __dynamic_array
142#define __dynamic_array(type, item, len) \ 177#define __dynamic_array(type, item, len) \
143 ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\ 178 ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\
144 "offset:%u;\tsize:%u;\n", \ 179 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
145 (unsigned int)offsetof(typeof(field), \ 180 (unsigned int)offsetof(typeof(field), \
146 __data_loc_##item), \ 181 __data_loc_##item), \
147 (unsigned int)sizeof(field.__data_loc_##item)); \ 182 (unsigned int)sizeof(field.__data_loc_##item), \
183 (unsigned int)is_signed_type(type)); \
148 if (!ret) \ 184 if (!ret) \
149 return 0; 185 return 0;
150 186
@@ -167,17 +203,50 @@
167#undef TP_perf_assign 203#undef TP_perf_assign
168#define TP_perf_assign(args...) 204#define TP_perf_assign(args...)
169 205
170#undef TRACE_EVENT 206#undef DECLARE_EVENT_CLASS
171#define TRACE_EVENT(call, proto, args, tstruct, func, print) \ 207#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
172static int \ 208static int \
173ftrace_format_##call(struct ftrace_event_call *unused, \ 209ftrace_format_setup_##call(struct ftrace_event_call *unused, \
174 struct trace_seq *s) \ 210 struct trace_seq *s) \
175{ \ 211{ \
176 struct ftrace_raw_##call field __attribute__((unused)); \ 212 struct ftrace_raw_##call field __attribute__((unused)); \
177 int ret = 0; \ 213 int ret = 0; \
178 \ 214 \
179 tstruct; \ 215 tstruct; \
180 \ 216 \
217 return ret; \
218} \
219 \
220static int \
221ftrace_format_##call(struct ftrace_event_call *unused, \
222 struct trace_seq *s) \
223{ \
224 int ret = 0; \
225 \
226 ret = ftrace_format_setup_##call(unused, s); \
227 if (!ret) \
228 return ret; \
229 \
230 ret = trace_seq_printf(s, "\nprint fmt: " print); \
231 \
232 return ret; \
233}
234
235#undef DEFINE_EVENT
236#define DEFINE_EVENT(template, name, proto, args)
237
238#undef DEFINE_EVENT_PRINT
239#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
240static int \
241ftrace_format_##name(struct ftrace_event_call *unused, \
242 struct trace_seq *s) \
243{ \
244 int ret = 0; \
245 \
246 ret = ftrace_format_setup_##template(unused, s); \
247 if (!ret) \
248 return ret; \
249 \
181 trace_seq_printf(s, "\nprint fmt: " print); \ 250 trace_seq_printf(s, "\nprint fmt: " print); \
182 \ 251 \
183 return ret; \ 252 return ret; \
@@ -252,10 +321,11 @@ ftrace_format_##call(struct ftrace_event_call *unused, \
252 ftrace_print_symbols_seq(p, value, symbols); \ 321 ftrace_print_symbols_seq(p, value, symbols); \
253 }) 322 })
254 323
255#undef TRACE_EVENT 324#undef DECLARE_EVENT_CLASS
256#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 325#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
257static enum print_line_t \ 326static enum print_line_t \
258ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ 327ftrace_raw_output_id_##call(int event_id, const char *name, \
328 struct trace_iterator *iter, int flags) \
259{ \ 329{ \
260 struct trace_seq *s = &iter->seq; \ 330 struct trace_seq *s = &iter->seq; \
261 struct ftrace_raw_##call *field; \ 331 struct ftrace_raw_##call *field; \
@@ -265,6 +335,47 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
265 \ 335 \
266 entry = iter->ent; \ 336 entry = iter->ent; \
267 \ 337 \
338 if (entry->type != event_id) { \
339 WARN_ON_ONCE(1); \
340 return TRACE_TYPE_UNHANDLED; \
341 } \
342 \
343 field = (typeof(field))entry; \
344 \
345 p = &get_cpu_var(ftrace_event_seq); \
346 trace_seq_init(p); \
347 ret = trace_seq_printf(s, "%s: ", name); \
348 if (ret) \
349 ret = trace_seq_printf(s, print); \
350 put_cpu(); \
351 if (!ret) \
352 return TRACE_TYPE_PARTIAL_LINE; \
353 \
354 return TRACE_TYPE_HANDLED; \
355}
356
357#undef DEFINE_EVENT
358#define DEFINE_EVENT(template, name, proto, args) \
359static enum print_line_t \
360ftrace_raw_output_##name(struct trace_iterator *iter, int flags) \
361{ \
362 return ftrace_raw_output_id_##template(event_##name.id, \
363 #name, iter, flags); \
364}
365
366#undef DEFINE_EVENT_PRINT
367#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
368static enum print_line_t \
369ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
370{ \
371 struct trace_seq *s = &iter->seq; \
372 struct ftrace_raw_##template *field; \
373 struct trace_entry *entry; \
374 struct trace_seq *p; \
375 int ret; \
376 \
377 entry = iter->ent; \
378 \
268 if (entry->type != event_##call.id) { \ 379 if (entry->type != event_##call.id) { \
269 WARN_ON_ONCE(1); \ 380 WARN_ON_ONCE(1); \
270 return TRACE_TYPE_UNHANDLED; \ 381 return TRACE_TYPE_UNHANDLED; \
@@ -274,14 +385,16 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
274 \ 385 \
275 p = &get_cpu_var(ftrace_event_seq); \ 386 p = &get_cpu_var(ftrace_event_seq); \
276 trace_seq_init(p); \ 387 trace_seq_init(p); \
277 ret = trace_seq_printf(s, #call ": " print); \ 388 ret = trace_seq_printf(s, "%s: ", #call); \
389 if (ret) \
390 ret = trace_seq_printf(s, print); \
278 put_cpu(); \ 391 put_cpu(); \
279 if (!ret) \ 392 if (!ret) \
280 return TRACE_TYPE_PARTIAL_LINE; \ 393 return TRACE_TYPE_PARTIAL_LINE; \
281 \ 394 \
282 return TRACE_TYPE_HANDLED; \ 395 return TRACE_TYPE_HANDLED; \
283} 396}
284 397
285#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 398#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
286 399
287#undef __field_ext 400#undef __field_ext
@@ -315,8 +428,8 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
315#undef __string 428#undef __string
316#define __string(item, src) __dynamic_array(char, item, -1) 429#define __string(item, src) __dynamic_array(char, item, -1)
317 430
318#undef TRACE_EVENT 431#undef DECLARE_EVENT_CLASS
319#define TRACE_EVENT(call, proto, args, tstruct, func, print) \ 432#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
320static int \ 433static int \
321ftrace_define_fields_##call(struct ftrace_event_call *event_call) \ 434ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
322{ \ 435{ \
@@ -332,6 +445,13 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
332 return ret; \ 445 return ret; \
333} 446}
334 447
448#undef DEFINE_EVENT
449#define DEFINE_EVENT(template, name, proto, args)
450
451#undef DEFINE_EVENT_PRINT
452#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
453 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
454
335#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 455#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
336 456
337/* 457/*
@@ -358,10 +478,10 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
358 __data_size += (len) * sizeof(type); 478 __data_size += (len) * sizeof(type);
359 479
360#undef __string 480#undef __string
361#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1) \ 481#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1)
362 482
363#undef TRACE_EVENT 483#undef DECLARE_EVENT_CLASS
364#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 484#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
365static inline int ftrace_get_offsets_##call( \ 485static inline int ftrace_get_offsets_##call( \
366 struct ftrace_data_offsets_##call *__data_offsets, proto) \ 486 struct ftrace_data_offsets_##call *__data_offsets, proto) \
367{ \ 487{ \
@@ -373,6 +493,13 @@ static inline int ftrace_get_offsets_##call( \
373 return __data_size; \ 493 return __data_size; \
374} 494}
375 495
496#undef DEFINE_EVENT
497#define DEFINE_EVENT(template, name, proto, args)
498
499#undef DEFINE_EVENT_PRINT
500#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
501 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
502
376#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 503#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
377 504
378#ifdef CONFIG_EVENT_PROFILE 505#ifdef CONFIG_EVENT_PROFILE
@@ -394,21 +521,28 @@ static inline int ftrace_get_offsets_##call( \
394 * 521 *
395 */ 522 */
396 523
397#undef TRACE_EVENT 524#undef DECLARE_EVENT_CLASS
398#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 525#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)
526
527#undef DEFINE_EVENT
528#define DEFINE_EVENT(template, name, proto, args) \
399 \ 529 \
400static void ftrace_profile_##call(proto); \ 530static void ftrace_profile_##name(proto); \
401 \ 531 \
402static int ftrace_profile_enable_##call(void) \ 532static int ftrace_profile_enable_##name(struct ftrace_event_call *unused)\
403{ \ 533{ \
404 return register_trace_##call(ftrace_profile_##call); \ 534 return register_trace_##name(ftrace_profile_##name); \
405} \ 535} \
406 \ 536 \
407static void ftrace_profile_disable_##call(void) \ 537static void ftrace_profile_disable_##name(struct ftrace_event_call *unused)\
408{ \ 538{ \
409 unregister_trace_##call(ftrace_profile_##call); \ 539 unregister_trace_##name(ftrace_profile_##name); \
410} 540}
411 541
542#undef DEFINE_EVENT_PRINT
543#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
544 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
545
412#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 546#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
413 547
414#endif 548#endif
@@ -423,7 +557,7 @@ static void ftrace_profile_disable_##call(void) \
423 * event_trace_printk(_RET_IP_, "<call>: " <fmt>); 557 * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
424 * } 558 * }
425 * 559 *
426 * static int ftrace_reg_event_<call>(void) 560 * static int ftrace_reg_event_<call>(struct ftrace_event_call *unused)
427 * { 561 * {
428 * int ret; 562 * int ret;
429 * 563 *
@@ -434,7 +568,7 @@ static void ftrace_profile_disable_##call(void) \
434 * return ret; 568 * return ret;
435 * } 569 * }
436 * 570 *
437 * static void ftrace_unreg_event_<call>(void) 571 * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
438 * { 572 * {
439 * unregister_trace_<call>(ftrace_event_<call>); 573 * unregister_trace_<call>(ftrace_event_<call>);
440 * } 574 * }
@@ -469,7 +603,7 @@ static void ftrace_profile_disable_##call(void) \
469 * trace_current_buffer_unlock_commit(buffer, event, irq_flags, pc); 603 * trace_current_buffer_unlock_commit(buffer, event, irq_flags, pc);
470 * } 604 * }
471 * 605 *
472 * static int ftrace_raw_reg_event_<call>(void) 606 * static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused)
473 * { 607 * {
474 * int ret; 608 * int ret;
475 * 609 *
@@ -480,7 +614,7 @@ static void ftrace_profile_disable_##call(void) \
480 * return ret; 614 * return ret;
481 * } 615 * }
482 * 616 *
483 * static void ftrace_unreg_event_<call>(void) 617 * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
484 * { 618 * {
485 * unregister_trace_<call>(ftrace_raw_event_<call>); 619 * unregister_trace_<call>(ftrace_raw_event_<call>);
486 * } 620 * }
@@ -489,7 +623,7 @@ static void ftrace_profile_disable_##call(void) \
489 * .trace = ftrace_raw_output_<call>, <-- stage 2 623 * .trace = ftrace_raw_output_<call>, <-- stage 2
490 * }; 624 * };
491 * 625 *
492 * static int ftrace_raw_init_event_<call>(void) 626 * static int ftrace_raw_init_event_<call>(struct ftrace_event_call *unused)
493 * { 627 * {
494 * int id; 628 * int id;
495 * 629 *
@@ -547,15 +681,13 @@ static void ftrace_profile_disable_##call(void) \
547#define __assign_str(dst, src) \ 681#define __assign_str(dst, src) \
548 strcpy(__get_str(dst), src); 682 strcpy(__get_str(dst), src);
549 683
550#undef TRACE_EVENT 684#undef DECLARE_EVENT_CLASS
551#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 685#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
552 \ 686 \
553static struct ftrace_event_call event_##call; \ 687static void ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \
554 \ 688 proto) \
555static void ftrace_raw_event_##call(proto) \
556{ \ 689{ \
557 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ 690 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
558 struct ftrace_event_call *event_call = &event_##call; \
559 struct ring_buffer_event *event; \ 691 struct ring_buffer_event *event; \
560 struct ftrace_raw_##call *entry; \ 692 struct ftrace_raw_##call *entry; \
561 struct ring_buffer *buffer; \ 693 struct ring_buffer *buffer; \
@@ -569,7 +701,7 @@ static void ftrace_raw_event_##call(proto) \
569 __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \ 701 __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
570 \ 702 \
571 event = trace_current_buffer_lock_reserve(&buffer, \ 703 event = trace_current_buffer_lock_reserve(&buffer, \
572 event_##call.id, \ 704 event_call->id, \
573 sizeof(*entry) + __data_size, \ 705 sizeof(*entry) + __data_size, \
574 irq_flags, pc); \ 706 irq_flags, pc); \
575 if (!event) \ 707 if (!event) \
@@ -584,9 +716,17 @@ static void ftrace_raw_event_##call(proto) \
584 if (!filter_current_check_discard(buffer, event_call, entry, event)) \ 716 if (!filter_current_check_discard(buffer, event_call, entry, event)) \
585 trace_nowake_buffer_unlock_commit(buffer, \ 717 trace_nowake_buffer_unlock_commit(buffer, \
586 event, irq_flags, pc); \ 718 event, irq_flags, pc); \
719}
720
721#undef DEFINE_EVENT
722#define DEFINE_EVENT(template, call, proto, args) \
723 \
724static void ftrace_raw_event_##call(proto) \
725{ \
726 ftrace_raw_event_id_##template(&event_##call, args); \
587} \ 727} \
588 \ 728 \
589static int ftrace_raw_reg_event_##call(void *ptr) \ 729static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
590{ \ 730{ \
591 int ret; \ 731 int ret; \
592 \ 732 \
@@ -597,7 +737,7 @@ static int ftrace_raw_reg_event_##call(void *ptr) \
597 return ret; \ 737 return ret; \
598} \ 738} \
599 \ 739 \
600static void ftrace_raw_unreg_event_##call(void *ptr) \ 740static void ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused)\
601{ \ 741{ \
602 unregister_trace_##call(ftrace_raw_event_##call); \ 742 unregister_trace_##call(ftrace_raw_event_##call); \
603} \ 743} \
@@ -606,7 +746,7 @@ static struct trace_event ftrace_event_type_##call = { \
606 .trace = ftrace_raw_output_##call, \ 746 .trace = ftrace_raw_output_##call, \
607}; \ 747}; \
608 \ 748 \
609static int ftrace_raw_init_event_##call(void) \ 749static int ftrace_raw_init_event_##call(struct ftrace_event_call *unused)\
610{ \ 750{ \
611 int id; \ 751 int id; \
612 \ 752 \
@@ -616,7 +756,36 @@ static int ftrace_raw_init_event_##call(void) \
616 event_##call.id = id; \ 756 event_##call.id = id; \
617 INIT_LIST_HEAD(&event_##call.fields); \ 757 INIT_LIST_HEAD(&event_##call.fields); \
618 return 0; \ 758 return 0; \
619} \ 759}
760
761#undef DEFINE_EVENT_PRINT
762#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
763 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
764
765#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
766
767#undef DECLARE_EVENT_CLASS
768#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)
769
770#undef DEFINE_EVENT
771#define DEFINE_EVENT(template, call, proto, args) \
772 \
773static struct ftrace_event_call __used \
774__attribute__((__aligned__(4))) \
775__attribute__((section("_ftrace_events"))) event_##call = { \
776 .name = #call, \
777 .system = __stringify(TRACE_SYSTEM), \
778 .event = &ftrace_event_type_##call, \
779 .raw_init = ftrace_raw_init_event_##call, \
780 .regfunc = ftrace_raw_reg_event_##call, \
781 .unregfunc = ftrace_raw_unreg_event_##call, \
782 .show_format = ftrace_format_##template, \
783 .define_fields = ftrace_define_fields_##template, \
784 _TRACE_PROFILE_INIT(call) \
785}
786
787#undef DEFINE_EVENT_PRINT
788#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
620 \ 789 \
621static struct ftrace_event_call __used \ 790static struct ftrace_event_call __used \
622__attribute__((__aligned__(4))) \ 791__attribute__((__aligned__(4))) \
@@ -628,7 +797,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
628 .regfunc = ftrace_raw_reg_event_##call, \ 797 .regfunc = ftrace_raw_reg_event_##call, \
629 .unregfunc = ftrace_raw_unreg_event_##call, \ 798 .unregfunc = ftrace_raw_unreg_event_##call, \
630 .show_format = ftrace_format_##call, \ 799 .show_format = ftrace_format_##call, \
631 .define_fields = ftrace_define_fields_##call, \ 800 .define_fields = ftrace_define_fields_##template, \
632 _TRACE_PROFILE_INIT(call) \ 801 _TRACE_PROFILE_INIT(call) \
633} 802}
634 803
@@ -646,6 +815,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
646 * struct ftrace_event_call *event_call = &event_<call>; 815 * struct ftrace_event_call *event_call = &event_<call>;
647 * extern void perf_tp_event(int, u64, u64, void *, int); 816 * extern void perf_tp_event(int, u64, u64, void *, int);
648 * struct ftrace_raw_##call *entry; 817 * struct ftrace_raw_##call *entry;
818 * struct perf_trace_buf *trace_buf;
649 * u64 __addr = 0, __count = 1; 819 * u64 __addr = 0, __count = 1;
650 * unsigned long irq_flags; 820 * unsigned long irq_flags;
651 * struct trace_entry *ent; 821 * struct trace_entry *ent;
@@ -670,14 +840,25 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
670 * __cpu = smp_processor_id(); 840 * __cpu = smp_processor_id();
671 * 841 *
672 * if (in_nmi()) 842 * if (in_nmi())
673 * raw_data = rcu_dereference(trace_profile_buf_nmi); 843 * trace_buf = rcu_dereference(perf_trace_buf_nmi);
674 * else 844 * else
675 * raw_data = rcu_dereference(trace_profile_buf); 845 * trace_buf = rcu_dereference(perf_trace_buf);
676 * 846 *
677 * if (!raw_data) 847 * if (!trace_buf)
678 * goto end; 848 * goto end;
679 * 849 *
680 * raw_data = per_cpu_ptr(raw_data, __cpu); 850 * trace_buf = per_cpu_ptr(trace_buf, __cpu);
851 *
852 * // Avoid recursion from perf that could mess up the buffer
853 * if (trace_buf->recursion++)
854 * goto end_recursion;
855 *
856 * raw_data = trace_buf->buf;
857 *
858 * // Make recursion update visible before entering perf_tp_event
859 * // so that we protect from perf recursions.
860 *
861 * barrier();
681 * 862 *
682 * //zero dead bytes from alignment to avoid stack leak to userspace: 863 * //zero dead bytes from alignment to avoid stack leak to userspace:
683 * *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; 864 * *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
@@ -704,21 +885,26 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
704#undef __perf_count 885#undef __perf_count
705#define __perf_count(c) __count = (c) 886#define __perf_count(c) __count = (c)
706 887
707#undef TRACE_EVENT 888#undef DECLARE_EVENT_CLASS
708#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 889#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
709static void ftrace_profile_##call(proto) \ 890static void \
891ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \
892 proto) \
710{ \ 893{ \
711 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ 894 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
712 struct ftrace_event_call *event_call = &event_##call; \ 895 extern int perf_swevent_get_recursion_context(void); \
713 extern void perf_tp_event(int, u64, u64, void *, int); \ 896 extern void perf_swevent_put_recursion_context(int rctx); \
897 extern void perf_tp_event(int, u64, u64, void *, int); \
714 struct ftrace_raw_##call *entry; \ 898 struct ftrace_raw_##call *entry; \
715 u64 __addr = 0, __count = 1; \ 899 u64 __addr = 0, __count = 1; \
716 unsigned long irq_flags; \ 900 unsigned long irq_flags; \
717 struct trace_entry *ent; \ 901 struct trace_entry *ent; \
718 int __entry_size; \ 902 int __entry_size; \
719 int __data_size; \ 903 int __data_size; \
904 char *trace_buf; \
720 char *raw_data; \ 905 char *raw_data; \
721 int __cpu; \ 906 int __cpu; \
907 int rctx; \
722 int pc; \ 908 int pc; \
723 \ 909 \
724 pc = preempt_count(); \ 910 pc = preempt_count(); \
@@ -733,17 +919,22 @@ static void ftrace_profile_##call(proto) \
733 return; \ 919 return; \
734 \ 920 \
735 local_irq_save(irq_flags); \ 921 local_irq_save(irq_flags); \
922 \
923 rctx = perf_swevent_get_recursion_context(); \
924 if (rctx < 0) \
925 goto end_recursion; \
926 \
736 __cpu = smp_processor_id(); \ 927 __cpu = smp_processor_id(); \
737 \ 928 \
738 if (in_nmi()) \ 929 if (in_nmi()) \
739 raw_data = rcu_dereference(trace_profile_buf_nmi); \ 930 trace_buf = rcu_dereference(perf_trace_buf_nmi); \
740 else \ 931 else \
741 raw_data = rcu_dereference(trace_profile_buf); \ 932 trace_buf = rcu_dereference(perf_trace_buf); \
742 \ 933 \
743 if (!raw_data) \ 934 if (!trace_buf) \
744 goto end; \ 935 goto end; \
745 \ 936 \
746 raw_data = per_cpu_ptr(raw_data, __cpu); \ 937 raw_data = per_cpu_ptr(trace_buf, __cpu); \
747 \ 938 \
748 *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \ 939 *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
749 entry = (struct ftrace_raw_##call *)raw_data; \ 940 entry = (struct ftrace_raw_##call *)raw_data; \
@@ -759,10 +950,25 @@ static void ftrace_profile_##call(proto) \
759 __entry_size); \ 950 __entry_size); \
760 \ 951 \
761end: \ 952end: \
953 perf_swevent_put_recursion_context(rctx); \
954end_recursion: \
762 local_irq_restore(irq_flags); \ 955 local_irq_restore(irq_flags); \
763 \ 956 \
764} 957}
765 958
959#undef DEFINE_EVENT
960#define DEFINE_EVENT(template, call, proto, args) \
961static void ftrace_profile_##call(proto) \
962{ \
963 struct ftrace_event_call *event_call = &event_##call; \
964 \
965 ftrace_profile_templ_##template(event_call, args); \
966}
967
968#undef DEFINE_EVENT_PRINT
969#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
970 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
971
766#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 972#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
767#endif /* CONFIG_EVENT_PROFILE */ 973#endif /* CONFIG_EVENT_PROFILE */
768 974
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index e972f0a40f8d..961fda3556bb 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -12,21 +12,19 @@
12 * A syscall entry in the ftrace syscalls array. 12 * A syscall entry in the ftrace syscalls array.
13 * 13 *
14 * @name: name of the syscall 14 * @name: name of the syscall
15 * @syscall_nr: number of the syscall
15 * @nb_args: number of parameters it takes 16 * @nb_args: number of parameters it takes
16 * @types: list of types as strings 17 * @types: list of types as strings
17 * @args: list of args as strings (args[i] matches types[i]) 18 * @args: list of args as strings (args[i] matches types[i])
18 * @enter_id: associated ftrace enter event id
19 * @exit_id: associated ftrace exit event id
20 * @enter_event: associated syscall_enter trace event 19 * @enter_event: associated syscall_enter trace event
21 * @exit_event: associated syscall_exit trace event 20 * @exit_event: associated syscall_exit trace event
22 */ 21 */
23struct syscall_metadata { 22struct syscall_metadata {
24 const char *name; 23 const char *name;
24 int syscall_nr;
25 int nb_args; 25 int nb_args;
26 const char **types; 26 const char **types;
27 const char **args; 27 const char **args;
28 int enter_id;
29 int exit_id;
30 28
31 struct ftrace_event_call *enter_event; 29 struct ftrace_event_call *enter_event;
32 struct ftrace_event_call *exit_event; 30 struct ftrace_event_call *exit_event;
@@ -34,29 +32,28 @@ struct syscall_metadata {
34 32
35#ifdef CONFIG_FTRACE_SYSCALLS 33#ifdef CONFIG_FTRACE_SYSCALLS
36extern unsigned long arch_syscall_addr(int nr); 34extern unsigned long arch_syscall_addr(int nr);
37extern int syscall_name_to_nr(char *name); 35extern int init_syscall_trace(struct ftrace_event_call *call);
38void set_syscall_enter_id(int num, int id); 36
39void set_syscall_exit_id(int num, int id);
40extern struct trace_event event_syscall_enter;
41extern struct trace_event event_syscall_exit;
42extern int reg_event_syscall_enter(void *ptr);
43extern void unreg_event_syscall_enter(void *ptr);
44extern int reg_event_syscall_exit(void *ptr);
45extern void unreg_event_syscall_exit(void *ptr);
46extern int syscall_enter_format(struct ftrace_event_call *call, 37extern int syscall_enter_format(struct ftrace_event_call *call,
47 struct trace_seq *s); 38 struct trace_seq *s);
48extern int syscall_exit_format(struct ftrace_event_call *call, 39extern int syscall_exit_format(struct ftrace_event_call *call,
49 struct trace_seq *s); 40 struct trace_seq *s);
50extern int syscall_enter_define_fields(struct ftrace_event_call *call); 41extern int syscall_enter_define_fields(struct ftrace_event_call *call);
51extern int syscall_exit_define_fields(struct ftrace_event_call *call); 42extern int syscall_exit_define_fields(struct ftrace_event_call *call);
43extern int reg_event_syscall_enter(struct ftrace_event_call *call);
44extern void unreg_event_syscall_enter(struct ftrace_event_call *call);
45extern int reg_event_syscall_exit(struct ftrace_event_call *call);
46extern void unreg_event_syscall_exit(struct ftrace_event_call *call);
47extern int
48ftrace_format_syscall(struct ftrace_event_call *call, struct trace_seq *s);
52enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags); 49enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
53enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags); 50enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
54#endif 51#endif
55#ifdef CONFIG_EVENT_PROFILE 52#ifdef CONFIG_EVENT_PROFILE
56int reg_prof_syscall_enter(char *name); 53int prof_sysenter_enable(struct ftrace_event_call *call);
57void unreg_prof_syscall_enter(char *name); 54void prof_sysenter_disable(struct ftrace_event_call *call);
58int reg_prof_syscall_exit(char *name); 55int prof_sysexit_enable(struct ftrace_event_call *call);
59void unreg_prof_syscall_exit(char *name); 56void prof_sysexit_disable(struct ftrace_event_call *call);
60 57
61#endif 58#endif
62 59
diff --git a/init/Kconfig b/init/Kconfig
index 9ee778294756..38899243213d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -763,6 +763,7 @@ config UID16
763 763
764config SYSCTL_SYSCALL 764config SYSCTL_SYSCALL
765 bool "Sysctl syscall support" if EMBEDDED 765 bool "Sysctl syscall support" if EMBEDDED
766 depends on PROC_SYSCTL
766 default y 767 default y
767 select SYSCTL 768 select SYSCTL
768 ---help--- 769 ---help---
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 7d3704750efc..56410faa4550 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -129,136 +129,60 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
129#define proc_ipcauto_dointvec_minmax NULL 129#define proc_ipcauto_dointvec_minmax NULL
130#endif 130#endif
131 131
132#ifdef CONFIG_SYSCTL_SYSCALL
133/* The generic sysctl ipc data routine. */
134static int sysctl_ipc_data(ctl_table *table,
135 void __user *oldval, size_t __user *oldlenp,
136 void __user *newval, size_t newlen)
137{
138 size_t len;
139 void *data;
140
141 /* Get out of I don't have a variable */
142 if (!table->data || !table->maxlen)
143 return -ENOTDIR;
144
145 data = get_ipc(table);
146 if (!data)
147 return -ENOTDIR;
148
149 if (oldval && oldlenp) {
150 if (get_user(len, oldlenp))
151 return -EFAULT;
152 if (len) {
153 if (len > table->maxlen)
154 len = table->maxlen;
155 if (copy_to_user(oldval, data, len))
156 return -EFAULT;
157 if (put_user(len, oldlenp))
158 return -EFAULT;
159 }
160 }
161
162 if (newval && newlen) {
163 if (newlen > table->maxlen)
164 newlen = table->maxlen;
165
166 if (copy_from_user(data, newval, newlen))
167 return -EFAULT;
168 }
169 return 1;
170}
171
172static int sysctl_ipc_registered_data(ctl_table *table,
173 void __user *oldval, size_t __user *oldlenp,
174 void __user *newval, size_t newlen)
175{
176 int rc;
177
178 rc = sysctl_ipc_data(table, oldval, oldlenp, newval, newlen);
179
180 if (newval && newlen && rc > 0)
181 /*
182 * Tunable has successfully been changed from userland
183 */
184 unregister_ipcns_notifier(current->nsproxy->ipc_ns);
185
186 return rc;
187}
188#else
189#define sysctl_ipc_data NULL
190#define sysctl_ipc_registered_data NULL
191#endif
192
193static int zero; 132static int zero;
194static int one = 1; 133static int one = 1;
195 134
196static struct ctl_table ipc_kern_table[] = { 135static struct ctl_table ipc_kern_table[] = {
197 { 136 {
198 .ctl_name = KERN_SHMMAX,
199 .procname = "shmmax", 137 .procname = "shmmax",
200 .data = &init_ipc_ns.shm_ctlmax, 138 .data = &init_ipc_ns.shm_ctlmax,
201 .maxlen = sizeof (init_ipc_ns.shm_ctlmax), 139 .maxlen = sizeof (init_ipc_ns.shm_ctlmax),
202 .mode = 0644, 140 .mode = 0644,
203 .proc_handler = proc_ipc_doulongvec_minmax, 141 .proc_handler = proc_ipc_doulongvec_minmax,
204 .strategy = sysctl_ipc_data,
205 }, 142 },
206 { 143 {
207 .ctl_name = KERN_SHMALL,
208 .procname = "shmall", 144 .procname = "shmall",
209 .data = &init_ipc_ns.shm_ctlall, 145 .data = &init_ipc_ns.shm_ctlall,
210 .maxlen = sizeof (init_ipc_ns.shm_ctlall), 146 .maxlen = sizeof (init_ipc_ns.shm_ctlall),
211 .mode = 0644, 147 .mode = 0644,
212 .proc_handler = proc_ipc_doulongvec_minmax, 148 .proc_handler = proc_ipc_doulongvec_minmax,
213 .strategy = sysctl_ipc_data,
214 }, 149 },
215 { 150 {
216 .ctl_name = KERN_SHMMNI,
217 .procname = "shmmni", 151 .procname = "shmmni",
218 .data = &init_ipc_ns.shm_ctlmni, 152 .data = &init_ipc_ns.shm_ctlmni,
219 .maxlen = sizeof (init_ipc_ns.shm_ctlmni), 153 .maxlen = sizeof (init_ipc_ns.shm_ctlmni),
220 .mode = 0644, 154 .mode = 0644,
221 .proc_handler = proc_ipc_dointvec, 155 .proc_handler = proc_ipc_dointvec,
222 .strategy = sysctl_ipc_data,
223 }, 156 },
224 { 157 {
225 .ctl_name = KERN_MSGMAX,
226 .procname = "msgmax", 158 .procname = "msgmax",
227 .data = &init_ipc_ns.msg_ctlmax, 159 .data = &init_ipc_ns.msg_ctlmax,
228 .maxlen = sizeof (init_ipc_ns.msg_ctlmax), 160 .maxlen = sizeof (init_ipc_ns.msg_ctlmax),
229 .mode = 0644, 161 .mode = 0644,
230 .proc_handler = proc_ipc_dointvec, 162 .proc_handler = proc_ipc_dointvec,
231 .strategy = sysctl_ipc_data,
232 }, 163 },
233 { 164 {
234 .ctl_name = KERN_MSGMNI,
235 .procname = "msgmni", 165 .procname = "msgmni",
236 .data = &init_ipc_ns.msg_ctlmni, 166 .data = &init_ipc_ns.msg_ctlmni,
237 .maxlen = sizeof (init_ipc_ns.msg_ctlmni), 167 .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
238 .mode = 0644, 168 .mode = 0644,
239 .proc_handler = proc_ipc_callback_dointvec, 169 .proc_handler = proc_ipc_callback_dointvec,
240 .strategy = sysctl_ipc_registered_data,
241 }, 170 },
242 { 171 {
243 .ctl_name = KERN_MSGMNB,
244 .procname = "msgmnb", 172 .procname = "msgmnb",
245 .data = &init_ipc_ns.msg_ctlmnb, 173 .data = &init_ipc_ns.msg_ctlmnb,
246 .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), 174 .maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
247 .mode = 0644, 175 .mode = 0644,
248 .proc_handler = proc_ipc_dointvec, 176 .proc_handler = proc_ipc_dointvec,
249 .strategy = sysctl_ipc_data,
250 }, 177 },
251 { 178 {
252 .ctl_name = KERN_SEM,
253 .procname = "sem", 179 .procname = "sem",
254 .data = &init_ipc_ns.sem_ctls, 180 .data = &init_ipc_ns.sem_ctls,
255 .maxlen = 4*sizeof (int), 181 .maxlen = 4*sizeof (int),
256 .mode = 0644, 182 .mode = 0644,
257 .proc_handler = proc_ipc_dointvec, 183 .proc_handler = proc_ipc_dointvec,
258 .strategy = sysctl_ipc_data,
259 }, 184 },
260 { 185 {
261 .ctl_name = CTL_UNNUMBERED,
262 .procname = "auto_msgmni", 186 .procname = "auto_msgmni",
263 .data = &init_ipc_ns.auto_msgmni, 187 .data = &init_ipc_ns.auto_msgmni,
264 .maxlen = sizeof(int), 188 .maxlen = sizeof(int),
@@ -272,7 +196,6 @@ static struct ctl_table ipc_kern_table[] = {
272 196
273static struct ctl_table ipc_root_table[] = { 197static struct ctl_table ipc_root_table[] = {
274 { 198 {
275 .ctl_name = CTL_KERN,
276 .procname = "kernel", 199 .procname = "kernel",
277 .mode = 0555, 200 .mode = 0555,
278 .child = ipc_kern_table, 201 .child = ipc_kern_table,
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 8a058711fc10..0c09366b96f3 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -88,7 +88,7 @@ static ctl_table mq_sysctls[] = {
88 .extra1 = &msg_maxsize_limit_min, 88 .extra1 = &msg_maxsize_limit_min,
89 .extra2 = &msg_maxsize_limit_max, 89 .extra2 = &msg_maxsize_limit_max,
90 }, 90 },
91 { .ctl_name = 0 } 91 {}
92}; 92};
93 93
94static ctl_table mq_sysctl_dir[] = { 94static ctl_table mq_sysctl_dir[] = {
@@ -97,17 +97,16 @@ static ctl_table mq_sysctl_dir[] = {
97 .mode = 0555, 97 .mode = 0555,
98 .child = mq_sysctls, 98 .child = mq_sysctls,
99 }, 99 },
100 { .ctl_name = 0 } 100 {}
101}; 101};
102 102
103static ctl_table mq_sysctl_root[] = { 103static ctl_table mq_sysctl_root[] = {
104 { 104 {
105 .ctl_name = CTL_FS,
106 .procname = "fs", 105 .procname = "fs",
107 .mode = 0555, 106 .mode = 0555,
108 .child = mq_sysctl_dir, 107 .child = mq_sysctl_dir,
109 }, 108 },
110 { .ctl_name = 0 } 109 {}
111}; 110};
112 111
113struct ctl_table_header *mq_register_sysctl_table(void) 112struct ctl_table_header *mq_register_sysctl_table(void)
diff --git a/kernel/Makefile b/kernel/Makefile
index dcf6789bf547..9943202b4355 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ 5obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
6 cpu.o exit.o itimer.o time.o softirq.o resource.o \ 6 cpu.o exit.o itimer.o time.o softirq.o resource.o \
7 sysctl.o capability.o ptrace.o timer.o user.o \ 7 sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
8 signal.o sys.o kmod.o workqueue.o pid.o \ 8 signal.o sys.o kmod.o workqueue.o pid.o \
9 rcupdate.o extable.o params.o posix-timers.o \ 9 rcupdate.o extable.o params.o posix-timers.o \
10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ 10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_mutex-debug.o = -pg
21CFLAGS_REMOVE_rtmutex-debug.o = -pg 21CFLAGS_REMOVE_rtmutex-debug.o = -pg
22CFLAGS_REMOVE_cgroup-debug.o = -pg 22CFLAGS_REMOVE_cgroup-debug.o = -pg
23CFLAGS_REMOVE_sched_clock.o = -pg 23CFLAGS_REMOVE_sched_clock.o = -pg
24CFLAGS_REMOVE_perf_event.o = -pg
24endif 25endif
25 26
26obj-$(CONFIG_FREEZER) += freezer.o 27obj-$(CONFIG_FREEZER) += freezer.o
@@ -97,6 +98,7 @@ obj-$(CONFIG_SMP) += sched_cpupri.o
97obj-$(CONFIG_SLOW_WORK) += slow-work.o 98obj-$(CONFIG_SLOW_WORK) += slow-work.o
98obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o 99obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o
99obj-$(CONFIG_PERF_EVENTS) += perf_event.o 100obj-$(CONFIG_PERF_EVENTS) += perf_event.o
101obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
100 102
101ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) 103ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
102# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is 104# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index b5cb469d2545..3cf2183b472d 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -537,8 +537,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
537 * element of the partition (one sched domain) to be passed to 537 * element of the partition (one sched domain) to be passed to
538 * partition_sched_domains(). 538 * partition_sched_domains().
539 */ 539 */
540/* FIXME: see the FIXME in partition_sched_domains() */ 540static int generate_sched_domains(cpumask_var_t **domains,
541static int generate_sched_domains(struct cpumask **domains,
542 struct sched_domain_attr **attributes) 541 struct sched_domain_attr **attributes)
543{ 542{
544 LIST_HEAD(q); /* queue of cpusets to be scanned */ 543 LIST_HEAD(q); /* queue of cpusets to be scanned */
@@ -546,7 +545,7 @@ static int generate_sched_domains(struct cpumask **domains,
546 struct cpuset **csa; /* array of all cpuset ptrs */ 545 struct cpuset **csa; /* array of all cpuset ptrs */
547 int csn; /* how many cpuset ptrs in csa so far */ 546 int csn; /* how many cpuset ptrs in csa so far */
548 int i, j, k; /* indices for partition finding loops */ 547 int i, j, k; /* indices for partition finding loops */
549 struct cpumask *doms; /* resulting partition; i.e. sched domains */ 548 cpumask_var_t *doms; /* resulting partition; i.e. sched domains */
550 struct sched_domain_attr *dattr; /* attributes for custom domains */ 549 struct sched_domain_attr *dattr; /* attributes for custom domains */
551 int ndoms = 0; /* number of sched domains in result */ 550 int ndoms = 0; /* number of sched domains in result */
552 int nslot; /* next empty doms[] struct cpumask slot */ 551 int nslot; /* next empty doms[] struct cpumask slot */
@@ -557,7 +556,8 @@ static int generate_sched_domains(struct cpumask **domains,
557 556
558 /* Special case for the 99% of systems with one, full, sched domain */ 557 /* Special case for the 99% of systems with one, full, sched domain */
559 if (is_sched_load_balance(&top_cpuset)) { 558 if (is_sched_load_balance(&top_cpuset)) {
560 doms = kmalloc(cpumask_size(), GFP_KERNEL); 559 ndoms = 1;
560 doms = alloc_sched_domains(ndoms);
561 if (!doms) 561 if (!doms)
562 goto done; 562 goto done;
563 563
@@ -566,9 +566,8 @@ static int generate_sched_domains(struct cpumask **domains,
566 *dattr = SD_ATTR_INIT; 566 *dattr = SD_ATTR_INIT;
567 update_domain_attr_tree(dattr, &top_cpuset); 567 update_domain_attr_tree(dattr, &top_cpuset);
568 } 568 }
569 cpumask_copy(doms, top_cpuset.cpus_allowed); 569 cpumask_copy(doms[0], top_cpuset.cpus_allowed);
570 570
571 ndoms = 1;
572 goto done; 571 goto done;
573 } 572 }
574 573
@@ -636,7 +635,7 @@ restart:
636 * Now we know how many domains to create. 635 * Now we know how many domains to create.
637 * Convert <csn, csa> to <ndoms, doms> and populate cpu masks. 636 * Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
638 */ 637 */
639 doms = kmalloc(ndoms * cpumask_size(), GFP_KERNEL); 638 doms = alloc_sched_domains(ndoms);
640 if (!doms) 639 if (!doms)
641 goto done; 640 goto done;
642 641
@@ -656,7 +655,7 @@ restart:
656 continue; 655 continue;
657 } 656 }
658 657
659 dp = doms + nslot; 658 dp = doms[nslot];
660 659
661 if (nslot == ndoms) { 660 if (nslot == ndoms) {
662 static int warnings = 10; 661 static int warnings = 10;
@@ -718,7 +717,7 @@ done:
718static void do_rebuild_sched_domains(struct work_struct *unused) 717static void do_rebuild_sched_domains(struct work_struct *unused)
719{ 718{
720 struct sched_domain_attr *attr; 719 struct sched_domain_attr *attr;
721 struct cpumask *doms; 720 cpumask_var_t *doms;
722 int ndoms; 721 int ndoms;
723 722
724 get_online_cpus(); 723 get_online_cpus();
@@ -2052,7 +2051,7 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
2052 unsigned long phase, void *unused_cpu) 2051 unsigned long phase, void *unused_cpu)
2053{ 2052{
2054 struct sched_domain_attr *attr; 2053 struct sched_domain_attr *attr;
2055 struct cpumask *doms; 2054 cpumask_var_t *doms;
2056 int ndoms; 2055 int ndoms;
2057 2056
2058 switch (phase) { 2057 switch (phase) {
@@ -2537,15 +2536,9 @@ const struct file_operations proc_cpuset_operations = {
2537}; 2536};
2538#endif /* CONFIG_PROC_PID_CPUSET */ 2537#endif /* CONFIG_PROC_PID_CPUSET */
2539 2538
2540/* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */ 2539/* Display task mems_allowed in /proc/<pid>/status file. */
2541void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task) 2540void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task)
2542{ 2541{
2543 seq_printf(m, "Cpus_allowed:\t");
2544 seq_cpumask(m, &task->cpus_allowed);
2545 seq_printf(m, "\n");
2546 seq_printf(m, "Cpus_allowed_list:\t");
2547 seq_cpumask_list(m, &task->cpus_allowed);
2548 seq_printf(m, "\n");
2549 seq_printf(m, "Mems_allowed:\t"); 2542 seq_printf(m, "Mems_allowed:\t");
2550 seq_nodemask(m, &task->mems_allowed); 2543 seq_nodemask(m, &task->mems_allowed);
2551 seq_printf(m, "\n"); 2544 seq_printf(m, "\n");
diff --git a/kernel/exit.c b/kernel/exit.c
index f7864ac2ecc1..80ae941cfd2e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -49,6 +49,7 @@
49#include <linux/init_task.h> 49#include <linux/init_task.h>
50#include <linux/perf_event.h> 50#include <linux/perf_event.h>
51#include <trace/events/sched.h> 51#include <trace/events/sched.h>
52#include <linux/hw_breakpoint.h>
52 53
53#include <asm/uaccess.h> 54#include <asm/uaccess.h>
54#include <asm/unistd.h> 55#include <asm/unistd.h>
@@ -110,9 +111,9 @@ static void __exit_signal(struct task_struct *tsk)
110 * We won't ever get here for the group leader, since it 111 * We won't ever get here for the group leader, since it
111 * will have been the last reference on the signal_struct. 112 * will have been the last reference on the signal_struct.
112 */ 113 */
113 sig->utime = cputime_add(sig->utime, task_utime(tsk)); 114 sig->utime = cputime_add(sig->utime, tsk->utime);
114 sig->stime = cputime_add(sig->stime, task_stime(tsk)); 115 sig->stime = cputime_add(sig->stime, tsk->stime);
115 sig->gtime = cputime_add(sig->gtime, task_gtime(tsk)); 116 sig->gtime = cputime_add(sig->gtime, tsk->gtime);
116 sig->min_flt += tsk->min_flt; 117 sig->min_flt += tsk->min_flt;
117 sig->maj_flt += tsk->maj_flt; 118 sig->maj_flt += tsk->maj_flt;
118 sig->nvcsw += tsk->nvcsw; 119 sig->nvcsw += tsk->nvcsw;
@@ -978,6 +979,10 @@ NORET_TYPE void do_exit(long code)
978 proc_exit_connector(tsk); 979 proc_exit_connector(tsk);
979 980
980 /* 981 /*
982 * FIXME: do that only when needed, using sched_exit tracepoint
983 */
984 flush_ptrace_hw_breakpoint(tsk);
985 /*
981 * Flush inherited counters to the parent - before the parent 986 * Flush inherited counters to the parent - before the parent
982 * gets woken up by child-exit notifications. 987 * gets woken up by child-exit notifications.
983 */ 988 */
@@ -1205,6 +1210,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1205 struct signal_struct *psig; 1210 struct signal_struct *psig;
1206 struct signal_struct *sig; 1211 struct signal_struct *sig;
1207 unsigned long maxrss; 1212 unsigned long maxrss;
1213 cputime_t tgutime, tgstime;
1208 1214
1209 /* 1215 /*
1210 * The resource counters for the group leader are in its 1216 * The resource counters for the group leader are in its
@@ -1220,20 +1226,23 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1220 * need to protect the access to parent->signal fields, 1226 * need to protect the access to parent->signal fields,
1221 * as other threads in the parent group can be right 1227 * as other threads in the parent group can be right
1222 * here reaping other children at the same time. 1228 * here reaping other children at the same time.
1229 *
1230 * We use thread_group_times() to get times for the thread
1231 * group, which consolidates times for all threads in the
1232 * group including the group leader.
1223 */ 1233 */
1234 thread_group_times(p, &tgutime, &tgstime);
1224 spin_lock_irq(&p->real_parent->sighand->siglock); 1235 spin_lock_irq(&p->real_parent->sighand->siglock);
1225 psig = p->real_parent->signal; 1236 psig = p->real_parent->signal;
1226 sig = p->signal; 1237 sig = p->signal;
1227 psig->cutime = 1238 psig->cutime =
1228 cputime_add(psig->cutime, 1239 cputime_add(psig->cutime,
1229 cputime_add(p->utime, 1240 cputime_add(tgutime,
1230 cputime_add(sig->utime, 1241 sig->cutime));
1231 sig->cutime)));
1232 psig->cstime = 1242 psig->cstime =
1233 cputime_add(psig->cstime, 1243 cputime_add(psig->cstime,
1234 cputime_add(p->stime, 1244 cputime_add(tgstime,
1235 cputime_add(sig->stime, 1245 sig->cstime));
1236 sig->cstime)));
1237 psig->cgtime = 1246 psig->cgtime =
1238 cputime_add(psig->cgtime, 1247 cputime_add(psig->cgtime,
1239 cputime_add(p->gtime, 1248 cputime_add(p->gtime,
diff --git a/kernel/fork.c b/kernel/fork.c
index 166b8c49257c..3d6f121bbe8a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -884,6 +884,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
884 sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; 884 sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
885 sig->gtime = cputime_zero; 885 sig->gtime = cputime_zero;
886 sig->cgtime = cputime_zero; 886 sig->cgtime = cputime_zero;
887#ifndef CONFIG_VIRT_CPU_ACCOUNTING
888 sig->prev_utime = sig->prev_stime = cputime_zero;
889#endif
887 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; 890 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
888 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; 891 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
889 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; 892 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
@@ -1066,8 +1069,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1066 p->gtime = cputime_zero; 1069 p->gtime = cputime_zero;
1067 p->utimescaled = cputime_zero; 1070 p->utimescaled = cputime_zero;
1068 p->stimescaled = cputime_zero; 1071 p->stimescaled = cputime_zero;
1072#ifndef CONFIG_VIRT_CPU_ACCOUNTING
1069 p->prev_utime = cputime_zero; 1073 p->prev_utime = cputime_zero;
1070 p->prev_stime = cputime_zero; 1074 p->prev_stime = cputime_zero;
1075#endif
1071 1076
1072 p->default_timer_slack_ns = current->timer_slack_ns; 1077 p->default_timer_slack_ns = current->timer_slack_ns;
1073 1078
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
new file mode 100644
index 000000000000..cf5ee1628411
--- /dev/null
+++ b/kernel/hw_breakpoint.c
@@ -0,0 +1,423 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2007 Alan Stern
17 * Copyright (C) IBM Corporation, 2009
18 * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com>
19 *
20 * Thanks to Ingo Molnar for his many suggestions.
21 *
22 * Authors: Alan Stern <stern@rowland.harvard.edu>
23 * K.Prasad <prasad@linux.vnet.ibm.com>
24 * Frederic Weisbecker <fweisbec@gmail.com>
25 */
26
27/*
28 * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
29 * using the CPU's debug registers.
30 * This file contains the arch-independent routines.
31 */
32
33#include <linux/irqflags.h>
34#include <linux/kallsyms.h>
35#include <linux/notifier.h>
36#include <linux/kprobes.h>
37#include <linux/kdebug.h>
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/percpu.h>
41#include <linux/sched.h>
42#include <linux/init.h>
43#include <linux/smp.h>
44
45#include <linux/hw_breakpoint.h>
46
47/*
48 * Constraints data
49 */
50
51/* Number of pinned cpu breakpoints in a cpu */
52static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned);
53
54/* Number of pinned task breakpoints in a cpu */
55static DEFINE_PER_CPU(unsigned int, task_bp_pinned[HBP_NUM]);
56
57/* Number of non-pinned cpu/task breakpoints in a cpu */
58static DEFINE_PER_CPU(unsigned int, nr_bp_flexible);
59
60/* Gather the number of total pinned and un-pinned bp in a cpuset */
61struct bp_busy_slots {
62 unsigned int pinned;
63 unsigned int flexible;
64};
65
66/* Serialize accesses to the above constraints */
67static DEFINE_MUTEX(nr_bp_mutex);
68
69/*
70 * Report the maximum number of pinned breakpoints a task
71 * have in this cpu
72 */
73static unsigned int max_task_bp_pinned(int cpu)
74{
75 int i;
76 unsigned int *tsk_pinned = per_cpu(task_bp_pinned, cpu);
77
78 for (i = HBP_NUM -1; i >= 0; i--) {
79 if (tsk_pinned[i] > 0)
80 return i + 1;
81 }
82
83 return 0;
84}
85
86/*
87 * Report the number of pinned/un-pinned breakpoints we have in
88 * a given cpu (cpu > -1) or in all of them (cpu = -1).
89 */
90static void fetch_bp_busy_slots(struct bp_busy_slots *slots, int cpu)
91{
92 if (cpu >= 0) {
93 slots->pinned = per_cpu(nr_cpu_bp_pinned, cpu);
94 slots->pinned += max_task_bp_pinned(cpu);
95 slots->flexible = per_cpu(nr_bp_flexible, cpu);
96
97 return;
98 }
99
100 for_each_online_cpu(cpu) {
101 unsigned int nr;
102
103 nr = per_cpu(nr_cpu_bp_pinned, cpu);
104 nr += max_task_bp_pinned(cpu);
105
106 if (nr > slots->pinned)
107 slots->pinned = nr;
108
109 nr = per_cpu(nr_bp_flexible, cpu);
110
111 if (nr > slots->flexible)
112 slots->flexible = nr;
113 }
114}
115
116/*
117 * Add a pinned breakpoint for the given task in our constraint table
118 */
119static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable)
120{
121 int count = 0;
122 struct perf_event *bp;
123 struct perf_event_context *ctx = tsk->perf_event_ctxp;
124 unsigned int *tsk_pinned;
125 struct list_head *list;
126 unsigned long flags;
127
128 if (WARN_ONCE(!ctx, "No perf context for this task"))
129 return;
130
131 list = &ctx->event_list;
132
133 spin_lock_irqsave(&ctx->lock, flags);
134
135 /*
136 * The current breakpoint counter is not included in the list
137 * at the open() callback time
138 */
139 list_for_each_entry(bp, list, event_entry) {
140 if (bp->attr.type == PERF_TYPE_BREAKPOINT)
141 count++;
142 }
143
144 spin_unlock_irqrestore(&ctx->lock, flags);
145
146 if (WARN_ONCE(count < 0, "No breakpoint counter found in the counter list"))
147 return;
148
149 tsk_pinned = per_cpu(task_bp_pinned, cpu);
150 if (enable) {
151 tsk_pinned[count]++;
152 if (count > 0)
153 tsk_pinned[count-1]--;
154 } else {
155 tsk_pinned[count]--;
156 if (count > 0)
157 tsk_pinned[count-1]++;
158 }
159}
160
161/*
162 * Add/remove the given breakpoint in our constraint table
163 */
164static void toggle_bp_slot(struct perf_event *bp, bool enable)
165{
166 int cpu = bp->cpu;
167 struct task_struct *tsk = bp->ctx->task;
168
169 /* Pinned counter task profiling */
170 if (tsk) {
171 if (cpu >= 0) {
172 toggle_bp_task_slot(tsk, cpu, enable);
173 return;
174 }
175
176 for_each_online_cpu(cpu)
177 toggle_bp_task_slot(tsk, cpu, enable);
178 return;
179 }
180
181 /* Pinned counter cpu profiling */
182 if (enable)
183 per_cpu(nr_cpu_bp_pinned, bp->cpu)++;
184 else
185 per_cpu(nr_cpu_bp_pinned, bp->cpu)--;
186}
187
188/*
189 * Contraints to check before allowing this new breakpoint counter:
190 *
191 * == Non-pinned counter == (Considered as pinned for now)
192 *
193 * - If attached to a single cpu, check:
194 *
195 * (per_cpu(nr_bp_flexible, cpu) || (per_cpu(nr_cpu_bp_pinned, cpu)
196 * + max(per_cpu(task_bp_pinned, cpu)))) < HBP_NUM
197 *
198 * -> If there are already non-pinned counters in this cpu, it means
199 * there is already a free slot for them.
200 * Otherwise, we check that the maximum number of per task
201 * breakpoints (for this cpu) plus the number of per cpu breakpoint
202 * (for this cpu) doesn't cover every registers.
203 *
204 * - If attached to every cpus, check:
205 *
206 * (per_cpu(nr_bp_flexible, *) || (max(per_cpu(nr_cpu_bp_pinned, *))
207 * + max(per_cpu(task_bp_pinned, *)))) < HBP_NUM
208 *
209 * -> This is roughly the same, except we check the number of per cpu
210 * bp for every cpu and we keep the max one. Same for the per tasks
211 * breakpoints.
212 *
213 *
214 * == Pinned counter ==
215 *
216 * - If attached to a single cpu, check:
217 *
218 * ((per_cpu(nr_bp_flexible, cpu) > 1) + per_cpu(nr_cpu_bp_pinned, cpu)
219 * + max(per_cpu(task_bp_pinned, cpu))) < HBP_NUM
220 *
221 * -> Same checks as before. But now the nr_bp_flexible, if any, must keep
222 * one register at least (or they will never be fed).
223 *
224 * - If attached to every cpus, check:
225 *
226 * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *))
227 * + max(per_cpu(task_bp_pinned, *))) < HBP_NUM
228 */
229int reserve_bp_slot(struct perf_event *bp)
230{
231 struct bp_busy_slots slots = {0};
232 int ret = 0;
233
234 mutex_lock(&nr_bp_mutex);
235
236 fetch_bp_busy_slots(&slots, bp->cpu);
237
238 /* Flexible counters need to keep at least one slot */
239 if (slots.pinned + (!!slots.flexible) == HBP_NUM) {
240 ret = -ENOSPC;
241 goto end;
242 }
243
244 toggle_bp_slot(bp, true);
245
246end:
247 mutex_unlock(&nr_bp_mutex);
248
249 return ret;
250}
251
252void release_bp_slot(struct perf_event *bp)
253{
254 mutex_lock(&nr_bp_mutex);
255
256 toggle_bp_slot(bp, false);
257
258 mutex_unlock(&nr_bp_mutex);
259}
260
261
262int __register_perf_hw_breakpoint(struct perf_event *bp)
263{
264 int ret;
265
266 ret = reserve_bp_slot(bp);
267 if (ret)
268 return ret;
269
270 /*
271 * Ptrace breakpoints can be temporary perf events only
272 * meant to reserve a slot. In this case, it is created disabled and
273 * we don't want to check the params right now (as we put a null addr)
274 * But perf tools create events as disabled and we want to check
275 * the params for them.
276 * This is a quick hack that will be removed soon, once we remove
277 * the tmp breakpoints from ptrace
278 */
279 if (!bp->attr.disabled || bp->callback == perf_bp_event)
280 ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task);
281
282 return ret;
283}
284
285int register_perf_hw_breakpoint(struct perf_event *bp)
286{
287 bp->callback = perf_bp_event;
288
289 return __register_perf_hw_breakpoint(bp);
290}
291
292/**
293 * register_user_hw_breakpoint - register a hardware breakpoint for user space
294 * @attr: breakpoint attributes
295 * @triggered: callback to trigger when we hit the breakpoint
296 * @tsk: pointer to 'task_struct' of the process to which the address belongs
297 */
298struct perf_event *
299register_user_hw_breakpoint(struct perf_event_attr *attr,
300 perf_callback_t triggered,
301 struct task_struct *tsk)
302{
303 return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered);
304}
305EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
306
307/**
308 * modify_user_hw_breakpoint - modify a user-space hardware breakpoint
309 * @bp: the breakpoint structure to modify
310 * @attr: new breakpoint attributes
311 * @triggered: callback to trigger when we hit the breakpoint
312 * @tsk: pointer to 'task_struct' of the process to which the address belongs
313 */
314struct perf_event *
315modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr,
316 perf_callback_t triggered,
317 struct task_struct *tsk)
318{
319 /*
320 * FIXME: do it without unregistering
321 * - We don't want to lose our slot
322 * - If the new bp is incorrect, don't lose the older one
323 */
324 unregister_hw_breakpoint(bp);
325
326 return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered);
327}
328EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint);
329
330/**
331 * unregister_hw_breakpoint - unregister a user-space hardware breakpoint
332 * @bp: the breakpoint structure to unregister
333 */
334void unregister_hw_breakpoint(struct perf_event *bp)
335{
336 if (!bp)
337 return;
338 perf_event_release_kernel(bp);
339}
340EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
341
342/**
343 * register_wide_hw_breakpoint - register a wide breakpoint in the kernel
344 * @attr: breakpoint attributes
345 * @triggered: callback to trigger when we hit the breakpoint
346 *
347 * @return a set of per_cpu pointers to perf events
348 */
349struct perf_event **
350register_wide_hw_breakpoint(struct perf_event_attr *attr,
351 perf_callback_t triggered)
352{
353 struct perf_event **cpu_events, **pevent, *bp;
354 long err;
355 int cpu;
356
357 cpu_events = alloc_percpu(typeof(*cpu_events));
358 if (!cpu_events)
359 return ERR_PTR(-ENOMEM);
360
361 for_each_possible_cpu(cpu) {
362 pevent = per_cpu_ptr(cpu_events, cpu);
363 bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered);
364
365 *pevent = bp;
366
367 if (IS_ERR(bp)) {
368 err = PTR_ERR(bp);
369 goto fail;
370 }
371 }
372
373 return cpu_events;
374
375fail:
376 for_each_possible_cpu(cpu) {
377 pevent = per_cpu_ptr(cpu_events, cpu);
378 if (IS_ERR(*pevent))
379 break;
380 unregister_hw_breakpoint(*pevent);
381 }
382 free_percpu(cpu_events);
383 /* return the error if any */
384 return ERR_PTR(err);
385}
386EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
387
388/**
389 * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
390 * @cpu_events: the per cpu set of events to unregister
391 */
392void unregister_wide_hw_breakpoint(struct perf_event **cpu_events)
393{
394 int cpu;
395 struct perf_event **pevent;
396
397 for_each_possible_cpu(cpu) {
398 pevent = per_cpu_ptr(cpu_events, cpu);
399 unregister_hw_breakpoint(*pevent);
400 }
401 free_percpu(cpu_events);
402}
403EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint);
404
405static struct notifier_block hw_breakpoint_exceptions_nb = {
406 .notifier_call = hw_breakpoint_exceptions_notify,
407 /* we need to be notified first */
408 .priority = 0x7fffffff
409};
410
411static int __init init_hw_breakpoint(void)
412{
413 return register_die_notifier(&hw_breakpoint_exceptions_nb);
414}
415core_initcall(init_hw_breakpoint);
416
417
418struct pmu perf_ops_bp = {
419 .enable = arch_install_hw_breakpoint,
420 .disable = arch_uninstall_hw_breakpoint,
421 .read = hw_breakpoint_pmu_read,
422 .unthrottle = hw_breakpoint_pmu_unthrottle
423};
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 8b6b8b697c68..8e5288a8a355 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -181,6 +181,7 @@ unsigned long kallsyms_lookup_name(const char *name)
181 } 181 }
182 return module_kallsyms_lookup_name(name); 182 return module_kallsyms_lookup_name(name);
183} 183}
184EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
184 185
185int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, 186int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
186 unsigned long), 187 unsigned long),
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index 9147a3190c9d..7d7014634022 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -870,7 +870,7 @@ static void gdb_cmd_getregs(struct kgdb_state *ks)
870 870
871 /* 871 /*
872 * All threads that don't have debuggerinfo should be 872 * All threads that don't have debuggerinfo should be
873 * in __schedule() sleeping, since all other CPUs 873 * in schedule() sleeping, since all other CPUs
874 * are in kgdb_wait, and thus have debuggerinfo. 874 * are in kgdb_wait, and thus have debuggerinfo.
875 */ 875 */
876 if (local_debuggerinfo) { 876 if (local_debuggerinfo) {
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1494e85b35f2..e5342a344c43 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -90,6 +90,9 @@ static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
90 */ 90 */
91static struct kprobe_blackpoint kprobe_blacklist[] = { 91static struct kprobe_blackpoint kprobe_blacklist[] = {
92 {"preempt_schedule",}, 92 {"preempt_schedule",},
93 {"native_get_debugreg",},
94 {"irq_entries_start",},
95 {"common_interrupt",},
93 {NULL} /* Terminator */ 96 {NULL} /* Terminator */
94}; 97};
95 98
@@ -673,6 +676,40 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
673 return (kprobe_opcode_t *)(((char *)addr) + p->offset); 676 return (kprobe_opcode_t *)(((char *)addr) + p->offset);
674} 677}
675 678
679/* Check passed kprobe is valid and return kprobe in kprobe_table. */
680static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
681{
682 struct kprobe *old_p, *list_p;
683
684 old_p = get_kprobe(p->addr);
685 if (unlikely(!old_p))
686 return NULL;
687
688 if (p != old_p) {
689 list_for_each_entry_rcu(list_p, &old_p->list, list)
690 if (list_p == p)
691 /* kprobe p is a valid probe */
692 goto valid;
693 return NULL;
694 }
695valid:
696 return old_p;
697}
698
699/* Return error if the kprobe is being re-registered */
700static inline int check_kprobe_rereg(struct kprobe *p)
701{
702 int ret = 0;
703 struct kprobe *old_p;
704
705 mutex_lock(&kprobe_mutex);
706 old_p = __get_valid_kprobe(p);
707 if (old_p)
708 ret = -EINVAL;
709 mutex_unlock(&kprobe_mutex);
710 return ret;
711}
712
676int __kprobes register_kprobe(struct kprobe *p) 713int __kprobes register_kprobe(struct kprobe *p)
677{ 714{
678 int ret = 0; 715 int ret = 0;
@@ -685,6 +722,10 @@ int __kprobes register_kprobe(struct kprobe *p)
685 return -EINVAL; 722 return -EINVAL;
686 p->addr = addr; 723 p->addr = addr;
687 724
725 ret = check_kprobe_rereg(p);
726 if (ret)
727 return ret;
728
688 preempt_disable(); 729 preempt_disable();
689 if (!kernel_text_address((unsigned long) p->addr) || 730 if (!kernel_text_address((unsigned long) p->addr) ||
690 in_kprobes_functions((unsigned long) p->addr)) { 731 in_kprobes_functions((unsigned long) p->addr)) {
@@ -754,26 +795,6 @@ out:
754} 795}
755EXPORT_SYMBOL_GPL(register_kprobe); 796EXPORT_SYMBOL_GPL(register_kprobe);
756 797
757/* Check passed kprobe is valid and return kprobe in kprobe_table. */
758static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
759{
760 struct kprobe *old_p, *list_p;
761
762 old_p = get_kprobe(p->addr);
763 if (unlikely(!old_p))
764 return NULL;
765
766 if (p != old_p) {
767 list_for_each_entry_rcu(list_p, &old_p->list, list)
768 if (list_p == p)
769 /* kprobe p is a valid probe */
770 goto valid;
771 return NULL;
772 }
773valid:
774 return old_p;
775}
776
777/* 798/*
778 * Unregister a kprobe without a scheduler synchronization. 799 * Unregister a kprobe without a scheduler synchronization.
779 */ 800 */
@@ -1141,6 +1162,13 @@ static void __kprobes kill_kprobe(struct kprobe *p)
1141 arch_remove_kprobe(p); 1162 arch_remove_kprobe(p);
1142} 1163}
1143 1164
1165void __kprobes dump_kprobe(struct kprobe *kp)
1166{
1167 printk(KERN_WARNING "Dumping kprobe:\n");
1168 printk(KERN_WARNING "Name: %s\nAddress: %p\nOffset: %x\n",
1169 kp->symbol_name, kp->addr, kp->offset);
1170}
1171
1144/* Module notifier call back, checking kprobes on the module */ 1172/* Module notifier call back, checking kprobes on the module */
1145static int __kprobes kprobes_module_callback(struct notifier_block *nb, 1173static int __kprobes kprobes_module_callback(struct notifier_block *nb,
1146 unsigned long val, void *data) 1174 unsigned long val, void *data)
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 9af56723c096..f5dcd36d3151 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -49,7 +49,7 @@
49#include "lockdep_internals.h" 49#include "lockdep_internals.h"
50 50
51#define CREATE_TRACE_POINTS 51#define CREATE_TRACE_POINTS
52#include <trace/events/lockdep.h> 52#include <trace/events/lock.h>
53 53
54#ifdef CONFIG_PROVE_LOCKING 54#ifdef CONFIG_PROVE_LOCKING
55int prove_locking = 1; 55int prove_locking = 1;
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 61d5aa5eced3..acd24e7643eb 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -558,7 +558,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
558 558
559static ATOMIC_NOTIFIER_HEAD(die_chain); 559static ATOMIC_NOTIFIER_HEAD(die_chain);
560 560
561int notrace notify_die(enum die_val val, const char *str, 561int notrace __kprobes notify_die(enum die_val val, const char *str,
562 struct pt_regs *regs, long err, int trap, int sig) 562 struct pt_regs *regs, long err, int trap, int sig)
563{ 563{
564 struct die_args args = { 564 struct die_args args = {
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 7f29643c8985..6b7ddba1dd64 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -28,6 +28,8 @@
28#include <linux/anon_inodes.h> 28#include <linux/anon_inodes.h>
29#include <linux/kernel_stat.h> 29#include <linux/kernel_stat.h>
30#include <linux/perf_event.h> 30#include <linux/perf_event.h>
31#include <linux/ftrace_event.h>
32#include <linux/hw_breakpoint.h>
31 33
32#include <asm/irq_regs.h> 34#include <asm/irq_regs.h>
33 35
@@ -244,6 +246,49 @@ static void perf_unpin_context(struct perf_event_context *ctx)
244 put_ctx(ctx); 246 put_ctx(ctx);
245} 247}
246 248
249static inline u64 perf_clock(void)
250{
251 return cpu_clock(smp_processor_id());
252}
253
254/*
255 * Update the record of the current time in a context.
256 */
257static void update_context_time(struct perf_event_context *ctx)
258{
259 u64 now = perf_clock();
260
261 ctx->time += now - ctx->timestamp;
262 ctx->timestamp = now;
263}
264
265/*
266 * Update the total_time_enabled and total_time_running fields for a event.
267 */
268static void update_event_times(struct perf_event *event)
269{
270 struct perf_event_context *ctx = event->ctx;
271 u64 run_end;
272
273 if (event->state < PERF_EVENT_STATE_INACTIVE ||
274 event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
275 return;
276
277 if (ctx->is_active)
278 run_end = ctx->time;
279 else
280 run_end = event->tstamp_stopped;
281
282 event->total_time_enabled = run_end - event->tstamp_enabled;
283
284 if (event->state == PERF_EVENT_STATE_INACTIVE)
285 run_end = event->tstamp_stopped;
286 else
287 run_end = ctx->time;
288
289 event->total_time_running = run_end - event->tstamp_running;
290}
291
247/* 292/*
248 * Add a event from the lists for its context. 293 * Add a event from the lists for its context.
249 * Must be called with ctx->mutex and ctx->lock held. 294 * Must be called with ctx->mutex and ctx->lock held.
@@ -292,6 +337,18 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
292 if (event->group_leader != event) 337 if (event->group_leader != event)
293 event->group_leader->nr_siblings--; 338 event->group_leader->nr_siblings--;
294 339
340 update_event_times(event);
341
342 /*
343 * If event was in error state, then keep it
344 * that way, otherwise bogus counts will be
345 * returned on read(). The only way to get out
346 * of error state is by explicit re-enabling
347 * of the event
348 */
349 if (event->state > PERF_EVENT_STATE_OFF)
350 event->state = PERF_EVENT_STATE_OFF;
351
295 /* 352 /*
296 * If this was a group event with sibling events then 353 * If this was a group event with sibling events then
297 * upgrade the siblings to singleton events by adding them 354 * upgrade the siblings to singleton events by adding them
@@ -445,50 +502,11 @@ retry:
445 * can remove the event safely, if the call above did not 502 * can remove the event safely, if the call above did not
446 * succeed. 503 * succeed.
447 */ 504 */
448 if (!list_empty(&event->group_entry)) { 505 if (!list_empty(&event->group_entry))
449 list_del_event(event, ctx); 506 list_del_event(event, ctx);
450 }
451 spin_unlock_irq(&ctx->lock); 507 spin_unlock_irq(&ctx->lock);
452} 508}
453 509
454static inline u64 perf_clock(void)
455{
456 return cpu_clock(smp_processor_id());
457}
458
459/*
460 * Update the record of the current time in a context.
461 */
462static void update_context_time(struct perf_event_context *ctx)
463{
464 u64 now = perf_clock();
465
466 ctx->time += now - ctx->timestamp;
467 ctx->timestamp = now;
468}
469
470/*
471 * Update the total_time_enabled and total_time_running fields for a event.
472 */
473static void update_event_times(struct perf_event *event)
474{
475 struct perf_event_context *ctx = event->ctx;
476 u64 run_end;
477
478 if (event->state < PERF_EVENT_STATE_INACTIVE ||
479 event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
480 return;
481
482 event->total_time_enabled = ctx->time - event->tstamp_enabled;
483
484 if (event->state == PERF_EVENT_STATE_INACTIVE)
485 run_end = event->tstamp_stopped;
486 else
487 run_end = ctx->time;
488
489 event->total_time_running = run_end - event->tstamp_running;
490}
491
492/* 510/*
493 * Update total_time_enabled and total_time_running for all events in a group. 511 * Update total_time_enabled and total_time_running for all events in a group.
494 */ 512 */
@@ -1031,10 +1049,10 @@ void __perf_event_sched_out(struct perf_event_context *ctx,
1031 update_context_time(ctx); 1049 update_context_time(ctx);
1032 1050
1033 perf_disable(); 1051 perf_disable();
1034 if (ctx->nr_active) 1052 if (ctx->nr_active) {
1035 list_for_each_entry(event, &ctx->group_list, group_entry) 1053 list_for_each_entry(event, &ctx->group_list, group_entry)
1036 group_sched_out(event, cpuctx, ctx); 1054 group_sched_out(event, cpuctx, ctx);
1037 1055 }
1038 perf_enable(); 1056 perf_enable();
1039 out: 1057 out:
1040 spin_unlock(&ctx->lock); 1058 spin_unlock(&ctx->lock);
@@ -1059,8 +1077,6 @@ static int context_equiv(struct perf_event_context *ctx1,
1059 && !ctx1->pin_count && !ctx2->pin_count; 1077 && !ctx1->pin_count && !ctx2->pin_count;
1060} 1078}
1061 1079
1062static void __perf_event_read(void *event);
1063
1064static void __perf_event_sync_stat(struct perf_event *event, 1080static void __perf_event_sync_stat(struct perf_event *event,
1065 struct perf_event *next_event) 1081 struct perf_event *next_event)
1066{ 1082{
@@ -1078,8 +1094,8 @@ static void __perf_event_sync_stat(struct perf_event *event,
1078 */ 1094 */
1079 switch (event->state) { 1095 switch (event->state) {
1080 case PERF_EVENT_STATE_ACTIVE: 1096 case PERF_EVENT_STATE_ACTIVE:
1081 __perf_event_read(event); 1097 event->pmu->read(event);
1082 break; 1098 /* fall-through */
1083 1099
1084 case PERF_EVENT_STATE_INACTIVE: 1100 case PERF_EVENT_STATE_INACTIVE:
1085 update_event_times(event); 1101 update_event_times(event);
@@ -1118,6 +1134,8 @@ static void perf_event_sync_stat(struct perf_event_context *ctx,
1118 if (!ctx->nr_stat) 1134 if (!ctx->nr_stat)
1119 return; 1135 return;
1120 1136
1137 update_context_time(ctx);
1138
1121 event = list_first_entry(&ctx->event_list, 1139 event = list_first_entry(&ctx->event_list,
1122 struct perf_event, event_entry); 1140 struct perf_event, event_entry);
1123 1141
@@ -1161,8 +1179,6 @@ void perf_event_task_sched_out(struct task_struct *task,
1161 if (likely(!ctx || !cpuctx->task_ctx)) 1179 if (likely(!ctx || !cpuctx->task_ctx))
1162 return; 1180 return;
1163 1181
1164 update_context_time(ctx);
1165
1166 rcu_read_lock(); 1182 rcu_read_lock();
1167 parent = rcu_dereference(ctx->parent_ctx); 1183 parent = rcu_dereference(ctx->parent_ctx);
1168 next_ctx = next->perf_event_ctxp; 1184 next_ctx = next->perf_event_ctxp;
@@ -1515,7 +1531,6 @@ static void __perf_event_read(void *info)
1515 struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context); 1531 struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
1516 struct perf_event *event = info; 1532 struct perf_event *event = info;
1517 struct perf_event_context *ctx = event->ctx; 1533 struct perf_event_context *ctx = event->ctx;
1518 unsigned long flags;
1519 1534
1520 /* 1535 /*
1521 * If this is a task context, we need to check whether it is 1536 * If this is a task context, we need to check whether it is
@@ -1527,12 +1542,12 @@ static void __perf_event_read(void *info)
1527 if (ctx->task && cpuctx->task_ctx != ctx) 1542 if (ctx->task && cpuctx->task_ctx != ctx)
1528 return; 1543 return;
1529 1544
1530 local_irq_save(flags); 1545 spin_lock(&ctx->lock);
1531 if (ctx->is_active) 1546 update_context_time(ctx);
1532 update_context_time(ctx);
1533 event->pmu->read(event);
1534 update_event_times(event); 1547 update_event_times(event);
1535 local_irq_restore(flags); 1548 spin_unlock(&ctx->lock);
1549
1550 event->pmu->read(event);
1536} 1551}
1537 1552
1538static u64 perf_event_read(struct perf_event *event) 1553static u64 perf_event_read(struct perf_event *event)
@@ -1545,7 +1560,13 @@ static u64 perf_event_read(struct perf_event *event)
1545 smp_call_function_single(event->oncpu, 1560 smp_call_function_single(event->oncpu,
1546 __perf_event_read, event, 1); 1561 __perf_event_read, event, 1);
1547 } else if (event->state == PERF_EVENT_STATE_INACTIVE) { 1562 } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
1563 struct perf_event_context *ctx = event->ctx;
1564 unsigned long flags;
1565
1566 spin_lock_irqsave(&ctx->lock, flags);
1567 update_context_time(ctx);
1548 update_event_times(event); 1568 update_event_times(event);
1569 spin_unlock_irqrestore(&ctx->lock, flags);
1549 } 1570 }
1550 1571
1551 return atomic64_read(&event->count); 1572 return atomic64_read(&event->count);
@@ -1658,6 +1679,8 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu)
1658 return ERR_PTR(err); 1679 return ERR_PTR(err);
1659} 1680}
1660 1681
1682static void perf_event_free_filter(struct perf_event *event);
1683
1661static void free_event_rcu(struct rcu_head *head) 1684static void free_event_rcu(struct rcu_head *head)
1662{ 1685{
1663 struct perf_event *event; 1686 struct perf_event *event;
@@ -1665,6 +1688,7 @@ static void free_event_rcu(struct rcu_head *head)
1665 event = container_of(head, struct perf_event, rcu_head); 1688 event = container_of(head, struct perf_event, rcu_head);
1666 if (event->ns) 1689 if (event->ns)
1667 put_pid_ns(event->ns); 1690 put_pid_ns(event->ns);
1691 perf_event_free_filter(event);
1668 kfree(event); 1692 kfree(event);
1669} 1693}
1670 1694
@@ -1696,16 +1720,10 @@ static void free_event(struct perf_event *event)
1696 call_rcu(&event->rcu_head, free_event_rcu); 1720 call_rcu(&event->rcu_head, free_event_rcu);
1697} 1721}
1698 1722
1699/* 1723int perf_event_release_kernel(struct perf_event *event)
1700 * Called when the last reference to the file is gone.
1701 */
1702static int perf_release(struct inode *inode, struct file *file)
1703{ 1724{
1704 struct perf_event *event = file->private_data;
1705 struct perf_event_context *ctx = event->ctx; 1725 struct perf_event_context *ctx = event->ctx;
1706 1726
1707 file->private_data = NULL;
1708
1709 WARN_ON_ONCE(ctx->parent_ctx); 1727 WARN_ON_ONCE(ctx->parent_ctx);
1710 mutex_lock(&ctx->mutex); 1728 mutex_lock(&ctx->mutex);
1711 perf_event_remove_from_context(event); 1729 perf_event_remove_from_context(event);
@@ -1720,6 +1738,19 @@ static int perf_release(struct inode *inode, struct file *file)
1720 1738
1721 return 0; 1739 return 0;
1722} 1740}
1741EXPORT_SYMBOL_GPL(perf_event_release_kernel);
1742
1743/*
1744 * Called when the last reference to the file is gone.
1745 */
1746static int perf_release(struct inode *inode, struct file *file)
1747{
1748 struct perf_event *event = file->private_data;
1749
1750 file->private_data = NULL;
1751
1752 return perf_event_release_kernel(event);
1753}
1723 1754
1724static int perf_event_read_size(struct perf_event *event) 1755static int perf_event_read_size(struct perf_event *event)
1725{ 1756{
@@ -1746,91 +1777,94 @@ static int perf_event_read_size(struct perf_event *event)
1746 return size; 1777 return size;
1747} 1778}
1748 1779
1749static u64 perf_event_read_value(struct perf_event *event) 1780u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
1750{ 1781{
1751 struct perf_event *child; 1782 struct perf_event *child;
1752 u64 total = 0; 1783 u64 total = 0;
1753 1784
1785 *enabled = 0;
1786 *running = 0;
1787
1788 mutex_lock(&event->child_mutex);
1754 total += perf_event_read(event); 1789 total += perf_event_read(event);
1755 list_for_each_entry(child, &event->child_list, child_list) 1790 *enabled += event->total_time_enabled +
1791 atomic64_read(&event->child_total_time_enabled);
1792 *running += event->total_time_running +
1793 atomic64_read(&event->child_total_time_running);
1794
1795 list_for_each_entry(child, &event->child_list, child_list) {
1756 total += perf_event_read(child); 1796 total += perf_event_read(child);
1797 *enabled += child->total_time_enabled;
1798 *running += child->total_time_running;
1799 }
1800 mutex_unlock(&event->child_mutex);
1757 1801
1758 return total; 1802 return total;
1759} 1803}
1760 1804EXPORT_SYMBOL_GPL(perf_event_read_value);
1761static int perf_event_read_entry(struct perf_event *event,
1762 u64 read_format, char __user *buf)
1763{
1764 int n = 0, count = 0;
1765 u64 values[2];
1766
1767 values[n++] = perf_event_read_value(event);
1768 if (read_format & PERF_FORMAT_ID)
1769 values[n++] = primary_event_id(event);
1770
1771 count = n * sizeof(u64);
1772
1773 if (copy_to_user(buf, values, count))
1774 return -EFAULT;
1775
1776 return count;
1777}
1778 1805
1779static int perf_event_read_group(struct perf_event *event, 1806static int perf_event_read_group(struct perf_event *event,
1780 u64 read_format, char __user *buf) 1807 u64 read_format, char __user *buf)
1781{ 1808{
1782 struct perf_event *leader = event->group_leader, *sub; 1809 struct perf_event *leader = event->group_leader, *sub;
1783 int n = 0, size = 0, err = -EFAULT; 1810 int n = 0, size = 0, ret = -EFAULT;
1784 u64 values[3]; 1811 struct perf_event_context *ctx = leader->ctx;
1812 u64 values[5];
1813 u64 count, enabled, running;
1814
1815 mutex_lock(&ctx->mutex);
1816 count = perf_event_read_value(leader, &enabled, &running);
1785 1817
1786 values[n++] = 1 + leader->nr_siblings; 1818 values[n++] = 1 + leader->nr_siblings;
1787 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1819 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1788 values[n++] = leader->total_time_enabled + 1820 values[n++] = enabled;
1789 atomic64_read(&leader->child_total_time_enabled); 1821 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1790 } 1822 values[n++] = running;
1791 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { 1823 values[n++] = count;
1792 values[n++] = leader->total_time_running + 1824 if (read_format & PERF_FORMAT_ID)
1793 atomic64_read(&leader->child_total_time_running); 1825 values[n++] = primary_event_id(leader);
1794 }
1795 1826
1796 size = n * sizeof(u64); 1827 size = n * sizeof(u64);
1797 1828
1798 if (copy_to_user(buf, values, size)) 1829 if (copy_to_user(buf, values, size))
1799 return -EFAULT; 1830 goto unlock;
1800
1801 err = perf_event_read_entry(leader, read_format, buf + size);
1802 if (err < 0)
1803 return err;
1804 1831
1805 size += err; 1832 ret = size;
1806 1833
1807 list_for_each_entry(sub, &leader->sibling_list, group_entry) { 1834 list_for_each_entry(sub, &leader->sibling_list, group_entry) {
1808 err = perf_event_read_entry(sub, read_format, 1835 n = 0;
1809 buf + size); 1836
1810 if (err < 0) 1837 values[n++] = perf_event_read_value(sub, &enabled, &running);
1811 return err; 1838 if (read_format & PERF_FORMAT_ID)
1839 values[n++] = primary_event_id(sub);
1840
1841 size = n * sizeof(u64);
1812 1842
1813 size += err; 1843 if (copy_to_user(buf + ret, values, size)) {
1844 ret = -EFAULT;
1845 goto unlock;
1846 }
1847
1848 ret += size;
1814 } 1849 }
1850unlock:
1851 mutex_unlock(&ctx->mutex);
1815 1852
1816 return size; 1853 return ret;
1817} 1854}
1818 1855
1819static int perf_event_read_one(struct perf_event *event, 1856static int perf_event_read_one(struct perf_event *event,
1820 u64 read_format, char __user *buf) 1857 u64 read_format, char __user *buf)
1821{ 1858{
1859 u64 enabled, running;
1822 u64 values[4]; 1860 u64 values[4];
1823 int n = 0; 1861 int n = 0;
1824 1862
1825 values[n++] = perf_event_read_value(event); 1863 values[n++] = perf_event_read_value(event, &enabled, &running);
1826 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1864 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1827 values[n++] = event->total_time_enabled + 1865 values[n++] = enabled;
1828 atomic64_read(&event->child_total_time_enabled); 1866 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1829 } 1867 values[n++] = running;
1830 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1831 values[n++] = event->total_time_running +
1832 atomic64_read(&event->child_total_time_running);
1833 }
1834 if (read_format & PERF_FORMAT_ID) 1868 if (read_format & PERF_FORMAT_ID)
1835 values[n++] = primary_event_id(event); 1869 values[n++] = primary_event_id(event);
1836 1870
@@ -1861,12 +1895,10 @@ perf_read_hw(struct perf_event *event, char __user *buf, size_t count)
1861 return -ENOSPC; 1895 return -ENOSPC;
1862 1896
1863 WARN_ON_ONCE(event->ctx->parent_ctx); 1897 WARN_ON_ONCE(event->ctx->parent_ctx);
1864 mutex_lock(&event->child_mutex);
1865 if (read_format & PERF_FORMAT_GROUP) 1898 if (read_format & PERF_FORMAT_GROUP)
1866 ret = perf_event_read_group(event, read_format, buf); 1899 ret = perf_event_read_group(event, read_format, buf);
1867 else 1900 else
1868 ret = perf_event_read_one(event, read_format, buf); 1901 ret = perf_event_read_one(event, read_format, buf);
1869 mutex_unlock(&event->child_mutex);
1870 1902
1871 return ret; 1903 return ret;
1872} 1904}
@@ -1974,7 +2006,8 @@ unlock:
1974 return ret; 2006 return ret;
1975} 2007}
1976 2008
1977int perf_event_set_output(struct perf_event *event, int output_fd); 2009static int perf_event_set_output(struct perf_event *event, int output_fd);
2010static int perf_event_set_filter(struct perf_event *event, void __user *arg);
1978 2011
1979static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2012static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1980{ 2013{
@@ -2002,6 +2035,9 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2002 case PERF_EVENT_IOC_SET_OUTPUT: 2035 case PERF_EVENT_IOC_SET_OUTPUT:
2003 return perf_event_set_output(event, arg); 2036 return perf_event_set_output(event, arg);
2004 2037
2038 case PERF_EVENT_IOC_SET_FILTER:
2039 return perf_event_set_filter(event, (void __user *)arg);
2040
2005 default: 2041 default:
2006 return -ENOTTY; 2042 return -ENOTTY;
2007 } 2043 }
@@ -2174,6 +2210,7 @@ static void perf_mmap_data_free(struct perf_mmap_data *data)
2174 perf_mmap_free_page((unsigned long)data->user_page); 2210 perf_mmap_free_page((unsigned long)data->user_page);
2175 for (i = 0; i < data->nr_pages; i++) 2211 for (i = 0; i < data->nr_pages; i++)
2176 perf_mmap_free_page((unsigned long)data->data_pages[i]); 2212 perf_mmap_free_page((unsigned long)data->data_pages[i]);
2213 kfree(data);
2177} 2214}
2178 2215
2179#else 2216#else
@@ -2214,6 +2251,7 @@ static void perf_mmap_data_free_work(struct work_struct *work)
2214 perf_mmap_unmark_page(base + (i * PAGE_SIZE)); 2251 perf_mmap_unmark_page(base + (i * PAGE_SIZE));
2215 2252
2216 vfree(base); 2253 vfree(base);
2254 kfree(data);
2217} 2255}
2218 2256
2219static void perf_mmap_data_free(struct perf_mmap_data *data) 2257static void perf_mmap_data_free(struct perf_mmap_data *data)
@@ -2307,7 +2345,7 @@ perf_mmap_data_init(struct perf_event *event, struct perf_mmap_data *data)
2307 } 2345 }
2308 2346
2309 if (!data->watermark) 2347 if (!data->watermark)
2310 data->watermark = max_t(long, PAGE_SIZE, max_size / 2); 2348 data->watermark = max_size / 2;
2311 2349
2312 2350
2313 rcu_assign_pointer(event->data, data); 2351 rcu_assign_pointer(event->data, data);
@@ -2319,7 +2357,6 @@ static void perf_mmap_data_free_rcu(struct rcu_head *rcu_head)
2319 2357
2320 data = container_of(rcu_head, struct perf_mmap_data, rcu_head); 2358 data = container_of(rcu_head, struct perf_mmap_data, rcu_head);
2321 perf_mmap_data_free(data); 2359 perf_mmap_data_free(data);
2322 kfree(data);
2323} 2360}
2324 2361
2325static void perf_mmap_data_release(struct perf_event *event) 2362static void perf_mmap_data_release(struct perf_event *event)
@@ -2666,20 +2703,21 @@ static void perf_output_wakeup(struct perf_output_handle *handle)
2666static void perf_output_lock(struct perf_output_handle *handle) 2703static void perf_output_lock(struct perf_output_handle *handle)
2667{ 2704{
2668 struct perf_mmap_data *data = handle->data; 2705 struct perf_mmap_data *data = handle->data;
2669 int cpu; 2706 int cur, cpu = get_cpu();
2670 2707
2671 handle->locked = 0; 2708 handle->locked = 0;
2672 2709
2673 local_irq_save(handle->flags); 2710 for (;;) {
2674 cpu = smp_processor_id(); 2711 cur = atomic_cmpxchg(&data->lock, -1, cpu);
2675 2712 if (cur == -1) {
2676 if (in_nmi() && atomic_read(&data->lock) == cpu) 2713 handle->locked = 1;
2677 return; 2714 break;
2715 }
2716 if (cur == cpu)
2717 break;
2678 2718
2679 while (atomic_cmpxchg(&data->lock, -1, cpu) != -1)
2680 cpu_relax(); 2719 cpu_relax();
2681 2720 }
2682 handle->locked = 1;
2683} 2721}
2684 2722
2685static void perf_output_unlock(struct perf_output_handle *handle) 2723static void perf_output_unlock(struct perf_output_handle *handle)
@@ -2725,7 +2763,7 @@ again:
2725 if (atomic_xchg(&data->wakeup, 0)) 2763 if (atomic_xchg(&data->wakeup, 0))
2726 perf_output_wakeup(handle); 2764 perf_output_wakeup(handle);
2727out: 2765out:
2728 local_irq_restore(handle->flags); 2766 put_cpu();
2729} 2767}
2730 2768
2731void perf_output_copy(struct perf_output_handle *handle, 2769void perf_output_copy(struct perf_output_handle *handle,
@@ -3236,15 +3274,10 @@ static void perf_event_task_ctx(struct perf_event_context *ctx,
3236{ 3274{
3237 struct perf_event *event; 3275 struct perf_event *event;
3238 3276
3239 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
3240 return;
3241
3242 rcu_read_lock();
3243 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { 3277 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
3244 if (perf_event_task_match(event)) 3278 if (perf_event_task_match(event))
3245 perf_event_task_output(event, task_event); 3279 perf_event_task_output(event, task_event);
3246 } 3280 }
3247 rcu_read_unlock();
3248} 3281}
3249 3282
3250static void perf_event_task_event(struct perf_task_event *task_event) 3283static void perf_event_task_event(struct perf_task_event *task_event)
@@ -3252,11 +3285,11 @@ static void perf_event_task_event(struct perf_task_event *task_event)
3252 struct perf_cpu_context *cpuctx; 3285 struct perf_cpu_context *cpuctx;
3253 struct perf_event_context *ctx = task_event->task_ctx; 3286 struct perf_event_context *ctx = task_event->task_ctx;
3254 3287
3288 rcu_read_lock();
3255 cpuctx = &get_cpu_var(perf_cpu_context); 3289 cpuctx = &get_cpu_var(perf_cpu_context);
3256 perf_event_task_ctx(&cpuctx->ctx, task_event); 3290 perf_event_task_ctx(&cpuctx->ctx, task_event);
3257 put_cpu_var(perf_cpu_context); 3291 put_cpu_var(perf_cpu_context);
3258 3292
3259 rcu_read_lock();
3260 if (!ctx) 3293 if (!ctx)
3261 ctx = rcu_dereference(task_event->task->perf_event_ctxp); 3294 ctx = rcu_dereference(task_event->task->perf_event_ctxp);
3262 if (ctx) 3295 if (ctx)
@@ -3348,15 +3381,10 @@ static void perf_event_comm_ctx(struct perf_event_context *ctx,
3348{ 3381{
3349 struct perf_event *event; 3382 struct perf_event *event;
3350 3383
3351 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
3352 return;
3353
3354 rcu_read_lock();
3355 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { 3384 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
3356 if (perf_event_comm_match(event)) 3385 if (perf_event_comm_match(event))
3357 perf_event_comm_output(event, comm_event); 3386 perf_event_comm_output(event, comm_event);
3358 } 3387 }
3359 rcu_read_unlock();
3360} 3388}
3361 3389
3362static void perf_event_comm_event(struct perf_comm_event *comm_event) 3390static void perf_event_comm_event(struct perf_comm_event *comm_event)
@@ -3367,7 +3395,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
3367 char comm[TASK_COMM_LEN]; 3395 char comm[TASK_COMM_LEN];
3368 3396
3369 memset(comm, 0, sizeof(comm)); 3397 memset(comm, 0, sizeof(comm));
3370 strncpy(comm, comm_event->task->comm, sizeof(comm)); 3398 strlcpy(comm, comm_event->task->comm, sizeof(comm));
3371 size = ALIGN(strlen(comm)+1, sizeof(u64)); 3399 size = ALIGN(strlen(comm)+1, sizeof(u64));
3372 3400
3373 comm_event->comm = comm; 3401 comm_event->comm = comm;
@@ -3375,11 +3403,11 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
3375 3403
3376 comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; 3404 comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
3377 3405
3406 rcu_read_lock();
3378 cpuctx = &get_cpu_var(perf_cpu_context); 3407 cpuctx = &get_cpu_var(perf_cpu_context);
3379 perf_event_comm_ctx(&cpuctx->ctx, comm_event); 3408 perf_event_comm_ctx(&cpuctx->ctx, comm_event);
3380 put_cpu_var(perf_cpu_context); 3409 put_cpu_var(perf_cpu_context);
3381 3410
3382 rcu_read_lock();
3383 /* 3411 /*
3384 * doesn't really matter which of the child contexts the 3412 * doesn't really matter which of the child contexts the
3385 * events ends up in. 3413 * events ends up in.
@@ -3472,15 +3500,10 @@ static void perf_event_mmap_ctx(struct perf_event_context *ctx,
3472{ 3500{
3473 struct perf_event *event; 3501 struct perf_event *event;
3474 3502
3475 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
3476 return;
3477
3478 rcu_read_lock();
3479 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { 3503 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
3480 if (perf_event_mmap_match(event, mmap_event)) 3504 if (perf_event_mmap_match(event, mmap_event))
3481 perf_event_mmap_output(event, mmap_event); 3505 perf_event_mmap_output(event, mmap_event);
3482 } 3506 }
3483 rcu_read_unlock();
3484} 3507}
3485 3508
3486static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) 3509static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
@@ -3536,11 +3559,11 @@ got_name:
3536 3559
3537 mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; 3560 mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
3538 3561
3562 rcu_read_lock();
3539 cpuctx = &get_cpu_var(perf_cpu_context); 3563 cpuctx = &get_cpu_var(perf_cpu_context);
3540 perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); 3564 perf_event_mmap_ctx(&cpuctx->ctx, mmap_event);
3541 put_cpu_var(perf_cpu_context); 3565 put_cpu_var(perf_cpu_context);
3542 3566
3543 rcu_read_lock();
3544 /* 3567 /*
3545 * doesn't really matter which of the child contexts the 3568 * doesn't really matter which of the child contexts the
3546 * events ends up in. 3569 * events ends up in.
@@ -3679,7 +3702,11 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
3679 perf_event_disable(event); 3702 perf_event_disable(event);
3680 } 3703 }
3681 3704
3682 perf_event_output(event, nmi, data, regs); 3705 if (event->overflow_handler)
3706 event->overflow_handler(event, nmi, data, regs);
3707 else
3708 perf_event_output(event, nmi, data, regs);
3709
3683 return ret; 3710 return ret;
3684} 3711}
3685 3712
@@ -3724,16 +3751,16 @@ again:
3724 return nr; 3751 return nr;
3725} 3752}
3726 3753
3727static void perf_swevent_overflow(struct perf_event *event, 3754static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
3728 int nmi, struct perf_sample_data *data, 3755 int nmi, struct perf_sample_data *data,
3729 struct pt_regs *regs) 3756 struct pt_regs *regs)
3730{ 3757{
3731 struct hw_perf_event *hwc = &event->hw; 3758 struct hw_perf_event *hwc = &event->hw;
3732 int throttle = 0; 3759 int throttle = 0;
3733 u64 overflow;
3734 3760
3735 data->period = event->hw.last_period; 3761 data->period = event->hw.last_period;
3736 overflow = perf_swevent_set_period(event); 3762 if (!overflow)
3763 overflow = perf_swevent_set_period(event);
3737 3764
3738 if (hwc->interrupts == MAX_INTERRUPTS) 3765 if (hwc->interrupts == MAX_INTERRUPTS)
3739 return; 3766 return;
@@ -3766,14 +3793,19 @@ static void perf_swevent_add(struct perf_event *event, u64 nr,
3766 3793
3767 atomic64_add(nr, &event->count); 3794 atomic64_add(nr, &event->count);
3768 3795
3796 if (!regs)
3797 return;
3798
3769 if (!hwc->sample_period) 3799 if (!hwc->sample_period)
3770 return; 3800 return;
3771 3801
3772 if (!regs) 3802 if (nr == 1 && hwc->sample_period == 1 && !event->attr.freq)
3803 return perf_swevent_overflow(event, 1, nmi, data, regs);
3804
3805 if (atomic64_add_negative(nr, &hwc->period_left))
3773 return; 3806 return;
3774 3807
3775 if (!atomic64_add_negative(nr, &hwc->period_left)) 3808 perf_swevent_overflow(event, 0, nmi, data, regs);
3776 perf_swevent_overflow(event, nmi, data, regs);
3777} 3809}
3778 3810
3779static int perf_swevent_is_counting(struct perf_event *event) 3811static int perf_swevent_is_counting(struct perf_event *event)
@@ -3806,25 +3838,44 @@ static int perf_swevent_is_counting(struct perf_event *event)
3806 return 1; 3838 return 1;
3807} 3839}
3808 3840
3841static int perf_tp_event_match(struct perf_event *event,
3842 struct perf_sample_data *data);
3843
3844static int perf_exclude_event(struct perf_event *event,
3845 struct pt_regs *regs)
3846{
3847 if (regs) {
3848 if (event->attr.exclude_user && user_mode(regs))
3849 return 1;
3850
3851 if (event->attr.exclude_kernel && !user_mode(regs))
3852 return 1;
3853 }
3854
3855 return 0;
3856}
3857
3809static int perf_swevent_match(struct perf_event *event, 3858static int perf_swevent_match(struct perf_event *event,
3810 enum perf_type_id type, 3859 enum perf_type_id type,
3811 u32 event_id, struct pt_regs *regs) 3860 u32 event_id,
3861 struct perf_sample_data *data,
3862 struct pt_regs *regs)
3812{ 3863{
3813 if (!perf_swevent_is_counting(event)) 3864 if (!perf_swevent_is_counting(event))
3814 return 0; 3865 return 0;
3815 3866
3816 if (event->attr.type != type) 3867 if (event->attr.type != type)
3817 return 0; 3868 return 0;
3869
3818 if (event->attr.config != event_id) 3870 if (event->attr.config != event_id)
3819 return 0; 3871 return 0;
3820 3872
3821 if (regs) { 3873 if (perf_exclude_event(event, regs))
3822 if (event->attr.exclude_user && user_mode(regs)) 3874 return 0;
3823 return 0;
3824 3875
3825 if (event->attr.exclude_kernel && !user_mode(regs)) 3876 if (event->attr.type == PERF_TYPE_TRACEPOINT &&
3826 return 0; 3877 !perf_tp_event_match(event, data))
3827 } 3878 return 0;
3828 3879
3829 return 1; 3880 return 1;
3830} 3881}
@@ -3837,49 +3888,59 @@ static void perf_swevent_ctx_event(struct perf_event_context *ctx,
3837{ 3888{
3838 struct perf_event *event; 3889 struct perf_event *event;
3839 3890
3840 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
3841 return;
3842
3843 rcu_read_lock();
3844 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { 3891 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
3845 if (perf_swevent_match(event, type, event_id, regs)) 3892 if (perf_swevent_match(event, type, event_id, data, regs))
3846 perf_swevent_add(event, nr, nmi, data, regs); 3893 perf_swevent_add(event, nr, nmi, data, regs);
3847 } 3894 }
3848 rcu_read_unlock();
3849} 3895}
3850 3896
3851static int *perf_swevent_recursion_context(struct perf_cpu_context *cpuctx) 3897int perf_swevent_get_recursion_context(void)
3852{ 3898{
3899 struct perf_cpu_context *cpuctx = &get_cpu_var(perf_cpu_context);
3900 int rctx;
3901
3853 if (in_nmi()) 3902 if (in_nmi())
3854 return &cpuctx->recursion[3]; 3903 rctx = 3;
3904 else if (in_irq())
3905 rctx = 2;
3906 else if (in_softirq())
3907 rctx = 1;
3908 else
3909 rctx = 0;
3910
3911 if (cpuctx->recursion[rctx]) {
3912 put_cpu_var(perf_cpu_context);
3913 return -1;
3914 }
3855 3915
3856 if (in_irq()) 3916 cpuctx->recursion[rctx]++;
3857 return &cpuctx->recursion[2]; 3917 barrier();
3858 3918
3859 if (in_softirq()) 3919 return rctx;
3860 return &cpuctx->recursion[1]; 3920}
3921EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context);
3861 3922
3862 return &cpuctx->recursion[0]; 3923void perf_swevent_put_recursion_context(int rctx)
3924{
3925 struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
3926 barrier();
3927 cpuctx->recursion[rctx]--;
3928 put_cpu_var(perf_cpu_context);
3863} 3929}
3930EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context);
3864 3931
3865static void do_perf_sw_event(enum perf_type_id type, u32 event_id, 3932static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
3866 u64 nr, int nmi, 3933 u64 nr, int nmi,
3867 struct perf_sample_data *data, 3934 struct perf_sample_data *data,
3868 struct pt_regs *regs) 3935 struct pt_regs *regs)
3869{ 3936{
3870 struct perf_cpu_context *cpuctx = &get_cpu_var(perf_cpu_context); 3937 struct perf_cpu_context *cpuctx;
3871 int *recursion = perf_swevent_recursion_context(cpuctx);
3872 struct perf_event_context *ctx; 3938 struct perf_event_context *ctx;
3873 3939
3874 if (*recursion) 3940 cpuctx = &__get_cpu_var(perf_cpu_context);
3875 goto out; 3941 rcu_read_lock();
3876
3877 (*recursion)++;
3878 barrier();
3879
3880 perf_swevent_ctx_event(&cpuctx->ctx, type, event_id, 3942 perf_swevent_ctx_event(&cpuctx->ctx, type, event_id,
3881 nr, nmi, data, regs); 3943 nr, nmi, data, regs);
3882 rcu_read_lock();
3883 /* 3944 /*
3884 * doesn't really matter which of the child contexts the 3945 * doesn't really matter which of the child contexts the
3885 * events ends up in. 3946 * events ends up in.
@@ -3888,23 +3949,24 @@ static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
3888 if (ctx) 3949 if (ctx)
3889 perf_swevent_ctx_event(ctx, type, event_id, nr, nmi, data, regs); 3950 perf_swevent_ctx_event(ctx, type, event_id, nr, nmi, data, regs);
3890 rcu_read_unlock(); 3951 rcu_read_unlock();
3891
3892 barrier();
3893 (*recursion)--;
3894
3895out:
3896 put_cpu_var(perf_cpu_context);
3897} 3952}
3898 3953
3899void __perf_sw_event(u32 event_id, u64 nr, int nmi, 3954void __perf_sw_event(u32 event_id, u64 nr, int nmi,
3900 struct pt_regs *regs, u64 addr) 3955 struct pt_regs *regs, u64 addr)
3901{ 3956{
3902 struct perf_sample_data data = { 3957 struct perf_sample_data data;
3903 .addr = addr, 3958 int rctx;
3904 };
3905 3959
3906 do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, 3960 rctx = perf_swevent_get_recursion_context();
3907 &data, regs); 3961 if (rctx < 0)
3962 return;
3963
3964 data.addr = addr;
3965 data.raw = NULL;
3966
3967 do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
3968
3969 perf_swevent_put_recursion_context(rctx);
3908} 3970}
3909 3971
3910static void perf_swevent_read(struct perf_event *event) 3972static void perf_swevent_read(struct perf_event *event)
@@ -3949,6 +4011,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
3949 event->pmu->read(event); 4011 event->pmu->read(event);
3950 4012
3951 data.addr = 0; 4013 data.addr = 0;
4014 data.period = event->hw.last_period;
3952 regs = get_irq_regs(); 4015 regs = get_irq_regs();
3953 /* 4016 /*
3954 * In case we exclude kernel IPs or are somehow not in interrupt 4017 * In case we exclude kernel IPs or are somehow not in interrupt
@@ -4108,6 +4171,7 @@ static const struct pmu perf_ops_task_clock = {
4108}; 4171};
4109 4172
4110#ifdef CONFIG_EVENT_PROFILE 4173#ifdef CONFIG_EVENT_PROFILE
4174
4111void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 4175void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4112 int entry_size) 4176 int entry_size)
4113{ 4177{
@@ -4126,13 +4190,21 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4126 if (!regs) 4190 if (!regs)
4127 regs = task_pt_regs(current); 4191 regs = task_pt_regs(current);
4128 4192
4193 /* Trace events already protected against recursion */
4129 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, 4194 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
4130 &data, regs); 4195 &data, regs);
4131} 4196}
4132EXPORT_SYMBOL_GPL(perf_tp_event); 4197EXPORT_SYMBOL_GPL(perf_tp_event);
4133 4198
4134extern int ftrace_profile_enable(int); 4199static int perf_tp_event_match(struct perf_event *event,
4135extern void ftrace_profile_disable(int); 4200 struct perf_sample_data *data)
4201{
4202 void *record = data->raw->data;
4203
4204 if (likely(!event->filter) || filter_match_preds(event->filter, record))
4205 return 1;
4206 return 0;
4207}
4136 4208
4137static void tp_perf_event_destroy(struct perf_event *event) 4209static void tp_perf_event_destroy(struct perf_event *event)
4138{ 4210{
@@ -4157,11 +4229,99 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event)
4157 4229
4158 return &perf_ops_generic; 4230 return &perf_ops_generic;
4159} 4231}
4232
4233static int perf_event_set_filter(struct perf_event *event, void __user *arg)
4234{
4235 char *filter_str;
4236 int ret;
4237
4238 if (event->attr.type != PERF_TYPE_TRACEPOINT)
4239 return -EINVAL;
4240
4241 filter_str = strndup_user(arg, PAGE_SIZE);
4242 if (IS_ERR(filter_str))
4243 return PTR_ERR(filter_str);
4244
4245 ret = ftrace_profile_set_filter(event, event->attr.config, filter_str);
4246
4247 kfree(filter_str);
4248 return ret;
4249}
4250
4251static void perf_event_free_filter(struct perf_event *event)
4252{
4253 ftrace_profile_free_filter(event);
4254}
4255
4160#else 4256#else
4257
4258static int perf_tp_event_match(struct perf_event *event,
4259 struct perf_sample_data *data)
4260{
4261 return 1;
4262}
4263
4161static const struct pmu *tp_perf_event_init(struct perf_event *event) 4264static const struct pmu *tp_perf_event_init(struct perf_event *event)
4162{ 4265{
4163 return NULL; 4266 return NULL;
4164} 4267}
4268
4269static int perf_event_set_filter(struct perf_event *event, void __user *arg)
4270{
4271 return -ENOENT;
4272}
4273
4274static void perf_event_free_filter(struct perf_event *event)
4275{
4276}
4277
4278#endif /* CONFIG_EVENT_PROFILE */
4279
4280#ifdef CONFIG_HAVE_HW_BREAKPOINT
4281static void bp_perf_event_destroy(struct perf_event *event)
4282{
4283 release_bp_slot(event);
4284}
4285
4286static const struct pmu *bp_perf_event_init(struct perf_event *bp)
4287{
4288 int err;
4289 /*
4290 * The breakpoint is already filled if we haven't created the counter
4291 * through perf syscall
4292 * FIXME: manage to get trigerred to NULL if it comes from syscalls
4293 */
4294 if (!bp->callback)
4295 err = register_perf_hw_breakpoint(bp);
4296 else
4297 err = __register_perf_hw_breakpoint(bp);
4298 if (err)
4299 return ERR_PTR(err);
4300
4301 bp->destroy = bp_perf_event_destroy;
4302
4303 return &perf_ops_bp;
4304}
4305
4306void perf_bp_event(struct perf_event *bp, void *data)
4307{
4308 struct perf_sample_data sample;
4309 struct pt_regs *regs = data;
4310
4311 sample.addr = bp->attr.bp_addr;
4312
4313 if (!perf_exclude_event(bp, regs))
4314 perf_swevent_add(bp, 1, 1, &sample, regs);
4315}
4316#else
4317static const struct pmu *bp_perf_event_init(struct perf_event *bp)
4318{
4319 return NULL;
4320}
4321
4322void perf_bp_event(struct perf_event *bp, void *regs)
4323{
4324}
4165#endif 4325#endif
4166 4326
4167atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; 4327atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
@@ -4208,6 +4368,8 @@ static const struct pmu *sw_perf_event_init(struct perf_event *event)
4208 case PERF_COUNT_SW_PAGE_FAULTS_MAJ: 4368 case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
4209 case PERF_COUNT_SW_CONTEXT_SWITCHES: 4369 case PERF_COUNT_SW_CONTEXT_SWITCHES:
4210 case PERF_COUNT_SW_CPU_MIGRATIONS: 4370 case PERF_COUNT_SW_CPU_MIGRATIONS:
4371 case PERF_COUNT_SW_ALIGNMENT_FAULTS:
4372 case PERF_COUNT_SW_EMULATION_FAULTS:
4211 if (!event->parent) { 4373 if (!event->parent) {
4212 atomic_inc(&perf_swevent_enabled[event_id]); 4374 atomic_inc(&perf_swevent_enabled[event_id]);
4213 event->destroy = sw_perf_event_destroy; 4375 event->destroy = sw_perf_event_destroy;
@@ -4228,6 +4390,7 @@ perf_event_alloc(struct perf_event_attr *attr,
4228 struct perf_event_context *ctx, 4390 struct perf_event_context *ctx,
4229 struct perf_event *group_leader, 4391 struct perf_event *group_leader,
4230 struct perf_event *parent_event, 4392 struct perf_event *parent_event,
4393 perf_callback_t callback,
4231 gfp_t gfpflags) 4394 gfp_t gfpflags)
4232{ 4395{
4233 const struct pmu *pmu; 4396 const struct pmu *pmu;
@@ -4270,6 +4433,11 @@ perf_event_alloc(struct perf_event_attr *attr,
4270 4433
4271 event->state = PERF_EVENT_STATE_INACTIVE; 4434 event->state = PERF_EVENT_STATE_INACTIVE;
4272 4435
4436 if (!callback && parent_event)
4437 callback = parent_event->callback;
4438
4439 event->callback = callback;
4440
4273 if (attr->disabled) 4441 if (attr->disabled)
4274 event->state = PERF_EVENT_STATE_OFF; 4442 event->state = PERF_EVENT_STATE_OFF;
4275 4443
@@ -4304,6 +4472,11 @@ perf_event_alloc(struct perf_event_attr *attr,
4304 pmu = tp_perf_event_init(event); 4472 pmu = tp_perf_event_init(event);
4305 break; 4473 break;
4306 4474
4475 case PERF_TYPE_BREAKPOINT:
4476 pmu = bp_perf_event_init(event);
4477 break;
4478
4479
4307 default: 4480 default:
4308 break; 4481 break;
4309 } 4482 }
@@ -4416,7 +4589,7 @@ err_size:
4416 goto out; 4589 goto out;
4417} 4590}
4418 4591
4419int perf_event_set_output(struct perf_event *event, int output_fd) 4592static int perf_event_set_output(struct perf_event *event, int output_fd)
4420{ 4593{
4421 struct perf_event *output_event = NULL; 4594 struct perf_event *output_event = NULL;
4422 struct file *output_file = NULL; 4595 struct file *output_file = NULL;
@@ -4546,7 +4719,7 @@ SYSCALL_DEFINE5(perf_event_open,
4546 } 4719 }
4547 4720
4548 event = perf_event_alloc(&attr, cpu, ctx, group_leader, 4721 event = perf_event_alloc(&attr, cpu, ctx, group_leader,
4549 NULL, GFP_KERNEL); 4722 NULL, NULL, GFP_KERNEL);
4550 err = PTR_ERR(event); 4723 err = PTR_ERR(event);
4551 if (IS_ERR(event)) 4724 if (IS_ERR(event))
4552 goto err_put_context; 4725 goto err_put_context;
@@ -4594,6 +4767,60 @@ err_put_context:
4594 return err; 4767 return err;
4595} 4768}
4596 4769
4770/**
4771 * perf_event_create_kernel_counter
4772 *
4773 * @attr: attributes of the counter to create
4774 * @cpu: cpu in which the counter is bound
4775 * @pid: task to profile
4776 */
4777struct perf_event *
4778perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
4779 pid_t pid, perf_callback_t callback)
4780{
4781 struct perf_event *event;
4782 struct perf_event_context *ctx;
4783 int err;
4784
4785 /*
4786 * Get the target context (task or percpu):
4787 */
4788
4789 ctx = find_get_context(pid, cpu);
4790 if (IS_ERR(ctx)) {
4791 err = PTR_ERR(ctx);
4792 goto err_exit;
4793 }
4794
4795 event = perf_event_alloc(attr, cpu, ctx, NULL,
4796 NULL, callback, GFP_KERNEL);
4797 if (IS_ERR(event)) {
4798 err = PTR_ERR(event);
4799 goto err_put_context;
4800 }
4801
4802 event->filp = NULL;
4803 WARN_ON_ONCE(ctx->parent_ctx);
4804 mutex_lock(&ctx->mutex);
4805 perf_install_in_context(ctx, event, cpu);
4806 ++ctx->generation;
4807 mutex_unlock(&ctx->mutex);
4808
4809 event->owner = current;
4810 get_task_struct(current);
4811 mutex_lock(&current->perf_event_mutex);
4812 list_add_tail(&event->owner_entry, &current->perf_event_list);
4813 mutex_unlock(&current->perf_event_mutex);
4814
4815 return event;
4816
4817 err_put_context:
4818 put_ctx(ctx);
4819 err_exit:
4820 return ERR_PTR(err);
4821}
4822EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
4823
4597/* 4824/*
4598 * inherit a event from parent task to child task: 4825 * inherit a event from parent task to child task:
4599 */ 4826 */
@@ -4619,7 +4846,7 @@ inherit_event(struct perf_event *parent_event,
4619 child_event = perf_event_alloc(&parent_event->attr, 4846 child_event = perf_event_alloc(&parent_event->attr,
4620 parent_event->cpu, child_ctx, 4847 parent_event->cpu, child_ctx,
4621 group_leader, parent_event, 4848 group_leader, parent_event,
4622 GFP_KERNEL); 4849 NULL, GFP_KERNEL);
4623 if (IS_ERR(child_event)) 4850 if (IS_ERR(child_event))
4624 return child_event; 4851 return child_event;
4625 get_ctx(child_ctx); 4852 get_ctx(child_ctx);
@@ -4637,6 +4864,8 @@ inherit_event(struct perf_event *parent_event,
4637 if (parent_event->attr.freq) 4864 if (parent_event->attr.freq)
4638 child_event->hw.sample_period = parent_event->hw.sample_period; 4865 child_event->hw.sample_period = parent_event->hw.sample_period;
4639 4866
4867 child_event->overflow_handler = parent_event->overflow_handler;
4868
4640 /* 4869 /*
4641 * Link it up in the child's context: 4870 * Link it up in the child's context:
4642 */ 4871 */
@@ -4726,7 +4955,6 @@ __perf_event_exit_task(struct perf_event *child_event,
4726{ 4955{
4727 struct perf_event *parent_event; 4956 struct perf_event *parent_event;
4728 4957
4729 update_event_times(child_event);
4730 perf_event_remove_from_context(child_event); 4958 perf_event_remove_from_context(child_event);
4731 4959
4732 parent_event = child_event->parent; 4960 parent_event = child_event->parent;
@@ -4778,6 +5006,7 @@ void perf_event_exit_task(struct task_struct *child)
4778 * the events from it. 5006 * the events from it.
4779 */ 5007 */
4780 unclone_ctx(child_ctx); 5008 unclone_ctx(child_ctx);
5009 update_context_time(child_ctx);
4781 spin_unlock_irqrestore(&child_ctx->lock, flags); 5010 spin_unlock_irqrestore(&child_ctx->lock, flags);
4782 5011
4783 /* 5012 /*
diff --git a/kernel/sched.c b/kernel/sched.c
index 6ae2739b8f19..e7f2cfa6a257 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -535,14 +535,12 @@ struct rq {
535 #define CPU_LOAD_IDX_MAX 5 535 #define CPU_LOAD_IDX_MAX 5
536 unsigned long cpu_load[CPU_LOAD_IDX_MAX]; 536 unsigned long cpu_load[CPU_LOAD_IDX_MAX];
537#ifdef CONFIG_NO_HZ 537#ifdef CONFIG_NO_HZ
538 unsigned long last_tick_seen;
539 unsigned char in_nohz_recently; 538 unsigned char in_nohz_recently;
540#endif 539#endif
541 /* capture load from *all* tasks on this cpu: */ 540 /* capture load from *all* tasks on this cpu: */
542 struct load_weight load; 541 struct load_weight load;
543 unsigned long nr_load_updates; 542 unsigned long nr_load_updates;
544 u64 nr_switches; 543 u64 nr_switches;
545 u64 nr_migrations_in;
546 544
547 struct cfs_rq cfs; 545 struct cfs_rq cfs;
548 struct rt_rq rt; 546 struct rt_rq rt;
@@ -591,6 +589,8 @@ struct rq {
591 589
592 u64 rt_avg; 590 u64 rt_avg;
593 u64 age_stamp; 591 u64 age_stamp;
592 u64 idle_stamp;
593 u64 avg_idle;
594#endif 594#endif
595 595
596 /* calc_load related fields */ 596 /* calc_load related fields */
@@ -772,7 +772,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf,
772 if (!sched_feat_names[i]) 772 if (!sched_feat_names[i])
773 return -EINVAL; 773 return -EINVAL;
774 774
775 filp->f_pos += cnt; 775 *ppos += cnt;
776 776
777 return cnt; 777 return cnt;
778} 778}
@@ -2017,6 +2017,7 @@ void kthread_bind(struct task_struct *p, unsigned int cpu)
2017 } 2017 }
2018 2018
2019 spin_lock_irqsave(&rq->lock, flags); 2019 spin_lock_irqsave(&rq->lock, flags);
2020 update_rq_clock(rq);
2020 set_task_cpu(p, cpu); 2021 set_task_cpu(p, cpu);
2021 p->cpus_allowed = cpumask_of_cpu(cpu); 2022 p->cpus_allowed = cpumask_of_cpu(cpu);
2022 p->rt.nr_cpus_allowed = 1; 2023 p->rt.nr_cpus_allowed = 1;
@@ -2078,7 +2079,6 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
2078#endif 2079#endif
2079 if (old_cpu != new_cpu) { 2080 if (old_cpu != new_cpu) {
2080 p->se.nr_migrations++; 2081 p->se.nr_migrations++;
2081 new_rq->nr_migrations_in++;
2082#ifdef CONFIG_SCHEDSTATS 2082#ifdef CONFIG_SCHEDSTATS
2083 if (task_hot(p, old_rq->clock, NULL)) 2083 if (task_hot(p, old_rq->clock, NULL))
2084 schedstat_inc(p, se.nr_forced2_migrations); 2084 schedstat_inc(p, se.nr_forced2_migrations);
@@ -2115,6 +2115,7 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
2115 * it is sufficient to simply update the task's cpu field. 2115 * it is sufficient to simply update the task's cpu field.
2116 */ 2116 */
2117 if (!p->se.on_rq && !task_running(rq, p)) { 2117 if (!p->se.on_rq && !task_running(rq, p)) {
2118 update_rq_clock(rq);
2118 set_task_cpu(p, dest_cpu); 2119 set_task_cpu(p, dest_cpu);
2119 return 0; 2120 return 0;
2120 } 2121 }
@@ -2376,14 +2377,15 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
2376 task_rq_unlock(rq, &flags); 2377 task_rq_unlock(rq, &flags);
2377 2378
2378 cpu = p->sched_class->select_task_rq(p, SD_BALANCE_WAKE, wake_flags); 2379 cpu = p->sched_class->select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
2379 if (cpu != orig_cpu) 2380 if (cpu != orig_cpu) {
2381 local_irq_save(flags);
2382 rq = cpu_rq(cpu);
2383 update_rq_clock(rq);
2380 set_task_cpu(p, cpu); 2384 set_task_cpu(p, cpu);
2381 2385 local_irq_restore(flags);
2386 }
2382 rq = task_rq_lock(p, &flags); 2387 rq = task_rq_lock(p, &flags);
2383 2388
2384 if (rq != orig_rq)
2385 update_rq_clock(rq);
2386
2387 WARN_ON(p->state != TASK_WAKING); 2389 WARN_ON(p->state != TASK_WAKING);
2388 cpu = task_cpu(p); 2390 cpu = task_cpu(p);
2389 2391
@@ -2440,6 +2442,17 @@ out_running:
2440#ifdef CONFIG_SMP 2442#ifdef CONFIG_SMP
2441 if (p->sched_class->task_wake_up) 2443 if (p->sched_class->task_wake_up)
2442 p->sched_class->task_wake_up(rq, p); 2444 p->sched_class->task_wake_up(rq, p);
2445
2446 if (unlikely(rq->idle_stamp)) {
2447 u64 delta = rq->clock - rq->idle_stamp;
2448 u64 max = 2*sysctl_sched_migration_cost;
2449
2450 if (delta > max)
2451 rq->avg_idle = max;
2452 else
2453 update_avg(&rq->avg_idle, delta);
2454 rq->idle_stamp = 0;
2455 }
2443#endif 2456#endif
2444out: 2457out:
2445 task_rq_unlock(rq, &flags); 2458 task_rq_unlock(rq, &flags);
@@ -2545,6 +2558,7 @@ static void __sched_fork(struct task_struct *p)
2545void sched_fork(struct task_struct *p, int clone_flags) 2558void sched_fork(struct task_struct *p, int clone_flags)
2546{ 2559{
2547 int cpu = get_cpu(); 2560 int cpu = get_cpu();
2561 unsigned long flags;
2548 2562
2549 __sched_fork(p); 2563 __sched_fork(p);
2550 2564
@@ -2581,7 +2595,10 @@ void sched_fork(struct task_struct *p, int clone_flags)
2581#ifdef CONFIG_SMP 2595#ifdef CONFIG_SMP
2582 cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0); 2596 cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0);
2583#endif 2597#endif
2598 local_irq_save(flags);
2599 update_rq_clock(cpu_rq(cpu));
2584 set_task_cpu(p, cpu); 2600 set_task_cpu(p, cpu);
2601 local_irq_restore(flags);
2585 2602
2586#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) 2603#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
2587 if (likely(sched_info_on())) 2604 if (likely(sched_info_on()))
@@ -2848,14 +2865,14 @@ context_switch(struct rq *rq, struct task_struct *prev,
2848 */ 2865 */
2849 arch_start_context_switch(prev); 2866 arch_start_context_switch(prev);
2850 2867
2851 if (unlikely(!mm)) { 2868 if (likely(!mm)) {
2852 next->active_mm = oldmm; 2869 next->active_mm = oldmm;
2853 atomic_inc(&oldmm->mm_count); 2870 atomic_inc(&oldmm->mm_count);
2854 enter_lazy_tlb(oldmm, next); 2871 enter_lazy_tlb(oldmm, next);
2855 } else 2872 } else
2856 switch_mm(oldmm, mm, next); 2873 switch_mm(oldmm, mm, next);
2857 2874
2858 if (unlikely(!prev->mm)) { 2875 if (likely(!prev->mm)) {
2859 prev->active_mm = NULL; 2876 prev->active_mm = NULL;
2860 rq->prev_mm = oldmm; 2877 rq->prev_mm = oldmm;
2861 } 2878 }
@@ -3018,15 +3035,6 @@ static void calc_load_account_active(struct rq *this_rq)
3018} 3035}
3019 3036
3020/* 3037/*
3021 * Externally visible per-cpu scheduler statistics:
3022 * cpu_nr_migrations(cpu) - number of migrations into that cpu
3023 */
3024u64 cpu_nr_migrations(int cpu)
3025{
3026 return cpu_rq(cpu)->nr_migrations_in;
3027}
3028
3029/*
3030 * Update rq->cpu_load[] statistics. This function is usually called every 3038 * Update rq->cpu_load[] statistics. This function is usually called every
3031 * scheduler tick (TICK_NSEC). 3039 * scheduler tick (TICK_NSEC).
3032 */ 3040 */
@@ -4126,7 +4134,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
4126 unsigned long flags; 4134 unsigned long flags;
4127 struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); 4135 struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
4128 4136
4129 cpumask_setall(cpus); 4137 cpumask_copy(cpus, cpu_online_mask);
4130 4138
4131 /* 4139 /*
4132 * When power savings policy is enabled for the parent domain, idle 4140 * When power savings policy is enabled for the parent domain, idle
@@ -4289,7 +4297,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
4289 int all_pinned = 0; 4297 int all_pinned = 0;
4290 struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); 4298 struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
4291 4299
4292 cpumask_setall(cpus); 4300 cpumask_copy(cpus, cpu_online_mask);
4293 4301
4294 /* 4302 /*
4295 * When power savings policy is enabled for the parent domain, idle 4303 * When power savings policy is enabled for the parent domain, idle
@@ -4429,6 +4437,11 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
4429 int pulled_task = 0; 4437 int pulled_task = 0;
4430 unsigned long next_balance = jiffies + HZ; 4438 unsigned long next_balance = jiffies + HZ;
4431 4439
4440 this_rq->idle_stamp = this_rq->clock;
4441
4442 if (this_rq->avg_idle < sysctl_sched_migration_cost)
4443 return;
4444
4432 for_each_domain(this_cpu, sd) { 4445 for_each_domain(this_cpu, sd) {
4433 unsigned long interval; 4446 unsigned long interval;
4434 4447
@@ -4443,8 +4456,10 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
4443 interval = msecs_to_jiffies(sd->balance_interval); 4456 interval = msecs_to_jiffies(sd->balance_interval);
4444 if (time_after(next_balance, sd->last_balance + interval)) 4457 if (time_after(next_balance, sd->last_balance + interval))
4445 next_balance = sd->last_balance + interval; 4458 next_balance = sd->last_balance + interval;
4446 if (pulled_task) 4459 if (pulled_task) {
4460 this_rq->idle_stamp = 0;
4447 break; 4461 break;
4462 }
4448 } 4463 }
4449 if (pulled_task || time_after(jiffies, this_rq->next_balance)) { 4464 if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
4450 /* 4465 /*
@@ -5046,8 +5061,13 @@ static void account_guest_time(struct task_struct *p, cputime_t cputime,
5046 p->gtime = cputime_add(p->gtime, cputime); 5061 p->gtime = cputime_add(p->gtime, cputime);
5047 5062
5048 /* Add guest time to cpustat. */ 5063 /* Add guest time to cpustat. */
5049 cpustat->user = cputime64_add(cpustat->user, tmp); 5064 if (TASK_NICE(p) > 0) {
5050 cpustat->guest = cputime64_add(cpustat->guest, tmp); 5065 cpustat->nice = cputime64_add(cpustat->nice, tmp);
5066 cpustat->guest_nice = cputime64_add(cpustat->guest_nice, tmp);
5067 } else {
5068 cpustat->user = cputime64_add(cpustat->user, tmp);
5069 cpustat->guest = cputime64_add(cpustat->guest, tmp);
5070 }
5051} 5071}
5052 5072
5053/* 5073/*
@@ -5162,60 +5182,86 @@ void account_idle_ticks(unsigned long ticks)
5162 * Use precise platform statistics if available: 5182 * Use precise platform statistics if available:
5163 */ 5183 */
5164#ifdef CONFIG_VIRT_CPU_ACCOUNTING 5184#ifdef CONFIG_VIRT_CPU_ACCOUNTING
5165cputime_t task_utime(struct task_struct *p) 5185void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
5166{ 5186{
5167 return p->utime; 5187 *ut = p->utime;
5188 *st = p->stime;
5168} 5189}
5169 5190
5170cputime_t task_stime(struct task_struct *p) 5191void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
5171{ 5192{
5172 return p->stime; 5193 struct task_cputime cputime;
5194
5195 thread_group_cputime(p, &cputime);
5196
5197 *ut = cputime.utime;
5198 *st = cputime.stime;
5173} 5199}
5174#else 5200#else
5175cputime_t task_utime(struct task_struct *p) 5201
5202#ifndef nsecs_to_cputime
5203# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs)
5204#endif
5205
5206void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
5176{ 5207{
5177 clock_t utime = cputime_to_clock_t(p->utime), 5208 cputime_t rtime, utime = p->utime, total = cputime_add(utime, p->stime);
5178 total = utime + cputime_to_clock_t(p->stime);
5179 u64 temp;
5180 5209
5181 /* 5210 /*
5182 * Use CFS's precise accounting: 5211 * Use CFS's precise accounting:
5183 */ 5212 */
5184 temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); 5213 rtime = nsecs_to_cputime(p->se.sum_exec_runtime);
5185 5214
5186 if (total) { 5215 if (total) {
5187 temp *= utime; 5216 u64 temp;
5217
5218 temp = (u64)(rtime * utime);
5188 do_div(temp, total); 5219 do_div(temp, total);
5189 } 5220 utime = (cputime_t)temp;
5190 utime = (clock_t)temp; 5221 } else
5222 utime = rtime;
5223
5224 /*
5225 * Compare with previous values, to keep monotonicity:
5226 */
5227 p->prev_utime = max(p->prev_utime, utime);
5228 p->prev_stime = max(p->prev_stime, cputime_sub(rtime, p->prev_utime));
5191 5229
5192 p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); 5230 *ut = p->prev_utime;
5193 return p->prev_utime; 5231 *st = p->prev_stime;
5194} 5232}
5195 5233
5196cputime_t task_stime(struct task_struct *p) 5234/*
5235 * Must be called with siglock held.
5236 */
5237void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
5197{ 5238{
5198 clock_t stime; 5239 struct signal_struct *sig = p->signal;
5240 struct task_cputime cputime;
5241 cputime_t rtime, utime, total;
5199 5242
5200 /* 5243 thread_group_cputime(p, &cputime);
5201 * Use CFS's precise accounting. (we subtract utime from
5202 * the total, to make sure the total observed by userspace
5203 * grows monotonically - apps rely on that):
5204 */
5205 stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
5206 cputime_to_clock_t(task_utime(p));
5207 5244
5208 if (stime >= 0) 5245 total = cputime_add(cputime.utime, cputime.stime);
5209 p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); 5246 rtime = nsecs_to_cputime(cputime.sum_exec_runtime);
5210 5247
5211 return p->prev_stime; 5248 if (total) {
5212} 5249 u64 temp;
5213#endif
5214 5250
5215inline cputime_t task_gtime(struct task_struct *p) 5251 temp = (u64)(rtime * cputime.utime);
5216{ 5252 do_div(temp, total);
5217 return p->gtime; 5253 utime = (cputime_t)temp;
5254 } else
5255 utime = rtime;
5256
5257 sig->prev_utime = max(sig->prev_utime, utime);
5258 sig->prev_stime = max(sig->prev_stime,
5259 cputime_sub(rtime, sig->prev_utime));
5260
5261 *ut = sig->prev_utime;
5262 *st = sig->prev_stime;
5218} 5263}
5264#endif
5219 5265
5220/* 5266/*
5221 * This function gets called by the timer code, with HZ frequency. 5267 * This function gets called by the timer code, with HZ frequency.
@@ -6175,22 +6221,14 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
6175 BUG_ON(p->se.on_rq); 6221 BUG_ON(p->se.on_rq);
6176 6222
6177 p->policy = policy; 6223 p->policy = policy;
6178 switch (p->policy) {
6179 case SCHED_NORMAL:
6180 case SCHED_BATCH:
6181 case SCHED_IDLE:
6182 p->sched_class = &fair_sched_class;
6183 break;
6184 case SCHED_FIFO:
6185 case SCHED_RR:
6186 p->sched_class = &rt_sched_class;
6187 break;
6188 }
6189
6190 p->rt_priority = prio; 6224 p->rt_priority = prio;
6191 p->normal_prio = normal_prio(p); 6225 p->normal_prio = normal_prio(p);
6192 /* we are holding p->pi_lock already */ 6226 /* we are holding p->pi_lock already */
6193 p->prio = rt_mutex_getprio(p); 6227 p->prio = rt_mutex_getprio(p);
6228 if (rt_prio(p->prio))
6229 p->sched_class = &rt_sched_class;
6230 else
6231 p->sched_class = &fair_sched_class;
6194 set_load_weight(p); 6232 set_load_weight(p);
6195} 6233}
6196 6234
@@ -6935,7 +6973,7 @@ void show_state_filter(unsigned long state_filter)
6935 /* 6973 /*
6936 * Only show locks if all tasks are dumped: 6974 * Only show locks if all tasks are dumped:
6937 */ 6975 */
6938 if (state_filter == -1) 6976 if (!state_filter)
6939 debug_show_all_locks(); 6977 debug_show_all_locks();
6940} 6978}
6941 6979
@@ -7406,17 +7444,16 @@ static struct ctl_table sd_ctl_dir[] = {
7406 .procname = "sched_domain", 7444 .procname = "sched_domain",
7407 .mode = 0555, 7445 .mode = 0555,
7408 }, 7446 },
7409 {0, }, 7447 {}
7410}; 7448};
7411 7449
7412static struct ctl_table sd_ctl_root[] = { 7450static struct ctl_table sd_ctl_root[] = {
7413 { 7451 {
7414 .ctl_name = CTL_KERN,
7415 .procname = "kernel", 7452 .procname = "kernel",
7416 .mode = 0555, 7453 .mode = 0555,
7417 .child = sd_ctl_dir, 7454 .child = sd_ctl_dir,
7418 }, 7455 },
7419 {0, }, 7456 {}
7420}; 7457};
7421 7458
7422static struct ctl_table *sd_alloc_ctl_entry(int n) 7459static struct ctl_table *sd_alloc_ctl_entry(int n)
@@ -7740,6 +7777,16 @@ early_initcall(migration_init);
7740 7777
7741#ifdef CONFIG_SCHED_DEBUG 7778#ifdef CONFIG_SCHED_DEBUG
7742 7779
7780static __read_mostly int sched_domain_debug_enabled;
7781
7782static int __init sched_domain_debug_setup(char *str)
7783{
7784 sched_domain_debug_enabled = 1;
7785
7786 return 0;
7787}
7788early_param("sched_debug", sched_domain_debug_setup);
7789
7743static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, 7790static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
7744 struct cpumask *groupmask) 7791 struct cpumask *groupmask)
7745{ 7792{
@@ -7826,6 +7873,9 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
7826 cpumask_var_t groupmask; 7873 cpumask_var_t groupmask;
7827 int level = 0; 7874 int level = 0;
7828 7875
7876 if (!sched_domain_debug_enabled)
7877 return;
7878
7829 if (!sd) { 7879 if (!sd) {
7830 printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu); 7880 printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
7831 return; 7881 return;
@@ -7905,6 +7955,8 @@ sd_parent_degenerate(struct sched_domain *sd, struct sched_domain *parent)
7905 7955
7906static void free_rootdomain(struct root_domain *rd) 7956static void free_rootdomain(struct root_domain *rd)
7907{ 7957{
7958 synchronize_sched();
7959
7908 cpupri_cleanup(&rd->cpupri); 7960 cpupri_cleanup(&rd->cpupri);
7909 7961
7910 free_cpumask_var(rd->rto_mask); 7962 free_cpumask_var(rd->rto_mask);
@@ -8045,6 +8097,7 @@ static cpumask_var_t cpu_isolated_map;
8045/* Setup the mask of cpus configured for isolated domains */ 8097/* Setup the mask of cpus configured for isolated domains */
8046static int __init isolated_cpu_setup(char *str) 8098static int __init isolated_cpu_setup(char *str)
8047{ 8099{
8100 alloc_bootmem_cpumask_var(&cpu_isolated_map);
8048 cpulist_parse(str, cpu_isolated_map); 8101 cpulist_parse(str, cpu_isolated_map);
8049 return 1; 8102 return 1;
8050} 8103}
@@ -8881,7 +8934,7 @@ static int build_sched_domains(const struct cpumask *cpu_map)
8881 return __build_sched_domains(cpu_map, NULL); 8934 return __build_sched_domains(cpu_map, NULL);
8882} 8935}
8883 8936
8884static struct cpumask *doms_cur; /* current sched domains */ 8937static cpumask_var_t *doms_cur; /* current sched domains */
8885static int ndoms_cur; /* number of sched domains in 'doms_cur' */ 8938static int ndoms_cur; /* number of sched domains in 'doms_cur' */
8886static struct sched_domain_attr *dattr_cur; 8939static struct sched_domain_attr *dattr_cur;
8887 /* attribues of custom domains in 'doms_cur' */ 8940 /* attribues of custom domains in 'doms_cur' */
@@ -8903,6 +8956,31 @@ int __attribute__((weak)) arch_update_cpu_topology(void)
8903 return 0; 8956 return 0;
8904} 8957}
8905 8958
8959cpumask_var_t *alloc_sched_domains(unsigned int ndoms)
8960{
8961 int i;
8962 cpumask_var_t *doms;
8963
8964 doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL);
8965 if (!doms)
8966 return NULL;
8967 for (i = 0; i < ndoms; i++) {
8968 if (!alloc_cpumask_var(&doms[i], GFP_KERNEL)) {
8969 free_sched_domains(doms, i);
8970 return NULL;
8971 }
8972 }
8973 return doms;
8974}
8975
8976void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms)
8977{
8978 unsigned int i;
8979 for (i = 0; i < ndoms; i++)
8980 free_cpumask_var(doms[i]);
8981 kfree(doms);
8982}
8983
8906/* 8984/*
8907 * Set up scheduler domains and groups. Callers must hold the hotplug lock. 8985 * Set up scheduler domains and groups. Callers must hold the hotplug lock.
8908 * For now this just excludes isolated cpus, but could be used to 8986 * For now this just excludes isolated cpus, but could be used to
@@ -8914,12 +8992,12 @@ static int arch_init_sched_domains(const struct cpumask *cpu_map)
8914 8992
8915 arch_update_cpu_topology(); 8993 arch_update_cpu_topology();
8916 ndoms_cur = 1; 8994 ndoms_cur = 1;
8917 doms_cur = kmalloc(cpumask_size(), GFP_KERNEL); 8995 doms_cur = alloc_sched_domains(ndoms_cur);
8918 if (!doms_cur) 8996 if (!doms_cur)
8919 doms_cur = fallback_doms; 8997 doms_cur = &fallback_doms;
8920 cpumask_andnot(doms_cur, cpu_map, cpu_isolated_map); 8998 cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map);
8921 dattr_cur = NULL; 8999 dattr_cur = NULL;
8922 err = build_sched_domains(doms_cur); 9000 err = build_sched_domains(doms_cur[0]);
8923 register_sched_domain_sysctl(); 9001 register_sched_domain_sysctl();
8924 9002
8925 return err; 9003 return err;
@@ -8969,19 +9047,19 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
8969 * doms_new[] to the current sched domain partitioning, doms_cur[]. 9047 * doms_new[] to the current sched domain partitioning, doms_cur[].
8970 * It destroys each deleted domain and builds each new domain. 9048 * It destroys each deleted domain and builds each new domain.
8971 * 9049 *
8972 * 'doms_new' is an array of cpumask's of length 'ndoms_new'. 9050 * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'.
8973 * The masks don't intersect (don't overlap.) We should setup one 9051 * The masks don't intersect (don't overlap.) We should setup one
8974 * sched domain for each mask. CPUs not in any of the cpumasks will 9052 * sched domain for each mask. CPUs not in any of the cpumasks will
8975 * not be load balanced. If the same cpumask appears both in the 9053 * not be load balanced. If the same cpumask appears both in the
8976 * current 'doms_cur' domains and in the new 'doms_new', we can leave 9054 * current 'doms_cur' domains and in the new 'doms_new', we can leave
8977 * it as it is. 9055 * it as it is.
8978 * 9056 *
8979 * The passed in 'doms_new' should be kmalloc'd. This routine takes 9057 * The passed in 'doms_new' should be allocated using
8980 * ownership of it and will kfree it when done with it. If the caller 9058 * alloc_sched_domains. This routine takes ownership of it and will
8981 * failed the kmalloc call, then it can pass in doms_new == NULL && 9059 * free_sched_domains it when done with it. If the caller failed the
8982 * ndoms_new == 1, and partition_sched_domains() will fallback to 9060 * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1,
8983 * the single partition 'fallback_doms', it also forces the domains 9061 * and partition_sched_domains() will fallback to the single partition
8984 * to be rebuilt. 9062 * 'fallback_doms', it also forces the domains to be rebuilt.
8985 * 9063 *
8986 * If doms_new == NULL it will be replaced with cpu_online_mask. 9064 * If doms_new == NULL it will be replaced with cpu_online_mask.
8987 * ndoms_new == 0 is a special case for destroying existing domains, 9065 * ndoms_new == 0 is a special case for destroying existing domains,
@@ -8989,8 +9067,7 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
8989 * 9067 *
8990 * Call with hotplug lock held 9068 * Call with hotplug lock held
8991 */ 9069 */
8992/* FIXME: Change to struct cpumask *doms_new[] */ 9070void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
8993void partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
8994 struct sched_domain_attr *dattr_new) 9071 struct sched_domain_attr *dattr_new)
8995{ 9072{
8996 int i, j, n; 9073 int i, j, n;
@@ -9009,40 +9086,40 @@ void partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
9009 /* Destroy deleted domains */ 9086 /* Destroy deleted domains */
9010 for (i = 0; i < ndoms_cur; i++) { 9087 for (i = 0; i < ndoms_cur; i++) {
9011 for (j = 0; j < n && !new_topology; j++) { 9088 for (j = 0; j < n && !new_topology; j++) {
9012 if (cpumask_equal(&doms_cur[i], &doms_new[j]) 9089 if (cpumask_equal(doms_cur[i], doms_new[j])
9013 && dattrs_equal(dattr_cur, i, dattr_new, j)) 9090 && dattrs_equal(dattr_cur, i, dattr_new, j))
9014 goto match1; 9091 goto match1;
9015 } 9092 }
9016 /* no match - a current sched domain not in new doms_new[] */ 9093 /* no match - a current sched domain not in new doms_new[] */
9017 detach_destroy_domains(doms_cur + i); 9094 detach_destroy_domains(doms_cur[i]);
9018match1: 9095match1:
9019 ; 9096 ;
9020 } 9097 }
9021 9098
9022 if (doms_new == NULL) { 9099 if (doms_new == NULL) {
9023 ndoms_cur = 0; 9100 ndoms_cur = 0;
9024 doms_new = fallback_doms; 9101 doms_new = &fallback_doms;
9025 cpumask_andnot(&doms_new[0], cpu_online_mask, cpu_isolated_map); 9102 cpumask_andnot(doms_new[0], cpu_online_mask, cpu_isolated_map);
9026 WARN_ON_ONCE(dattr_new); 9103 WARN_ON_ONCE(dattr_new);
9027 } 9104 }
9028 9105
9029 /* Build new domains */ 9106 /* Build new domains */
9030 for (i = 0; i < ndoms_new; i++) { 9107 for (i = 0; i < ndoms_new; i++) {
9031 for (j = 0; j < ndoms_cur && !new_topology; j++) { 9108 for (j = 0; j < ndoms_cur && !new_topology; j++) {
9032 if (cpumask_equal(&doms_new[i], &doms_cur[j]) 9109 if (cpumask_equal(doms_new[i], doms_cur[j])
9033 && dattrs_equal(dattr_new, i, dattr_cur, j)) 9110 && dattrs_equal(dattr_new, i, dattr_cur, j))
9034 goto match2; 9111 goto match2;
9035 } 9112 }
9036 /* no match - add a new doms_new */ 9113 /* no match - add a new doms_new */
9037 __build_sched_domains(doms_new + i, 9114 __build_sched_domains(doms_new[i],
9038 dattr_new ? dattr_new + i : NULL); 9115 dattr_new ? dattr_new + i : NULL);
9039match2: 9116match2:
9040 ; 9117 ;
9041 } 9118 }
9042 9119
9043 /* Remember the new sched domains */ 9120 /* Remember the new sched domains */
9044 if (doms_cur != fallback_doms) 9121 if (doms_cur != &fallback_doms)
9045 kfree(doms_cur); 9122 free_sched_domains(doms_cur, ndoms_cur);
9046 kfree(dattr_cur); /* kfree(NULL) is safe */ 9123 kfree(dattr_cur); /* kfree(NULL) is safe */
9047 doms_cur = doms_new; 9124 doms_cur = doms_new;
9048 dattr_cur = dattr_new; 9125 dattr_cur = dattr_new;
@@ -9364,10 +9441,6 @@ void __init sched_init(void)
9364#ifdef CONFIG_CPUMASK_OFFSTACK 9441#ifdef CONFIG_CPUMASK_OFFSTACK
9365 alloc_size += num_possible_cpus() * cpumask_size(); 9442 alloc_size += num_possible_cpus() * cpumask_size();
9366#endif 9443#endif
9367 /*
9368 * As sched_init() is called before page_alloc is setup,
9369 * we use alloc_bootmem().
9370 */
9371 if (alloc_size) { 9444 if (alloc_size) {
9372 ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT); 9445 ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT);
9373 9446
@@ -9522,6 +9595,8 @@ void __init sched_init(void)
9522 rq->cpu = i; 9595 rq->cpu = i;
9523 rq->online = 0; 9596 rq->online = 0;
9524 rq->migration_thread = NULL; 9597 rq->migration_thread = NULL;
9598 rq->idle_stamp = 0;
9599 rq->avg_idle = 2*sysctl_sched_migration_cost;
9525 INIT_LIST_HEAD(&rq->migration_queue); 9600 INIT_LIST_HEAD(&rq->migration_queue);
9526 rq_attach_root(rq, &def_root_domain); 9601 rq_attach_root(rq, &def_root_domain);
9527#endif 9602#endif
@@ -9571,7 +9646,9 @@ void __init sched_init(void)
9571 zalloc_cpumask_var(&nohz.cpu_mask, GFP_NOWAIT); 9646 zalloc_cpumask_var(&nohz.cpu_mask, GFP_NOWAIT);
9572 alloc_cpumask_var(&nohz.ilb_grp_nohz_mask, GFP_NOWAIT); 9647 alloc_cpumask_var(&nohz.ilb_grp_nohz_mask, GFP_NOWAIT);
9573#endif 9648#endif
9574 zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); 9649 /* May be allocated at isolcpus cmdline parse time */
9650 if (cpu_isolated_map == NULL)
9651 zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
9575#endif /* SMP */ 9652#endif /* SMP */
9576 9653
9577 perf_event_init(); 9654 perf_event_init();
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index efb84409bc43..6988cf08f705 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -285,12 +285,16 @@ static void print_cpu(struct seq_file *m, int cpu)
285 285
286#ifdef CONFIG_SCHEDSTATS 286#ifdef CONFIG_SCHEDSTATS
287#define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n); 287#define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n);
288#define P64(n) SEQ_printf(m, " .%-30s: %Ld\n", #n, rq->n);
288 289
289 P(yld_count); 290 P(yld_count);
290 291
291 P(sched_switch); 292 P(sched_switch);
292 P(sched_count); 293 P(sched_count);
293 P(sched_goidle); 294 P(sched_goidle);
295#ifdef CONFIG_SMP
296 P64(avg_idle);
297#endif
294 298
295 P(ttwu_count); 299 P(ttwu_count);
296 P(ttwu_local); 300 P(ttwu_local);
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 37087a7fac22..f61837ad336d 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -1345,6 +1345,37 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
1345} 1345}
1346 1346
1347/* 1347/*
1348 * Try and locate an idle CPU in the sched_domain.
1349 */
1350static int
1351select_idle_sibling(struct task_struct *p, struct sched_domain *sd, int target)
1352{
1353 int cpu = smp_processor_id();
1354 int prev_cpu = task_cpu(p);
1355 int i;
1356
1357 /*
1358 * If this domain spans both cpu and prev_cpu (see the SD_WAKE_AFFINE
1359 * test in select_task_rq_fair) and the prev_cpu is idle then that's
1360 * always a better target than the current cpu.
1361 */
1362 if (target == cpu && !cpu_rq(prev_cpu)->cfs.nr_running)
1363 return prev_cpu;
1364
1365 /*
1366 * Otherwise, iterate the domain and find an elegible idle cpu.
1367 */
1368 for_each_cpu_and(i, sched_domain_span(sd), &p->cpus_allowed) {
1369 if (!cpu_rq(i)->cfs.nr_running) {
1370 target = i;
1371 break;
1372 }
1373 }
1374
1375 return target;
1376}
1377
1378/*
1348 * sched_balance_self: balance the current task (running on cpu) in domains 1379 * sched_balance_self: balance the current task (running on cpu) in domains
1349 * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and 1380 * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
1350 * SD_BALANCE_EXEC. 1381 * SD_BALANCE_EXEC.
@@ -1398,11 +1429,35 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag
1398 want_sd = 0; 1429 want_sd = 0;
1399 } 1430 }
1400 1431
1401 if (want_affine && (tmp->flags & SD_WAKE_AFFINE) && 1432 /*
1402 cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) { 1433 * While iterating the domains looking for a spanning
1434 * WAKE_AFFINE domain, adjust the affine target to any idle cpu
1435 * in cache sharing domains along the way.
1436 */
1437 if (want_affine) {
1438 int target = -1;
1403 1439
1404 affine_sd = tmp; 1440 /*
1405 want_affine = 0; 1441 * If both cpu and prev_cpu are part of this domain,
1442 * cpu is a valid SD_WAKE_AFFINE target.
1443 */
1444 if (cpumask_test_cpu(prev_cpu, sched_domain_span(tmp)))
1445 target = cpu;
1446
1447 /*
1448 * If there's an idle sibling in this domain, make that
1449 * the wake_affine target instead of the current cpu.
1450 */
1451 if (tmp->flags & SD_PREFER_SIBLING)
1452 target = select_idle_sibling(p, tmp, target);
1453
1454 if (target >= 0) {
1455 if (tmp->flags & SD_WAKE_AFFINE) {
1456 affine_sd = tmp;
1457 want_affine = 0;
1458 }
1459 cpu = target;
1460 }
1406 } 1461 }
1407 1462
1408 if (!want_sd && !want_affine) 1463 if (!want_sd && !want_affine)
@@ -1679,7 +1734,7 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
1679 struct cfs_rq *cfs_rq = &rq->cfs; 1734 struct cfs_rq *cfs_rq = &rq->cfs;
1680 struct sched_entity *se; 1735 struct sched_entity *se;
1681 1736
1682 if (unlikely(!cfs_rq->nr_running)) 1737 if (!cfs_rq->nr_running)
1683 return NULL; 1738 return NULL;
1684 1739
1685 do { 1740 do {
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index a4d790cddb19..5c5fef378415 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1153,29 +1153,12 @@ static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu)
1153 1153
1154static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask); 1154static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask);
1155 1155
1156static inline int pick_optimal_cpu(int this_cpu,
1157 const struct cpumask *mask)
1158{
1159 int first;
1160
1161 /* "this_cpu" is cheaper to preempt than a remote processor */
1162 if ((this_cpu != -1) && cpumask_test_cpu(this_cpu, mask))
1163 return this_cpu;
1164
1165 first = cpumask_first(mask);
1166 if (first < nr_cpu_ids)
1167 return first;
1168
1169 return -1;
1170}
1171
1172static int find_lowest_rq(struct task_struct *task) 1156static int find_lowest_rq(struct task_struct *task)
1173{ 1157{
1174 struct sched_domain *sd; 1158 struct sched_domain *sd;
1175 struct cpumask *lowest_mask = __get_cpu_var(local_cpu_mask); 1159 struct cpumask *lowest_mask = __get_cpu_var(local_cpu_mask);
1176 int this_cpu = smp_processor_id(); 1160 int this_cpu = smp_processor_id();
1177 int cpu = task_cpu(task); 1161 int cpu = task_cpu(task);
1178 cpumask_var_t domain_mask;
1179 1162
1180 if (task->rt.nr_cpus_allowed == 1) 1163 if (task->rt.nr_cpus_allowed == 1)
1181 return -1; /* No other targets possible */ 1164 return -1; /* No other targets possible */
@@ -1198,28 +1181,26 @@ static int find_lowest_rq(struct task_struct *task)
1198 * Otherwise, we consult the sched_domains span maps to figure 1181 * Otherwise, we consult the sched_domains span maps to figure
1199 * out which cpu is logically closest to our hot cache data. 1182 * out which cpu is logically closest to our hot cache data.
1200 */ 1183 */
1201 if (this_cpu == cpu) 1184 if (!cpumask_test_cpu(this_cpu, lowest_mask))
1202 this_cpu = -1; /* Skip this_cpu opt if the same */ 1185 this_cpu = -1; /* Skip this_cpu opt if not among lowest */
1203
1204 if (alloc_cpumask_var(&domain_mask, GFP_ATOMIC)) {
1205 for_each_domain(cpu, sd) {
1206 if (sd->flags & SD_WAKE_AFFINE) {
1207 int best_cpu;
1208 1186
1209 cpumask_and(domain_mask, 1187 for_each_domain(cpu, sd) {
1210 sched_domain_span(sd), 1188 if (sd->flags & SD_WAKE_AFFINE) {
1211 lowest_mask); 1189 int best_cpu;
1212 1190
1213 best_cpu = pick_optimal_cpu(this_cpu, 1191 /*
1214 domain_mask); 1192 * "this_cpu" is cheaper to preempt than a
1215 1193 * remote processor.
1216 if (best_cpu != -1) { 1194 */
1217 free_cpumask_var(domain_mask); 1195 if (this_cpu != -1 &&
1218 return best_cpu; 1196 cpumask_test_cpu(this_cpu, sched_domain_span(sd)))
1219 } 1197 return this_cpu;
1220 } 1198
1199 best_cpu = cpumask_first_and(lowest_mask,
1200 sched_domain_span(sd));
1201 if (best_cpu < nr_cpu_ids)
1202 return best_cpu;
1221 } 1203 }
1222 free_cpumask_var(domain_mask);
1223 } 1204 }
1224 1205
1225 /* 1206 /*
@@ -1227,7 +1208,13 @@ static int find_lowest_rq(struct task_struct *task)
1227 * just give the caller *something* to work with from the compatible 1208 * just give the caller *something* to work with from the compatible
1228 * locations. 1209 * locations.
1229 */ 1210 */
1230 return pick_optimal_cpu(this_cpu, lowest_mask); 1211 if (this_cpu != -1)
1212 return this_cpu;
1213
1214 cpu = cpumask_any(lowest_mask);
1215 if (cpu < nr_cpu_ids)
1216 return cpu;
1217 return -1;
1231} 1218}
1232 1219
1233/* Will lock the rq it finds */ 1220/* Will lock the rq it finds */
diff --git a/kernel/signal.c b/kernel/signal.c
index fe08008133da..6b982f2cf524 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -28,7 +28,8 @@
28#include <linux/freezer.h> 28#include <linux/freezer.h>
29#include <linux/pid_namespace.h> 29#include <linux/pid_namespace.h>
30#include <linux/nsproxy.h> 30#include <linux/nsproxy.h>
31#include <trace/events/sched.h> 31#define CREATE_TRACE_POINTS
32#include <trace/events/signal.h>
32 33
33#include <asm/param.h> 34#include <asm/param.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
@@ -856,7 +857,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
856 struct sigqueue *q; 857 struct sigqueue *q;
857 int override_rlimit; 858 int override_rlimit;
858 859
859 trace_sched_signal_send(sig, t); 860 trace_signal_generate(sig, info, t);
860 861
861 assert_spin_locked(&t->sighand->siglock); 862 assert_spin_locked(&t->sighand->siglock);
862 863
@@ -918,12 +919,21 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
918 break; 919 break;
919 } 920 }
920 } else if (!is_si_special(info)) { 921 } else if (!is_si_special(info)) {
921 if (sig >= SIGRTMIN && info->si_code != SI_USER) 922 if (sig >= SIGRTMIN && info->si_code != SI_USER) {
922 /* 923 /*
923 * Queue overflow, abort. We may abort if the signal was rt 924 * Queue overflow, abort. We may abort if the
924 * and sent by user using something other than kill(). 925 * signal was rt and sent by user using something
925 */ 926 * other than kill().
927 */
928 trace_signal_overflow_fail(sig, group, info);
926 return -EAGAIN; 929 return -EAGAIN;
930 } else {
931 /*
932 * This is a silent loss of information. We still
933 * send the signal, but the *info bits are lost.
934 */
935 trace_signal_lose_info(sig, group, info);
936 }
927 } 937 }
928 938
929out_set: 939out_set:
@@ -1859,6 +1869,9 @@ relock:
1859 ka = &sighand->action[signr-1]; 1869 ka = &sighand->action[signr-1];
1860 } 1870 }
1861 1871
1872 /* Trace actually delivered signals. */
1873 trace_signal_deliver(signr, info, ka);
1874
1862 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ 1875 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
1863 continue; 1876 continue;
1864 if (ka->sa.sa_handler != SIG_DFL) { 1877 if (ka->sa.sa_handler != SIG_DFL) {
diff --git a/kernel/slow-work.c b/kernel/slow-work.c
index 00889bd3c590..7494bbf5a270 100644
--- a/kernel/slow-work.c
+++ b/kernel/slow-work.c
@@ -49,7 +49,6 @@ static const int slow_work_max_vslow = 99;
49 49
50ctl_table slow_work_sysctls[] = { 50ctl_table slow_work_sysctls[] = {
51 { 51 {
52 .ctl_name = CTL_UNNUMBERED,
53 .procname = "min-threads", 52 .procname = "min-threads",
54 .data = &slow_work_min_threads, 53 .data = &slow_work_min_threads,
55 .maxlen = sizeof(unsigned), 54 .maxlen = sizeof(unsigned),
@@ -59,7 +58,6 @@ ctl_table slow_work_sysctls[] = {
59 .extra2 = &slow_work_max_threads, 58 .extra2 = &slow_work_max_threads,
60 }, 59 },
61 { 60 {
62 .ctl_name = CTL_UNNUMBERED,
63 .procname = "max-threads", 61 .procname = "max-threads",
64 .data = &slow_work_max_threads, 62 .data = &slow_work_max_threads,
65 .maxlen = sizeof(unsigned), 63 .maxlen = sizeof(unsigned),
@@ -69,16 +67,15 @@ ctl_table slow_work_sysctls[] = {
69 .extra2 = (void *) &slow_work_max_max_threads, 67 .extra2 = (void *) &slow_work_max_max_threads,
70 }, 68 },
71 { 69 {
72 .ctl_name = CTL_UNNUMBERED,
73 .procname = "vslow-percentage", 70 .procname = "vslow-percentage",
74 .data = &vslow_work_proportion, 71 .data = &vslow_work_proportion,
75 .maxlen = sizeof(unsigned), 72 .maxlen = sizeof(unsigned),
76 .mode = 0644, 73 .mode = 0644,
77 .proc_handler = &proc_dointvec_minmax, 74 .proc_handler = proc_dointvec_minmax,
78 .extra1 = (void *) &slow_work_min_vslow, 75 .extra1 = (void *) &slow_work_min_vslow,
79 .extra2 = (void *) &slow_work_max_vslow, 76 .extra2 = (void *) &slow_work_max_vslow,
80 }, 77 },
81 { .ctl_name = 0 } 78 {}
82}; 79};
83#endif 80#endif
84 81
diff --git a/kernel/sys.c b/kernel/sys.c
index ce17760d9c51..9968c5fb55b9 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -911,16 +911,15 @@ change_okay:
911 911
912void do_sys_times(struct tms *tms) 912void do_sys_times(struct tms *tms)
913{ 913{
914 struct task_cputime cputime; 914 cputime_t tgutime, tgstime, cutime, cstime;
915 cputime_t cutime, cstime;
916 915
917 thread_group_cputime(current, &cputime);
918 spin_lock_irq(&current->sighand->siglock); 916 spin_lock_irq(&current->sighand->siglock);
917 thread_group_times(current, &tgutime, &tgstime);
919 cutime = current->signal->cutime; 918 cutime = current->signal->cutime;
920 cstime = current->signal->cstime; 919 cstime = current->signal->cstime;
921 spin_unlock_irq(&current->sighand->siglock); 920 spin_unlock_irq(&current->sighand->siglock);
922 tms->tms_utime = cputime_to_clock_t(cputime.utime); 921 tms->tms_utime = cputime_to_clock_t(tgutime);
923 tms->tms_stime = cputime_to_clock_t(cputime.stime); 922 tms->tms_stime = cputime_to_clock_t(tgstime);
924 tms->tms_cutime = cputime_to_clock_t(cutime); 923 tms->tms_cutime = cputime_to_clock_t(cutime);
925 tms->tms_cstime = cputime_to_clock_t(cstime); 924 tms->tms_cstime = cputime_to_clock_t(cstime);
926} 925}
@@ -1338,16 +1337,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1338{ 1337{
1339 struct task_struct *t; 1338 struct task_struct *t;
1340 unsigned long flags; 1339 unsigned long flags;
1341 cputime_t utime, stime; 1340 cputime_t tgutime, tgstime, utime, stime;
1342 struct task_cputime cputime;
1343 unsigned long maxrss = 0; 1341 unsigned long maxrss = 0;
1344 1342
1345 memset((char *) r, 0, sizeof *r); 1343 memset((char *) r, 0, sizeof *r);
1346 utime = stime = cputime_zero; 1344 utime = stime = cputime_zero;
1347 1345
1348 if (who == RUSAGE_THREAD) { 1346 if (who == RUSAGE_THREAD) {
1349 utime = task_utime(current); 1347 task_times(current, &utime, &stime);
1350 stime = task_stime(current);
1351 accumulate_thread_rusage(p, r); 1348 accumulate_thread_rusage(p, r);
1352 maxrss = p->signal->maxrss; 1349 maxrss = p->signal->maxrss;
1353 goto out; 1350 goto out;
@@ -1373,9 +1370,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1373 break; 1370 break;
1374 1371
1375 case RUSAGE_SELF: 1372 case RUSAGE_SELF:
1376 thread_group_cputime(p, &cputime); 1373 thread_group_times(p, &tgutime, &tgstime);
1377 utime = cputime_add(utime, cputime.utime); 1374 utime = cputime_add(utime, tgutime);
1378 stime = cputime_add(stime, cputime.stime); 1375 stime = cputime_add(stime, tgstime);
1379 r->ru_nvcsw += p->signal->nvcsw; 1376 r->ru_nvcsw += p->signal->nvcsw;
1380 r->ru_nivcsw += p->signal->nivcsw; 1377 r->ru_nivcsw += p->signal->nivcsw;
1381 r->ru_minflt += p->signal->min_flt; 1378 r->ru_minflt += p->signal->min_flt;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index f050ba85d420..695384f12a7d 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -141,7 +141,6 @@ cond_syscall(sys_pciconfig_read);
141cond_syscall(sys_pciconfig_write); 141cond_syscall(sys_pciconfig_write);
142cond_syscall(sys_pciconfig_iobase); 142cond_syscall(sys_pciconfig_iobase);
143cond_syscall(sys32_ipc); 143cond_syscall(sys32_ipc);
144cond_syscall(sys32_sysctl);
145cond_syscall(ppc_rtas); 144cond_syscall(ppc_rtas);
146cond_syscall(sys_spu_run); 145cond_syscall(sys_spu_run);
147cond_syscall(sys_spu_create); 146cond_syscall(sys_spu_create);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4dbf93a52ee9..9327a26765c5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -27,7 +27,6 @@
27#include <linux/security.h> 27#include <linux/security.h>
28#include <linux/ctype.h> 28#include <linux/ctype.h>
29#include <linux/kmemcheck.h> 29#include <linux/kmemcheck.h>
30#include <linux/smp_lock.h>
31#include <linux/fs.h> 30#include <linux/fs.h>
32#include <linux/init.h> 31#include <linux/init.h>
33#include <linux/kernel.h> 32#include <linux/kernel.h>
@@ -61,7 +60,6 @@
61#include <asm/io.h> 60#include <asm/io.h>
62#endif 61#endif
63 62
64static int deprecated_sysctl_warning(struct __sysctl_args *args);
65 63
66#if defined(CONFIG_SYSCTL) 64#if defined(CONFIG_SYSCTL)
67 65
@@ -210,31 +208,26 @@ extern int lock_stat;
210 208
211static struct ctl_table root_table[] = { 209static struct ctl_table root_table[] = {
212 { 210 {
213 .ctl_name = CTL_KERN,
214 .procname = "kernel", 211 .procname = "kernel",
215 .mode = 0555, 212 .mode = 0555,
216 .child = kern_table, 213 .child = kern_table,
217 }, 214 },
218 { 215 {
219 .ctl_name = CTL_VM,
220 .procname = "vm", 216 .procname = "vm",
221 .mode = 0555, 217 .mode = 0555,
222 .child = vm_table, 218 .child = vm_table,
223 }, 219 },
224 { 220 {
225 .ctl_name = CTL_FS,
226 .procname = "fs", 221 .procname = "fs",
227 .mode = 0555, 222 .mode = 0555,
228 .child = fs_table, 223 .child = fs_table,
229 }, 224 },
230 { 225 {
231 .ctl_name = CTL_DEBUG,
232 .procname = "debug", 226 .procname = "debug",
233 .mode = 0555, 227 .mode = 0555,
234 .child = debug_table, 228 .child = debug_table,
235 }, 229 },
236 { 230 {
237 .ctl_name = CTL_DEV,
238 .procname = "dev", 231 .procname = "dev",
239 .mode = 0555, 232 .mode = 0555,
240 .child = dev_table, 233 .child = dev_table,
@@ -243,7 +236,7 @@ static struct ctl_table root_table[] = {
243 * NOTE: do not add new entries to this table unless you have read 236 * NOTE: do not add new entries to this table unless you have read
244 * Documentation/sysctl/ctl_unnumbered.txt 237 * Documentation/sysctl/ctl_unnumbered.txt
245 */ 238 */
246 { .ctl_name = 0 } 239 { }
247}; 240};
248 241
249#ifdef CONFIG_SCHED_DEBUG 242#ifdef CONFIG_SCHED_DEBUG
@@ -255,192 +248,166 @@ static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
255 248
256static struct ctl_table kern_table[] = { 249static struct ctl_table kern_table[] = {
257 { 250 {
258 .ctl_name = CTL_UNNUMBERED,
259 .procname = "sched_child_runs_first", 251 .procname = "sched_child_runs_first",
260 .data = &sysctl_sched_child_runs_first, 252 .data = &sysctl_sched_child_runs_first,
261 .maxlen = sizeof(unsigned int), 253 .maxlen = sizeof(unsigned int),
262 .mode = 0644, 254 .mode = 0644,
263 .proc_handler = &proc_dointvec, 255 .proc_handler = proc_dointvec,
264 }, 256 },
265#ifdef CONFIG_SCHED_DEBUG 257#ifdef CONFIG_SCHED_DEBUG
266 { 258 {
267 .ctl_name = CTL_UNNUMBERED,
268 .procname = "sched_min_granularity_ns", 259 .procname = "sched_min_granularity_ns",
269 .data = &sysctl_sched_min_granularity, 260 .data = &sysctl_sched_min_granularity,
270 .maxlen = sizeof(unsigned int), 261 .maxlen = sizeof(unsigned int),
271 .mode = 0644, 262 .mode = 0644,
272 .proc_handler = &sched_nr_latency_handler, 263 .proc_handler = sched_nr_latency_handler,
273 .strategy = &sysctl_intvec,
274 .extra1 = &min_sched_granularity_ns, 264 .extra1 = &min_sched_granularity_ns,
275 .extra2 = &max_sched_granularity_ns, 265 .extra2 = &max_sched_granularity_ns,
276 }, 266 },
277 { 267 {
278 .ctl_name = CTL_UNNUMBERED,
279 .procname = "sched_latency_ns", 268 .procname = "sched_latency_ns",
280 .data = &sysctl_sched_latency, 269 .data = &sysctl_sched_latency,
281 .maxlen = sizeof(unsigned int), 270 .maxlen = sizeof(unsigned int),
282 .mode = 0644, 271 .mode = 0644,
283 .proc_handler = &sched_nr_latency_handler, 272 .proc_handler = sched_nr_latency_handler,
284 .strategy = &sysctl_intvec,
285 .extra1 = &min_sched_granularity_ns, 273 .extra1 = &min_sched_granularity_ns,
286 .extra2 = &max_sched_granularity_ns, 274 .extra2 = &max_sched_granularity_ns,
287 }, 275 },
288 { 276 {
289 .ctl_name = CTL_UNNUMBERED,
290 .procname = "sched_wakeup_granularity_ns", 277 .procname = "sched_wakeup_granularity_ns",
291 .data = &sysctl_sched_wakeup_granularity, 278 .data = &sysctl_sched_wakeup_granularity,
292 .maxlen = sizeof(unsigned int), 279 .maxlen = sizeof(unsigned int),
293 .mode = 0644, 280 .mode = 0644,
294 .proc_handler = &proc_dointvec_minmax, 281 .proc_handler = proc_dointvec_minmax,
295 .strategy = &sysctl_intvec,
296 .extra1 = &min_wakeup_granularity_ns, 282 .extra1 = &min_wakeup_granularity_ns,
297 .extra2 = &max_wakeup_granularity_ns, 283 .extra2 = &max_wakeup_granularity_ns,
298 }, 284 },
299 { 285 {
300 .ctl_name = CTL_UNNUMBERED,
301 .procname = "sched_shares_ratelimit", 286 .procname = "sched_shares_ratelimit",
302 .data = &sysctl_sched_shares_ratelimit, 287 .data = &sysctl_sched_shares_ratelimit,
303 .maxlen = sizeof(unsigned int), 288 .maxlen = sizeof(unsigned int),
304 .mode = 0644, 289 .mode = 0644,
305 .proc_handler = &proc_dointvec, 290 .proc_handler = proc_dointvec,
306 }, 291 },
307 { 292 {
308 .ctl_name = CTL_UNNUMBERED,
309 .procname = "sched_shares_thresh", 293 .procname = "sched_shares_thresh",
310 .data = &sysctl_sched_shares_thresh, 294 .data = &sysctl_sched_shares_thresh,
311 .maxlen = sizeof(unsigned int), 295 .maxlen = sizeof(unsigned int),
312 .mode = 0644, 296 .mode = 0644,
313 .proc_handler = &proc_dointvec_minmax, 297 .proc_handler = proc_dointvec_minmax,
314 .strategy = &sysctl_intvec,
315 .extra1 = &zero, 298 .extra1 = &zero,
316 }, 299 },
317 { 300 {
318 .ctl_name = CTL_UNNUMBERED,
319 .procname = "sched_features", 301 .procname = "sched_features",
320 .data = &sysctl_sched_features, 302 .data = &sysctl_sched_features,
321 .maxlen = sizeof(unsigned int), 303 .maxlen = sizeof(unsigned int),
322 .mode = 0644, 304 .mode = 0644,
323 .proc_handler = &proc_dointvec, 305 .proc_handler = proc_dointvec,
324 }, 306 },
325 { 307 {
326 .ctl_name = CTL_UNNUMBERED,
327 .procname = "sched_migration_cost", 308 .procname = "sched_migration_cost",
328 .data = &sysctl_sched_migration_cost, 309 .data = &sysctl_sched_migration_cost,
329 .maxlen = sizeof(unsigned int), 310 .maxlen = sizeof(unsigned int),
330 .mode = 0644, 311 .mode = 0644,
331 .proc_handler = &proc_dointvec, 312 .proc_handler = proc_dointvec,
332 }, 313 },
333 { 314 {
334 .ctl_name = CTL_UNNUMBERED,
335 .procname = "sched_nr_migrate", 315 .procname = "sched_nr_migrate",
336 .data = &sysctl_sched_nr_migrate, 316 .data = &sysctl_sched_nr_migrate,
337 .maxlen = sizeof(unsigned int), 317 .maxlen = sizeof(unsigned int),
338 .mode = 0644, 318 .mode = 0644,
339 .proc_handler = &proc_dointvec, 319 .proc_handler = proc_dointvec,
340 }, 320 },
341 { 321 {
342 .ctl_name = CTL_UNNUMBERED,
343 .procname = "sched_time_avg", 322 .procname = "sched_time_avg",
344 .data = &sysctl_sched_time_avg, 323 .data = &sysctl_sched_time_avg,
345 .maxlen = sizeof(unsigned int), 324 .maxlen = sizeof(unsigned int),
346 .mode = 0644, 325 .mode = 0644,
347 .proc_handler = &proc_dointvec, 326 .proc_handler = proc_dointvec,
348 }, 327 },
349 { 328 {
350 .ctl_name = CTL_UNNUMBERED,
351 .procname = "timer_migration", 329 .procname = "timer_migration",
352 .data = &sysctl_timer_migration, 330 .data = &sysctl_timer_migration,
353 .maxlen = sizeof(unsigned int), 331 .maxlen = sizeof(unsigned int),
354 .mode = 0644, 332 .mode = 0644,
355 .proc_handler = &proc_dointvec_minmax, 333 .proc_handler = proc_dointvec_minmax,
356 .strategy = &sysctl_intvec,
357 .extra1 = &zero, 334 .extra1 = &zero,
358 .extra2 = &one, 335 .extra2 = &one,
359 }, 336 },
360#endif 337#endif
361 { 338 {
362 .ctl_name = CTL_UNNUMBERED,
363 .procname = "sched_rt_period_us", 339 .procname = "sched_rt_period_us",
364 .data = &sysctl_sched_rt_period, 340 .data = &sysctl_sched_rt_period,
365 .maxlen = sizeof(unsigned int), 341 .maxlen = sizeof(unsigned int),
366 .mode = 0644, 342 .mode = 0644,
367 .proc_handler = &sched_rt_handler, 343 .proc_handler = sched_rt_handler,
368 }, 344 },
369 { 345 {
370 .ctl_name = CTL_UNNUMBERED,
371 .procname = "sched_rt_runtime_us", 346 .procname = "sched_rt_runtime_us",
372 .data = &sysctl_sched_rt_runtime, 347 .data = &sysctl_sched_rt_runtime,
373 .maxlen = sizeof(int), 348 .maxlen = sizeof(int),
374 .mode = 0644, 349 .mode = 0644,
375 .proc_handler = &sched_rt_handler, 350 .proc_handler = sched_rt_handler,
376 }, 351 },
377 { 352 {
378 .ctl_name = CTL_UNNUMBERED,
379 .procname = "sched_compat_yield", 353 .procname = "sched_compat_yield",
380 .data = &sysctl_sched_compat_yield, 354 .data = &sysctl_sched_compat_yield,
381 .maxlen = sizeof(unsigned int), 355 .maxlen = sizeof(unsigned int),
382 .mode = 0644, 356 .mode = 0644,
383 .proc_handler = &proc_dointvec, 357 .proc_handler = proc_dointvec,
384 }, 358 },
385#ifdef CONFIG_PROVE_LOCKING 359#ifdef CONFIG_PROVE_LOCKING
386 { 360 {
387 .ctl_name = CTL_UNNUMBERED,
388 .procname = "prove_locking", 361 .procname = "prove_locking",
389 .data = &prove_locking, 362 .data = &prove_locking,
390 .maxlen = sizeof(int), 363 .maxlen = sizeof(int),
391 .mode = 0644, 364 .mode = 0644,
392 .proc_handler = &proc_dointvec, 365 .proc_handler = proc_dointvec,
393 }, 366 },
394#endif 367#endif
395#ifdef CONFIG_LOCK_STAT 368#ifdef CONFIG_LOCK_STAT
396 { 369 {
397 .ctl_name = CTL_UNNUMBERED,
398 .procname = "lock_stat", 370 .procname = "lock_stat",
399 .data = &lock_stat, 371 .data = &lock_stat,
400 .maxlen = sizeof(int), 372 .maxlen = sizeof(int),
401 .mode = 0644, 373 .mode = 0644,
402 .proc_handler = &proc_dointvec, 374 .proc_handler = proc_dointvec,
403 }, 375 },
404#endif 376#endif
405 { 377 {
406 .ctl_name = KERN_PANIC,
407 .procname = "panic", 378 .procname = "panic",
408 .data = &panic_timeout, 379 .data = &panic_timeout,
409 .maxlen = sizeof(int), 380 .maxlen = sizeof(int),
410 .mode = 0644, 381 .mode = 0644,
411 .proc_handler = &proc_dointvec, 382 .proc_handler = proc_dointvec,
412 }, 383 },
413 { 384 {
414 .ctl_name = KERN_CORE_USES_PID,
415 .procname = "core_uses_pid", 385 .procname = "core_uses_pid",
416 .data = &core_uses_pid, 386 .data = &core_uses_pid,
417 .maxlen = sizeof(int), 387 .maxlen = sizeof(int),
418 .mode = 0644, 388 .mode = 0644,
419 .proc_handler = &proc_dointvec, 389 .proc_handler = proc_dointvec,
420 }, 390 },
421 { 391 {
422 .ctl_name = KERN_CORE_PATTERN,
423 .procname = "core_pattern", 392 .procname = "core_pattern",
424 .data = core_pattern, 393 .data = core_pattern,
425 .maxlen = CORENAME_MAX_SIZE, 394 .maxlen = CORENAME_MAX_SIZE,
426 .mode = 0644, 395 .mode = 0644,
427 .proc_handler = &proc_dostring, 396 .proc_handler = proc_dostring,
428 .strategy = &sysctl_string,
429 }, 397 },
430 { 398 {
431 .ctl_name = CTL_UNNUMBERED,
432 .procname = "core_pipe_limit", 399 .procname = "core_pipe_limit",
433 .data = &core_pipe_limit, 400 .data = &core_pipe_limit,
434 .maxlen = sizeof(unsigned int), 401 .maxlen = sizeof(unsigned int),
435 .mode = 0644, 402 .mode = 0644,
436 .proc_handler = &proc_dointvec, 403 .proc_handler = proc_dointvec,
437 }, 404 },
438#ifdef CONFIG_PROC_SYSCTL 405#ifdef CONFIG_PROC_SYSCTL
439 { 406 {
440 .procname = "tainted", 407 .procname = "tainted",
441 .maxlen = sizeof(long), 408 .maxlen = sizeof(long),
442 .mode = 0644, 409 .mode = 0644,
443 .proc_handler = &proc_taint, 410 .proc_handler = proc_taint,
444 }, 411 },
445#endif 412#endif
446#ifdef CONFIG_LATENCYTOP 413#ifdef CONFIG_LATENCYTOP
@@ -449,181 +416,160 @@ static struct ctl_table kern_table[] = {
449 .data = &latencytop_enabled, 416 .data = &latencytop_enabled,
450 .maxlen = sizeof(int), 417 .maxlen = sizeof(int),
451 .mode = 0644, 418 .mode = 0644,
452 .proc_handler = &proc_dointvec, 419 .proc_handler = proc_dointvec,
453 }, 420 },
454#endif 421#endif
455#ifdef CONFIG_BLK_DEV_INITRD 422#ifdef CONFIG_BLK_DEV_INITRD
456 { 423 {
457 .ctl_name = KERN_REALROOTDEV,
458 .procname = "real-root-dev", 424 .procname = "real-root-dev",
459 .data = &real_root_dev, 425 .data = &real_root_dev,
460 .maxlen = sizeof(int), 426 .maxlen = sizeof(int),
461 .mode = 0644, 427 .mode = 0644,
462 .proc_handler = &proc_dointvec, 428 .proc_handler = proc_dointvec,
463 }, 429 },
464#endif 430#endif
465 { 431 {
466 .ctl_name = CTL_UNNUMBERED,
467 .procname = "print-fatal-signals", 432 .procname = "print-fatal-signals",
468 .data = &print_fatal_signals, 433 .data = &print_fatal_signals,
469 .maxlen = sizeof(int), 434 .maxlen = sizeof(int),
470 .mode = 0644, 435 .mode = 0644,
471 .proc_handler = &proc_dointvec, 436 .proc_handler = proc_dointvec,
472 }, 437 },
473#ifdef CONFIG_SPARC 438#ifdef CONFIG_SPARC
474 { 439 {
475 .ctl_name = KERN_SPARC_REBOOT,
476 .procname = "reboot-cmd", 440 .procname = "reboot-cmd",
477 .data = reboot_command, 441 .data = reboot_command,
478 .maxlen = 256, 442 .maxlen = 256,
479 .mode = 0644, 443 .mode = 0644,
480 .proc_handler = &proc_dostring, 444 .proc_handler = proc_dostring,
481 .strategy = &sysctl_string,
482 }, 445 },
483 { 446 {
484 .ctl_name = KERN_SPARC_STOP_A,
485 .procname = "stop-a", 447 .procname = "stop-a",
486 .data = &stop_a_enabled, 448 .data = &stop_a_enabled,
487 .maxlen = sizeof (int), 449 .maxlen = sizeof (int),
488 .mode = 0644, 450 .mode = 0644,
489 .proc_handler = &proc_dointvec, 451 .proc_handler = proc_dointvec,
490 }, 452 },
491 { 453 {
492 .ctl_name = KERN_SPARC_SCONS_PWROFF,
493 .procname = "scons-poweroff", 454 .procname = "scons-poweroff",
494 .data = &scons_pwroff, 455 .data = &scons_pwroff,
495 .maxlen = sizeof (int), 456 .maxlen = sizeof (int),
496 .mode = 0644, 457 .mode = 0644,
497 .proc_handler = &proc_dointvec, 458 .proc_handler = proc_dointvec,
498 }, 459 },
499#endif 460#endif
500#ifdef CONFIG_SPARC64 461#ifdef CONFIG_SPARC64
501 { 462 {
502 .ctl_name = CTL_UNNUMBERED,
503 .procname = "tsb-ratio", 463 .procname = "tsb-ratio",
504 .data = &sysctl_tsb_ratio, 464 .data = &sysctl_tsb_ratio,
505 .maxlen = sizeof (int), 465 .maxlen = sizeof (int),
506 .mode = 0644, 466 .mode = 0644,
507 .proc_handler = &proc_dointvec, 467 .proc_handler = proc_dointvec,
508 }, 468 },
509#endif 469#endif
510#ifdef __hppa__ 470#ifdef __hppa__
511 { 471 {
512 .ctl_name = KERN_HPPA_PWRSW,
513 .procname = "soft-power", 472 .procname = "soft-power",
514 .data = &pwrsw_enabled, 473 .data = &pwrsw_enabled,
515 .maxlen = sizeof (int), 474 .maxlen = sizeof (int),
516 .mode = 0644, 475 .mode = 0644,
517 .proc_handler = &proc_dointvec, 476 .proc_handler = proc_dointvec,
518 }, 477 },
519 { 478 {
520 .ctl_name = KERN_HPPA_UNALIGNED,
521 .procname = "unaligned-trap", 479 .procname = "unaligned-trap",
522 .data = &unaligned_enabled, 480 .data = &unaligned_enabled,
523 .maxlen = sizeof (int), 481 .maxlen = sizeof (int),
524 .mode = 0644, 482 .mode = 0644,
525 .proc_handler = &proc_dointvec, 483 .proc_handler = proc_dointvec,
526 }, 484 },
527#endif 485#endif
528 { 486 {
529 .ctl_name = KERN_CTLALTDEL,
530 .procname = "ctrl-alt-del", 487 .procname = "ctrl-alt-del",
531 .data = &C_A_D, 488 .data = &C_A_D,
532 .maxlen = sizeof(int), 489 .maxlen = sizeof(int),
533 .mode = 0644, 490 .mode = 0644,
534 .proc_handler = &proc_dointvec, 491 .proc_handler = proc_dointvec,
535 }, 492 },
536#ifdef CONFIG_FUNCTION_TRACER 493#ifdef CONFIG_FUNCTION_TRACER
537 { 494 {
538 .ctl_name = CTL_UNNUMBERED,
539 .procname = "ftrace_enabled", 495 .procname = "ftrace_enabled",
540 .data = &ftrace_enabled, 496 .data = &ftrace_enabled,
541 .maxlen = sizeof(int), 497 .maxlen = sizeof(int),
542 .mode = 0644, 498 .mode = 0644,
543 .proc_handler = &ftrace_enable_sysctl, 499 .proc_handler = ftrace_enable_sysctl,
544 }, 500 },
545#endif 501#endif
546#ifdef CONFIG_STACK_TRACER 502#ifdef CONFIG_STACK_TRACER
547 { 503 {
548 .ctl_name = CTL_UNNUMBERED,
549 .procname = "stack_tracer_enabled", 504 .procname = "stack_tracer_enabled",
550 .data = &stack_tracer_enabled, 505 .data = &stack_tracer_enabled,
551 .maxlen = sizeof(int), 506 .maxlen = sizeof(int),
552 .mode = 0644, 507 .mode = 0644,
553 .proc_handler = &stack_trace_sysctl, 508 .proc_handler = stack_trace_sysctl,
554 }, 509 },
555#endif 510#endif
556#ifdef CONFIG_TRACING 511#ifdef CONFIG_TRACING
557 { 512 {
558 .ctl_name = CTL_UNNUMBERED,
559 .procname = "ftrace_dump_on_oops", 513 .procname = "ftrace_dump_on_oops",
560 .data = &ftrace_dump_on_oops, 514 .data = &ftrace_dump_on_oops,
561 .maxlen = sizeof(int), 515 .maxlen = sizeof(int),
562 .mode = 0644, 516 .mode = 0644,
563 .proc_handler = &proc_dointvec, 517 .proc_handler = proc_dointvec,
564 }, 518 },
565#endif 519#endif
566#ifdef CONFIG_MODULES 520#ifdef CONFIG_MODULES
567 { 521 {
568 .ctl_name = KERN_MODPROBE,
569 .procname = "modprobe", 522 .procname = "modprobe",
570 .data = &modprobe_path, 523 .data = &modprobe_path,
571 .maxlen = KMOD_PATH_LEN, 524 .maxlen = KMOD_PATH_LEN,
572 .mode = 0644, 525 .mode = 0644,
573 .proc_handler = &proc_dostring, 526 .proc_handler = proc_dostring,
574 .strategy = &sysctl_string,
575 }, 527 },
576 { 528 {
577 .ctl_name = CTL_UNNUMBERED,
578 .procname = "modules_disabled", 529 .procname = "modules_disabled",
579 .data = &modules_disabled, 530 .data = &modules_disabled,
580 .maxlen = sizeof(int), 531 .maxlen = sizeof(int),
581 .mode = 0644, 532 .mode = 0644,
582 /* only handle a transition from default "0" to "1" */ 533 /* only handle a transition from default "0" to "1" */
583 .proc_handler = &proc_dointvec_minmax, 534 .proc_handler = proc_dointvec_minmax,
584 .extra1 = &one, 535 .extra1 = &one,
585 .extra2 = &one, 536 .extra2 = &one,
586 }, 537 },
587#endif 538#endif
588#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) 539#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
589 { 540 {
590 .ctl_name = KERN_HOTPLUG,
591 .procname = "hotplug", 541 .procname = "hotplug",
592 .data = &uevent_helper, 542 .data = &uevent_helper,
593 .maxlen = UEVENT_HELPER_PATH_LEN, 543 .maxlen = UEVENT_HELPER_PATH_LEN,
594 .mode = 0644, 544 .mode = 0644,
595 .proc_handler = &proc_dostring, 545 .proc_handler = proc_dostring,
596 .strategy = &sysctl_string,
597 }, 546 },
598#endif 547#endif
599#ifdef CONFIG_CHR_DEV_SG 548#ifdef CONFIG_CHR_DEV_SG
600 { 549 {
601 .ctl_name = KERN_SG_BIG_BUFF,
602 .procname = "sg-big-buff", 550 .procname = "sg-big-buff",
603 .data = &sg_big_buff, 551 .data = &sg_big_buff,
604 .maxlen = sizeof (int), 552 .maxlen = sizeof (int),
605 .mode = 0444, 553 .mode = 0444,
606 .proc_handler = &proc_dointvec, 554 .proc_handler = proc_dointvec,
607 }, 555 },
608#endif 556#endif
609#ifdef CONFIG_BSD_PROCESS_ACCT 557#ifdef CONFIG_BSD_PROCESS_ACCT
610 { 558 {
611 .ctl_name = KERN_ACCT,
612 .procname = "acct", 559 .procname = "acct",
613 .data = &acct_parm, 560 .data = &acct_parm,
614 .maxlen = 3*sizeof(int), 561 .maxlen = 3*sizeof(int),
615 .mode = 0644, 562 .mode = 0644,
616 .proc_handler = &proc_dointvec, 563 .proc_handler = proc_dointvec,
617 }, 564 },
618#endif 565#endif
619#ifdef CONFIG_MAGIC_SYSRQ 566#ifdef CONFIG_MAGIC_SYSRQ
620 { 567 {
621 .ctl_name = KERN_SYSRQ,
622 .procname = "sysrq", 568 .procname = "sysrq",
623 .data = &__sysrq_enabled, 569 .data = &__sysrq_enabled,
624 .maxlen = sizeof (int), 570 .maxlen = sizeof (int),
625 .mode = 0644, 571 .mode = 0644,
626 .proc_handler = &proc_dointvec, 572 .proc_handler = proc_dointvec,
627 }, 573 },
628#endif 574#endif
629#ifdef CONFIG_PROC_SYSCTL 575#ifdef CONFIG_PROC_SYSCTL
@@ -632,215 +578,188 @@ static struct ctl_table kern_table[] = {
632 .data = NULL, 578 .data = NULL,
633 .maxlen = sizeof (int), 579 .maxlen = sizeof (int),
634 .mode = 0600, 580 .mode = 0600,
635 .proc_handler = &proc_do_cad_pid, 581 .proc_handler = proc_do_cad_pid,
636 }, 582 },
637#endif 583#endif
638 { 584 {
639 .ctl_name = KERN_MAX_THREADS,
640 .procname = "threads-max", 585 .procname = "threads-max",
641 .data = &max_threads, 586 .data = &max_threads,
642 .maxlen = sizeof(int), 587 .maxlen = sizeof(int),
643 .mode = 0644, 588 .mode = 0644,
644 .proc_handler = &proc_dointvec, 589 .proc_handler = proc_dointvec,
645 }, 590 },
646 { 591 {
647 .ctl_name = KERN_RANDOM,
648 .procname = "random", 592 .procname = "random",
649 .mode = 0555, 593 .mode = 0555,
650 .child = random_table, 594 .child = random_table,
651 }, 595 },
652 { 596 {
653 .ctl_name = KERN_OVERFLOWUID,
654 .procname = "overflowuid", 597 .procname = "overflowuid",
655 .data = &overflowuid, 598 .data = &overflowuid,
656 .maxlen = sizeof(int), 599 .maxlen = sizeof(int),
657 .mode = 0644, 600 .mode = 0644,
658 .proc_handler = &proc_dointvec_minmax, 601 .proc_handler = proc_dointvec_minmax,
659 .strategy = &sysctl_intvec,
660 .extra1 = &minolduid, 602 .extra1 = &minolduid,
661 .extra2 = &maxolduid, 603 .extra2 = &maxolduid,
662 }, 604 },
663 { 605 {
664 .ctl_name = KERN_OVERFLOWGID,
665 .procname = "overflowgid", 606 .procname = "overflowgid",
666 .data = &overflowgid, 607 .data = &overflowgid,
667 .maxlen = sizeof(int), 608 .maxlen = sizeof(int),
668 .mode = 0644, 609 .mode = 0644,
669 .proc_handler = &proc_dointvec_minmax, 610 .proc_handler = proc_dointvec_minmax,
670 .strategy = &sysctl_intvec,
671 .extra1 = &minolduid, 611 .extra1 = &minolduid,
672 .extra2 = &maxolduid, 612 .extra2 = &maxolduid,
673 }, 613 },
674#ifdef CONFIG_S390 614#ifdef CONFIG_S390
675#ifdef CONFIG_MATHEMU 615#ifdef CONFIG_MATHEMU
676 { 616 {
677 .ctl_name = KERN_IEEE_EMULATION_WARNINGS,
678 .procname = "ieee_emulation_warnings", 617 .procname = "ieee_emulation_warnings",
679 .data = &sysctl_ieee_emulation_warnings, 618 .data = &sysctl_ieee_emulation_warnings,
680 .maxlen = sizeof(int), 619 .maxlen = sizeof(int),
681 .mode = 0644, 620 .mode = 0644,
682 .proc_handler = &proc_dointvec, 621 .proc_handler = proc_dointvec,
683 }, 622 },
684#endif 623#endif
685 { 624 {
686 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
687 .procname = "userprocess_debug", 625 .procname = "userprocess_debug",
688 .data = &sysctl_userprocess_debug, 626 .data = &sysctl_userprocess_debug,
689 .maxlen = sizeof(int), 627 .maxlen = sizeof(int),
690 .mode = 0644, 628 .mode = 0644,
691 .proc_handler = &proc_dointvec, 629 .proc_handler = proc_dointvec,
692 }, 630 },
693#endif 631#endif
694 { 632 {
695 .ctl_name = KERN_PIDMAX,
696 .procname = "pid_max", 633 .procname = "pid_max",
697 .data = &pid_max, 634 .data = &pid_max,
698 .maxlen = sizeof (int), 635 .maxlen = sizeof (int),
699 .mode = 0644, 636 .mode = 0644,
700 .proc_handler = &proc_dointvec_minmax, 637 .proc_handler = proc_dointvec_minmax,
701 .strategy = sysctl_intvec,
702 .extra1 = &pid_max_min, 638 .extra1 = &pid_max_min,
703 .extra2 = &pid_max_max, 639 .extra2 = &pid_max_max,
704 }, 640 },
705 { 641 {
706 .ctl_name = KERN_PANIC_ON_OOPS,
707 .procname = "panic_on_oops", 642 .procname = "panic_on_oops",
708 .data = &panic_on_oops, 643 .data = &panic_on_oops,
709 .maxlen = sizeof(int), 644 .maxlen = sizeof(int),
710 .mode = 0644, 645 .mode = 0644,
711 .proc_handler = &proc_dointvec, 646 .proc_handler = proc_dointvec,
712 }, 647 },
713#if defined CONFIG_PRINTK 648#if defined CONFIG_PRINTK
714 { 649 {
715 .ctl_name = KERN_PRINTK,
716 .procname = "printk", 650 .procname = "printk",
717 .data = &console_loglevel, 651 .data = &console_loglevel,
718 .maxlen = 4*sizeof(int), 652 .maxlen = 4*sizeof(int),
719 .mode = 0644, 653 .mode = 0644,
720 .proc_handler = &proc_dointvec, 654 .proc_handler = proc_dointvec,
721 }, 655 },
722 { 656 {
723 .ctl_name = KERN_PRINTK_RATELIMIT,
724 .procname = "printk_ratelimit", 657 .procname = "printk_ratelimit",
725 .data = &printk_ratelimit_state.interval, 658 .data = &printk_ratelimit_state.interval,
726 .maxlen = sizeof(int), 659 .maxlen = sizeof(int),
727 .mode = 0644, 660 .mode = 0644,
728 .proc_handler = &proc_dointvec_jiffies, 661 .proc_handler = proc_dointvec_jiffies,
729 .strategy = &sysctl_jiffies,
730 }, 662 },
731 { 663 {
732 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
733 .procname = "printk_ratelimit_burst", 664 .procname = "printk_ratelimit_burst",
734 .data = &printk_ratelimit_state.burst, 665 .data = &printk_ratelimit_state.burst,
735 .maxlen = sizeof(int), 666 .maxlen = sizeof(int),
736 .mode = 0644, 667 .mode = 0644,
737 .proc_handler = &proc_dointvec, 668 .proc_handler = proc_dointvec,
738 }, 669 },
739 { 670 {
740 .ctl_name = CTL_UNNUMBERED,
741 .procname = "printk_delay", 671 .procname = "printk_delay",
742 .data = &printk_delay_msec, 672 .data = &printk_delay_msec,
743 .maxlen = sizeof(int), 673 .maxlen = sizeof(int),
744 .mode = 0644, 674 .mode = 0644,
745 .proc_handler = &proc_dointvec_minmax, 675 .proc_handler = proc_dointvec_minmax,
746 .strategy = &sysctl_intvec,
747 .extra1 = &zero, 676 .extra1 = &zero,
748 .extra2 = &ten_thousand, 677 .extra2 = &ten_thousand,
749 }, 678 },
750#endif 679#endif
751 { 680 {
752 .ctl_name = KERN_NGROUPS_MAX,
753 .procname = "ngroups_max", 681 .procname = "ngroups_max",
754 .data = &ngroups_max, 682 .data = &ngroups_max,
755 .maxlen = sizeof (int), 683 .maxlen = sizeof (int),
756 .mode = 0444, 684 .mode = 0444,
757 .proc_handler = &proc_dointvec, 685 .proc_handler = proc_dointvec,
758 }, 686 },
759#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) 687#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
760 { 688 {
761 .ctl_name = KERN_UNKNOWN_NMI_PANIC,
762 .procname = "unknown_nmi_panic", 689 .procname = "unknown_nmi_panic",
763 .data = &unknown_nmi_panic, 690 .data = &unknown_nmi_panic,
764 .maxlen = sizeof (int), 691 .maxlen = sizeof (int),
765 .mode = 0644, 692 .mode = 0644,
766 .proc_handler = &proc_dointvec, 693 .proc_handler = proc_dointvec,
767 }, 694 },
768 { 695 {
769 .procname = "nmi_watchdog", 696 .procname = "nmi_watchdog",
770 .data = &nmi_watchdog_enabled, 697 .data = &nmi_watchdog_enabled,
771 .maxlen = sizeof (int), 698 .maxlen = sizeof (int),
772 .mode = 0644, 699 .mode = 0644,
773 .proc_handler = &proc_nmi_enabled, 700 .proc_handler = proc_nmi_enabled,
774 }, 701 },
775#endif 702#endif
776#if defined(CONFIG_X86) 703#if defined(CONFIG_X86)
777 { 704 {
778 .ctl_name = KERN_PANIC_ON_NMI,
779 .procname = "panic_on_unrecovered_nmi", 705 .procname = "panic_on_unrecovered_nmi",
780 .data = &panic_on_unrecovered_nmi, 706 .data = &panic_on_unrecovered_nmi,
781 .maxlen = sizeof(int), 707 .maxlen = sizeof(int),
782 .mode = 0644, 708 .mode = 0644,
783 .proc_handler = &proc_dointvec, 709 .proc_handler = proc_dointvec,
784 }, 710 },
785 { 711 {
786 .ctl_name = CTL_UNNUMBERED,
787 .procname = "panic_on_io_nmi", 712 .procname = "panic_on_io_nmi",
788 .data = &panic_on_io_nmi, 713 .data = &panic_on_io_nmi,
789 .maxlen = sizeof(int), 714 .maxlen = sizeof(int),
790 .mode = 0644, 715 .mode = 0644,
791 .proc_handler = &proc_dointvec, 716 .proc_handler = proc_dointvec,
792 }, 717 },
793 { 718 {
794 .ctl_name = KERN_BOOTLOADER_TYPE,
795 .procname = "bootloader_type", 719 .procname = "bootloader_type",
796 .data = &bootloader_type, 720 .data = &bootloader_type,
797 .maxlen = sizeof (int), 721 .maxlen = sizeof (int),
798 .mode = 0444, 722 .mode = 0444,
799 .proc_handler = &proc_dointvec, 723 .proc_handler = proc_dointvec,
800 }, 724 },
801 { 725 {
802 .ctl_name = CTL_UNNUMBERED,
803 .procname = "bootloader_version", 726 .procname = "bootloader_version",
804 .data = &bootloader_version, 727 .data = &bootloader_version,
805 .maxlen = sizeof (int), 728 .maxlen = sizeof (int),
806 .mode = 0444, 729 .mode = 0444,
807 .proc_handler = &proc_dointvec, 730 .proc_handler = proc_dointvec,
808 }, 731 },
809 { 732 {
810 .ctl_name = CTL_UNNUMBERED,
811 .procname = "kstack_depth_to_print", 733 .procname = "kstack_depth_to_print",
812 .data = &kstack_depth_to_print, 734 .data = &kstack_depth_to_print,
813 .maxlen = sizeof(int), 735 .maxlen = sizeof(int),
814 .mode = 0644, 736 .mode = 0644,
815 .proc_handler = &proc_dointvec, 737 .proc_handler = proc_dointvec,
816 }, 738 },
817 { 739 {
818 .ctl_name = CTL_UNNUMBERED,
819 .procname = "io_delay_type", 740 .procname = "io_delay_type",
820 .data = &io_delay_type, 741 .data = &io_delay_type,
821 .maxlen = sizeof(int), 742 .maxlen = sizeof(int),
822 .mode = 0644, 743 .mode = 0644,
823 .proc_handler = &proc_dointvec, 744 .proc_handler = proc_dointvec,
824 }, 745 },
825#endif 746#endif
826#if defined(CONFIG_MMU) 747#if defined(CONFIG_MMU)
827 { 748 {
828 .ctl_name = KERN_RANDOMIZE,
829 .procname = "randomize_va_space", 749 .procname = "randomize_va_space",
830 .data = &randomize_va_space, 750 .data = &randomize_va_space,
831 .maxlen = sizeof(int), 751 .maxlen = sizeof(int),
832 .mode = 0644, 752 .mode = 0644,
833 .proc_handler = &proc_dointvec, 753 .proc_handler = proc_dointvec,
834 }, 754 },
835#endif 755#endif
836#if defined(CONFIG_S390) && defined(CONFIG_SMP) 756#if defined(CONFIG_S390) && defined(CONFIG_SMP)
837 { 757 {
838 .ctl_name = KERN_SPIN_RETRY,
839 .procname = "spin_retry", 758 .procname = "spin_retry",
840 .data = &spin_retry, 759 .data = &spin_retry,
841 .maxlen = sizeof (int), 760 .maxlen = sizeof (int),
842 .mode = 0644, 761 .mode = 0644,
843 .proc_handler = &proc_dointvec, 762 .proc_handler = proc_dointvec,
844 }, 763 },
845#endif 764#endif
846#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) 765#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
@@ -849,123 +768,104 @@ static struct ctl_table kern_table[] = {
849 .data = &acpi_realmode_flags, 768 .data = &acpi_realmode_flags,
850 .maxlen = sizeof (unsigned long), 769 .maxlen = sizeof (unsigned long),
851 .mode = 0644, 770 .mode = 0644,
852 .proc_handler = &proc_doulongvec_minmax, 771 .proc_handler = proc_doulongvec_minmax,
853 }, 772 },
854#endif 773#endif
855#ifdef CONFIG_IA64 774#ifdef CONFIG_IA64
856 { 775 {
857 .ctl_name = KERN_IA64_UNALIGNED,
858 .procname = "ignore-unaligned-usertrap", 776 .procname = "ignore-unaligned-usertrap",
859 .data = &no_unaligned_warning, 777 .data = &no_unaligned_warning,
860 .maxlen = sizeof (int), 778 .maxlen = sizeof (int),
861 .mode = 0644, 779 .mode = 0644,
862 .proc_handler = &proc_dointvec, 780 .proc_handler = proc_dointvec,
863 }, 781 },
864 { 782 {
865 .ctl_name = CTL_UNNUMBERED,
866 .procname = "unaligned-dump-stack", 783 .procname = "unaligned-dump-stack",
867 .data = &unaligned_dump_stack, 784 .data = &unaligned_dump_stack,
868 .maxlen = sizeof (int), 785 .maxlen = sizeof (int),
869 .mode = 0644, 786 .mode = 0644,
870 .proc_handler = &proc_dointvec, 787 .proc_handler = proc_dointvec,
871 }, 788 },
872#endif 789#endif
873#ifdef CONFIG_DETECT_SOFTLOCKUP 790#ifdef CONFIG_DETECT_SOFTLOCKUP
874 { 791 {
875 .ctl_name = CTL_UNNUMBERED,
876 .procname = "softlockup_panic", 792 .procname = "softlockup_panic",
877 .data = &softlockup_panic, 793 .data = &softlockup_panic,
878 .maxlen = sizeof(int), 794 .maxlen = sizeof(int),
879 .mode = 0644, 795 .mode = 0644,
880 .proc_handler = &proc_dointvec_minmax, 796 .proc_handler = proc_dointvec_minmax,
881 .strategy = &sysctl_intvec,
882 .extra1 = &zero, 797 .extra1 = &zero,
883 .extra2 = &one, 798 .extra2 = &one,
884 }, 799 },
885 { 800 {
886 .ctl_name = CTL_UNNUMBERED,
887 .procname = "softlockup_thresh", 801 .procname = "softlockup_thresh",
888 .data = &softlockup_thresh, 802 .data = &softlockup_thresh,
889 .maxlen = sizeof(int), 803 .maxlen = sizeof(int),
890 .mode = 0644, 804 .mode = 0644,
891 .proc_handler = &proc_dosoftlockup_thresh, 805 .proc_handler = proc_dosoftlockup_thresh,
892 .strategy = &sysctl_intvec,
893 .extra1 = &neg_one, 806 .extra1 = &neg_one,
894 .extra2 = &sixty, 807 .extra2 = &sixty,
895 }, 808 },
896#endif 809#endif
897#ifdef CONFIG_DETECT_HUNG_TASK 810#ifdef CONFIG_DETECT_HUNG_TASK
898 { 811 {
899 .ctl_name = CTL_UNNUMBERED,
900 .procname = "hung_task_panic", 812 .procname = "hung_task_panic",
901 .data = &sysctl_hung_task_panic, 813 .data = &sysctl_hung_task_panic,
902 .maxlen = sizeof(int), 814 .maxlen = sizeof(int),
903 .mode = 0644, 815 .mode = 0644,
904 .proc_handler = &proc_dointvec_minmax, 816 .proc_handler = proc_dointvec_minmax,
905 .strategy = &sysctl_intvec,
906 .extra1 = &zero, 817 .extra1 = &zero,
907 .extra2 = &one, 818 .extra2 = &one,
908 }, 819 },
909 { 820 {
910 .ctl_name = CTL_UNNUMBERED,
911 .procname = "hung_task_check_count", 821 .procname = "hung_task_check_count",
912 .data = &sysctl_hung_task_check_count, 822 .data = &sysctl_hung_task_check_count,
913 .maxlen = sizeof(unsigned long), 823 .maxlen = sizeof(unsigned long),
914 .mode = 0644, 824 .mode = 0644,
915 .proc_handler = &proc_doulongvec_minmax, 825 .proc_handler = proc_doulongvec_minmax,
916 .strategy = &sysctl_intvec,
917 }, 826 },
918 { 827 {
919 .ctl_name = CTL_UNNUMBERED,
920 .procname = "hung_task_timeout_secs", 828 .procname = "hung_task_timeout_secs",
921 .data = &sysctl_hung_task_timeout_secs, 829 .data = &sysctl_hung_task_timeout_secs,
922 .maxlen = sizeof(unsigned long), 830 .maxlen = sizeof(unsigned long),
923 .mode = 0644, 831 .mode = 0644,
924 .proc_handler = &proc_dohung_task_timeout_secs, 832 .proc_handler = proc_dohung_task_timeout_secs,
925 .strategy = &sysctl_intvec,
926 }, 833 },
927 { 834 {
928 .ctl_name = CTL_UNNUMBERED,
929 .procname = "hung_task_warnings", 835 .procname = "hung_task_warnings",
930 .data = &sysctl_hung_task_warnings, 836 .data = &sysctl_hung_task_warnings,
931 .maxlen = sizeof(unsigned long), 837 .maxlen = sizeof(unsigned long),
932 .mode = 0644, 838 .mode = 0644,
933 .proc_handler = &proc_doulongvec_minmax, 839 .proc_handler = proc_doulongvec_minmax,
934 .strategy = &sysctl_intvec,
935 }, 840 },
936#endif 841#endif
937#ifdef CONFIG_COMPAT 842#ifdef CONFIG_COMPAT
938 { 843 {
939 .ctl_name = KERN_COMPAT_LOG,
940 .procname = "compat-log", 844 .procname = "compat-log",
941 .data = &compat_log, 845 .data = &compat_log,
942 .maxlen = sizeof (int), 846 .maxlen = sizeof (int),
943 .mode = 0644, 847 .mode = 0644,
944 .proc_handler = &proc_dointvec, 848 .proc_handler = proc_dointvec,
945 }, 849 },
946#endif 850#endif
947#ifdef CONFIG_RT_MUTEXES 851#ifdef CONFIG_RT_MUTEXES
948 { 852 {
949 .ctl_name = KERN_MAX_LOCK_DEPTH,
950 .procname = "max_lock_depth", 853 .procname = "max_lock_depth",
951 .data = &max_lock_depth, 854 .data = &max_lock_depth,
952 .maxlen = sizeof(int), 855 .maxlen = sizeof(int),
953 .mode = 0644, 856 .mode = 0644,
954 .proc_handler = &proc_dointvec, 857 .proc_handler = proc_dointvec,
955 }, 858 },
956#endif 859#endif
957 { 860 {
958 .ctl_name = CTL_UNNUMBERED,
959 .procname = "poweroff_cmd", 861 .procname = "poweroff_cmd",
960 .data = &poweroff_cmd, 862 .data = &poweroff_cmd,
961 .maxlen = POWEROFF_CMD_PATH_LEN, 863 .maxlen = POWEROFF_CMD_PATH_LEN,
962 .mode = 0644, 864 .mode = 0644,
963 .proc_handler = &proc_dostring, 865 .proc_handler = proc_dostring,
964 .strategy = &sysctl_string,
965 }, 866 },
966#ifdef CONFIG_KEYS 867#ifdef CONFIG_KEYS
967 { 868 {
968 .ctl_name = CTL_UNNUMBERED,
969 .procname = "keys", 869 .procname = "keys",
970 .mode = 0555, 870 .mode = 0555,
971 .child = key_sysctls, 871 .child = key_sysctls,
@@ -973,17 +873,15 @@ static struct ctl_table kern_table[] = {
973#endif 873#endif
974#ifdef CONFIG_RCU_TORTURE_TEST 874#ifdef CONFIG_RCU_TORTURE_TEST
975 { 875 {
976 .ctl_name = CTL_UNNUMBERED,
977 .procname = "rcutorture_runnable", 876 .procname = "rcutorture_runnable",
978 .data = &rcutorture_runnable, 877 .data = &rcutorture_runnable,
979 .maxlen = sizeof(int), 878 .maxlen = sizeof(int),
980 .mode = 0644, 879 .mode = 0644,
981 .proc_handler = &proc_dointvec, 880 .proc_handler = proc_dointvec,
982 }, 881 },
983#endif 882#endif
984#ifdef CONFIG_SLOW_WORK 883#ifdef CONFIG_SLOW_WORK
985 { 884 {
986 .ctl_name = CTL_UNNUMBERED,
987 .procname = "slow-work", 885 .procname = "slow-work",
988 .mode = 0555, 886 .mode = 0555,
989 .child = slow_work_sysctls, 887 .child = slow_work_sysctls,
@@ -991,146 +889,127 @@ static struct ctl_table kern_table[] = {
991#endif 889#endif
992#ifdef CONFIG_PERF_EVENTS 890#ifdef CONFIG_PERF_EVENTS
993 { 891 {
994 .ctl_name = CTL_UNNUMBERED,
995 .procname = "perf_event_paranoid", 892 .procname = "perf_event_paranoid",
996 .data = &sysctl_perf_event_paranoid, 893 .data = &sysctl_perf_event_paranoid,
997 .maxlen = sizeof(sysctl_perf_event_paranoid), 894 .maxlen = sizeof(sysctl_perf_event_paranoid),
998 .mode = 0644, 895 .mode = 0644,
999 .proc_handler = &proc_dointvec, 896 .proc_handler = proc_dointvec,
1000 }, 897 },
1001 { 898 {
1002 .ctl_name = CTL_UNNUMBERED,
1003 .procname = "perf_event_mlock_kb", 899 .procname = "perf_event_mlock_kb",
1004 .data = &sysctl_perf_event_mlock, 900 .data = &sysctl_perf_event_mlock,
1005 .maxlen = sizeof(sysctl_perf_event_mlock), 901 .maxlen = sizeof(sysctl_perf_event_mlock),
1006 .mode = 0644, 902 .mode = 0644,
1007 .proc_handler = &proc_dointvec, 903 .proc_handler = proc_dointvec,
1008 }, 904 },
1009 { 905 {
1010 .ctl_name = CTL_UNNUMBERED,
1011 .procname = "perf_event_max_sample_rate", 906 .procname = "perf_event_max_sample_rate",
1012 .data = &sysctl_perf_event_sample_rate, 907 .data = &sysctl_perf_event_sample_rate,
1013 .maxlen = sizeof(sysctl_perf_event_sample_rate), 908 .maxlen = sizeof(sysctl_perf_event_sample_rate),
1014 .mode = 0644, 909 .mode = 0644,
1015 .proc_handler = &proc_dointvec, 910 .proc_handler = proc_dointvec,
1016 }, 911 },
1017#endif 912#endif
1018#ifdef CONFIG_KMEMCHECK 913#ifdef CONFIG_KMEMCHECK
1019 { 914 {
1020 .ctl_name = CTL_UNNUMBERED,
1021 .procname = "kmemcheck", 915 .procname = "kmemcheck",
1022 .data = &kmemcheck_enabled, 916 .data = &kmemcheck_enabled,
1023 .maxlen = sizeof(int), 917 .maxlen = sizeof(int),
1024 .mode = 0644, 918 .mode = 0644,
1025 .proc_handler = &proc_dointvec, 919 .proc_handler = proc_dointvec,
1026 }, 920 },
1027#endif 921#endif
1028#ifdef CONFIG_BLOCK 922#ifdef CONFIG_BLOCK
1029 { 923 {
1030 .ctl_name = CTL_UNNUMBERED,
1031 .procname = "blk_iopoll", 924 .procname = "blk_iopoll",
1032 .data = &blk_iopoll_enabled, 925 .data = &blk_iopoll_enabled,
1033 .maxlen = sizeof(int), 926 .maxlen = sizeof(int),
1034 .mode = 0644, 927 .mode = 0644,
1035 .proc_handler = &proc_dointvec, 928 .proc_handler = proc_dointvec,
1036 }, 929 },
1037#endif 930#endif
1038/* 931/*
1039 * NOTE: do not add new entries to this table unless you have read 932 * NOTE: do not add new entries to this table unless you have read
1040 * Documentation/sysctl/ctl_unnumbered.txt 933 * Documentation/sysctl/ctl_unnumbered.txt
1041 */ 934 */
1042 { .ctl_name = 0 } 935 { }
1043}; 936};
1044 937
1045static struct ctl_table vm_table[] = { 938static struct ctl_table vm_table[] = {
1046 { 939 {
1047 .ctl_name = VM_OVERCOMMIT_MEMORY,
1048 .procname = "overcommit_memory", 940 .procname = "overcommit_memory",
1049 .data = &sysctl_overcommit_memory, 941 .data = &sysctl_overcommit_memory,
1050 .maxlen = sizeof(sysctl_overcommit_memory), 942 .maxlen = sizeof(sysctl_overcommit_memory),
1051 .mode = 0644, 943 .mode = 0644,
1052 .proc_handler = &proc_dointvec, 944 .proc_handler = proc_dointvec,
1053 }, 945 },
1054 { 946 {
1055 .ctl_name = VM_PANIC_ON_OOM,
1056 .procname = "panic_on_oom", 947 .procname = "panic_on_oom",
1057 .data = &sysctl_panic_on_oom, 948 .data = &sysctl_panic_on_oom,
1058 .maxlen = sizeof(sysctl_panic_on_oom), 949 .maxlen = sizeof(sysctl_panic_on_oom),
1059 .mode = 0644, 950 .mode = 0644,
1060 .proc_handler = &proc_dointvec, 951 .proc_handler = proc_dointvec,
1061 }, 952 },
1062 { 953 {
1063 .ctl_name = CTL_UNNUMBERED,
1064 .procname = "oom_kill_allocating_task", 954 .procname = "oom_kill_allocating_task",
1065 .data = &sysctl_oom_kill_allocating_task, 955 .data = &sysctl_oom_kill_allocating_task,
1066 .maxlen = sizeof(sysctl_oom_kill_allocating_task), 956 .maxlen = sizeof(sysctl_oom_kill_allocating_task),
1067 .mode = 0644, 957 .mode = 0644,
1068 .proc_handler = &proc_dointvec, 958 .proc_handler = proc_dointvec,
1069 }, 959 },
1070 { 960 {
1071 .ctl_name = CTL_UNNUMBERED,
1072 .procname = "oom_dump_tasks", 961 .procname = "oom_dump_tasks",
1073 .data = &sysctl_oom_dump_tasks, 962 .data = &sysctl_oom_dump_tasks,
1074 .maxlen = sizeof(sysctl_oom_dump_tasks), 963 .maxlen = sizeof(sysctl_oom_dump_tasks),
1075 .mode = 0644, 964 .mode = 0644,
1076 .proc_handler = &proc_dointvec, 965 .proc_handler = proc_dointvec,
1077 }, 966 },
1078 { 967 {
1079 .ctl_name = VM_OVERCOMMIT_RATIO,
1080 .procname = "overcommit_ratio", 968 .procname = "overcommit_ratio",
1081 .data = &sysctl_overcommit_ratio, 969 .data = &sysctl_overcommit_ratio,
1082 .maxlen = sizeof(sysctl_overcommit_ratio), 970 .maxlen = sizeof(sysctl_overcommit_ratio),
1083 .mode = 0644, 971 .mode = 0644,
1084 .proc_handler = &proc_dointvec, 972 .proc_handler = proc_dointvec,
1085 }, 973 },
1086 { 974 {
1087 .ctl_name = VM_PAGE_CLUSTER,
1088 .procname = "page-cluster", 975 .procname = "page-cluster",
1089 .data = &page_cluster, 976 .data = &page_cluster,
1090 .maxlen = sizeof(int), 977 .maxlen = sizeof(int),
1091 .mode = 0644, 978 .mode = 0644,
1092 .proc_handler = &proc_dointvec, 979 .proc_handler = proc_dointvec,
1093 }, 980 },
1094 { 981 {
1095 .ctl_name = VM_DIRTY_BACKGROUND,
1096 .procname = "dirty_background_ratio", 982 .procname = "dirty_background_ratio",
1097 .data = &dirty_background_ratio, 983 .data = &dirty_background_ratio,
1098 .maxlen = sizeof(dirty_background_ratio), 984 .maxlen = sizeof(dirty_background_ratio),
1099 .mode = 0644, 985 .mode = 0644,
1100 .proc_handler = &dirty_background_ratio_handler, 986 .proc_handler = dirty_background_ratio_handler,
1101 .strategy = &sysctl_intvec,
1102 .extra1 = &zero, 987 .extra1 = &zero,
1103 .extra2 = &one_hundred, 988 .extra2 = &one_hundred,
1104 }, 989 },
1105 { 990 {
1106 .ctl_name = CTL_UNNUMBERED,
1107 .procname = "dirty_background_bytes", 991 .procname = "dirty_background_bytes",
1108 .data = &dirty_background_bytes, 992 .data = &dirty_background_bytes,
1109 .maxlen = sizeof(dirty_background_bytes), 993 .maxlen = sizeof(dirty_background_bytes),
1110 .mode = 0644, 994 .mode = 0644,
1111 .proc_handler = &dirty_background_bytes_handler, 995 .proc_handler = dirty_background_bytes_handler,
1112 .strategy = &sysctl_intvec,
1113 .extra1 = &one_ul, 996 .extra1 = &one_ul,
1114 }, 997 },
1115 { 998 {
1116 .ctl_name = VM_DIRTY_RATIO,
1117 .procname = "dirty_ratio", 999 .procname = "dirty_ratio",
1118 .data = &vm_dirty_ratio, 1000 .data = &vm_dirty_ratio,
1119 .maxlen = sizeof(vm_dirty_ratio), 1001 .maxlen = sizeof(vm_dirty_ratio),
1120 .mode = 0644, 1002 .mode = 0644,
1121 .proc_handler = &dirty_ratio_handler, 1003 .proc_handler = dirty_ratio_handler,
1122 .strategy = &sysctl_intvec,
1123 .extra1 = &zero, 1004 .extra1 = &zero,
1124 .extra2 = &one_hundred, 1005 .extra2 = &one_hundred,
1125 }, 1006 },
1126 { 1007 {
1127 .ctl_name = CTL_UNNUMBERED,
1128 .procname = "dirty_bytes", 1008 .procname = "dirty_bytes",
1129 .data = &vm_dirty_bytes, 1009 .data = &vm_dirty_bytes,
1130 .maxlen = sizeof(vm_dirty_bytes), 1010 .maxlen = sizeof(vm_dirty_bytes),
1131 .mode = 0644, 1011 .mode = 0644,
1132 .proc_handler = &dirty_bytes_handler, 1012 .proc_handler = dirty_bytes_handler,
1133 .strategy = &sysctl_intvec,
1134 .extra1 = &dirty_bytes_min, 1013 .extra1 = &dirty_bytes_min,
1135 }, 1014 },
1136 { 1015 {
@@ -1138,31 +1017,28 @@ static struct ctl_table vm_table[] = {
1138 .data = &dirty_writeback_interval, 1017 .data = &dirty_writeback_interval,
1139 .maxlen = sizeof(dirty_writeback_interval), 1018 .maxlen = sizeof(dirty_writeback_interval),
1140 .mode = 0644, 1019 .mode = 0644,
1141 .proc_handler = &dirty_writeback_centisecs_handler, 1020 .proc_handler = dirty_writeback_centisecs_handler,
1142 }, 1021 },
1143 { 1022 {
1144 .procname = "dirty_expire_centisecs", 1023 .procname = "dirty_expire_centisecs",
1145 .data = &dirty_expire_interval, 1024 .data = &dirty_expire_interval,
1146 .maxlen = sizeof(dirty_expire_interval), 1025 .maxlen = sizeof(dirty_expire_interval),
1147 .mode = 0644, 1026 .mode = 0644,
1148 .proc_handler = &proc_dointvec, 1027 .proc_handler = proc_dointvec,
1149 }, 1028 },
1150 { 1029 {
1151 .ctl_name = VM_NR_PDFLUSH_THREADS,
1152 .procname = "nr_pdflush_threads", 1030 .procname = "nr_pdflush_threads",
1153 .data = &nr_pdflush_threads, 1031 .data = &nr_pdflush_threads,
1154 .maxlen = sizeof nr_pdflush_threads, 1032 .maxlen = sizeof nr_pdflush_threads,
1155 .mode = 0444 /* read-only*/, 1033 .mode = 0444 /* read-only*/,
1156 .proc_handler = &proc_dointvec, 1034 .proc_handler = proc_dointvec,
1157 }, 1035 },
1158 { 1036 {
1159 .ctl_name = VM_SWAPPINESS,
1160 .procname = "swappiness", 1037 .procname = "swappiness",
1161 .data = &vm_swappiness, 1038 .data = &vm_swappiness,
1162 .maxlen = sizeof(vm_swappiness), 1039 .maxlen = sizeof(vm_swappiness),
1163 .mode = 0644, 1040 .mode = 0644,
1164 .proc_handler = &proc_dointvec_minmax, 1041 .proc_handler = proc_dointvec_minmax,
1165 .strategy = &sysctl_intvec,
1166 .extra1 = &zero, 1042 .extra1 = &zero,
1167 .extra2 = &one_hundred, 1043 .extra2 = &one_hundred,
1168 }, 1044 },
@@ -1172,255 +1048,213 @@ static struct ctl_table vm_table[] = {
1172 .data = NULL, 1048 .data = NULL,
1173 .maxlen = sizeof(unsigned long), 1049 .maxlen = sizeof(unsigned long),
1174 .mode = 0644, 1050 .mode = 0644,
1175 .proc_handler = &hugetlb_sysctl_handler, 1051 .proc_handler = hugetlb_sysctl_handler,
1176 .extra1 = (void *)&hugetlb_zero, 1052 .extra1 = (void *)&hugetlb_zero,
1177 .extra2 = (void *)&hugetlb_infinity, 1053 .extra2 = (void *)&hugetlb_infinity,
1178 }, 1054 },
1179 { 1055 {
1180 .ctl_name = VM_HUGETLB_GROUP,
1181 .procname = "hugetlb_shm_group", 1056 .procname = "hugetlb_shm_group",
1182 .data = &sysctl_hugetlb_shm_group, 1057 .data = &sysctl_hugetlb_shm_group,
1183 .maxlen = sizeof(gid_t), 1058 .maxlen = sizeof(gid_t),
1184 .mode = 0644, 1059 .mode = 0644,
1185 .proc_handler = &proc_dointvec, 1060 .proc_handler = proc_dointvec,
1186 }, 1061 },
1187 { 1062 {
1188 .ctl_name = CTL_UNNUMBERED,
1189 .procname = "hugepages_treat_as_movable", 1063 .procname = "hugepages_treat_as_movable",
1190 .data = &hugepages_treat_as_movable, 1064 .data = &hugepages_treat_as_movable,
1191 .maxlen = sizeof(int), 1065 .maxlen = sizeof(int),
1192 .mode = 0644, 1066 .mode = 0644,
1193 .proc_handler = &hugetlb_treat_movable_handler, 1067 .proc_handler = hugetlb_treat_movable_handler,
1194 }, 1068 },
1195 { 1069 {
1196 .ctl_name = CTL_UNNUMBERED,
1197 .procname = "nr_overcommit_hugepages", 1070 .procname = "nr_overcommit_hugepages",
1198 .data = NULL, 1071 .data = NULL,
1199 .maxlen = sizeof(unsigned long), 1072 .maxlen = sizeof(unsigned long),
1200 .mode = 0644, 1073 .mode = 0644,
1201 .proc_handler = &hugetlb_overcommit_handler, 1074 .proc_handler = hugetlb_overcommit_handler,
1202 .extra1 = (void *)&hugetlb_zero, 1075 .extra1 = (void *)&hugetlb_zero,
1203 .extra2 = (void *)&hugetlb_infinity, 1076 .extra2 = (void *)&hugetlb_infinity,
1204 }, 1077 },
1205#endif 1078#endif
1206 { 1079 {
1207 .ctl_name = VM_LOWMEM_RESERVE_RATIO,
1208 .procname = "lowmem_reserve_ratio", 1080 .procname = "lowmem_reserve_ratio",
1209 .data = &sysctl_lowmem_reserve_ratio, 1081 .data = &sysctl_lowmem_reserve_ratio,
1210 .maxlen = sizeof(sysctl_lowmem_reserve_ratio), 1082 .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
1211 .mode = 0644, 1083 .mode = 0644,
1212 .proc_handler = &lowmem_reserve_ratio_sysctl_handler, 1084 .proc_handler = lowmem_reserve_ratio_sysctl_handler,
1213 .strategy = &sysctl_intvec,
1214 }, 1085 },
1215 { 1086 {
1216 .ctl_name = VM_DROP_PAGECACHE,
1217 .procname = "drop_caches", 1087 .procname = "drop_caches",
1218 .data = &sysctl_drop_caches, 1088 .data = &sysctl_drop_caches,
1219 .maxlen = sizeof(int), 1089 .maxlen = sizeof(int),
1220 .mode = 0644, 1090 .mode = 0644,
1221 .proc_handler = drop_caches_sysctl_handler, 1091 .proc_handler = drop_caches_sysctl_handler,
1222 .strategy = &sysctl_intvec,
1223 }, 1092 },
1224 { 1093 {
1225 .ctl_name = VM_MIN_FREE_KBYTES,
1226 .procname = "min_free_kbytes", 1094 .procname = "min_free_kbytes",
1227 .data = &min_free_kbytes, 1095 .data = &min_free_kbytes,
1228 .maxlen = sizeof(min_free_kbytes), 1096 .maxlen = sizeof(min_free_kbytes),
1229 .mode = 0644, 1097 .mode = 0644,
1230 .proc_handler = &min_free_kbytes_sysctl_handler, 1098 .proc_handler = min_free_kbytes_sysctl_handler,
1231 .strategy = &sysctl_intvec,
1232 .extra1 = &zero, 1099 .extra1 = &zero,
1233 }, 1100 },
1234 { 1101 {
1235 .ctl_name = VM_PERCPU_PAGELIST_FRACTION,
1236 .procname = "percpu_pagelist_fraction", 1102 .procname = "percpu_pagelist_fraction",
1237 .data = &percpu_pagelist_fraction, 1103 .data = &percpu_pagelist_fraction,
1238 .maxlen = sizeof(percpu_pagelist_fraction), 1104 .maxlen = sizeof(percpu_pagelist_fraction),
1239 .mode = 0644, 1105 .mode = 0644,
1240 .proc_handler = &percpu_pagelist_fraction_sysctl_handler, 1106 .proc_handler = percpu_pagelist_fraction_sysctl_handler,
1241 .strategy = &sysctl_intvec,
1242 .extra1 = &min_percpu_pagelist_fract, 1107 .extra1 = &min_percpu_pagelist_fract,
1243 }, 1108 },
1244#ifdef CONFIG_MMU 1109#ifdef CONFIG_MMU
1245 { 1110 {
1246 .ctl_name = VM_MAX_MAP_COUNT,
1247 .procname = "max_map_count", 1111 .procname = "max_map_count",
1248 .data = &sysctl_max_map_count, 1112 .data = &sysctl_max_map_count,
1249 .maxlen = sizeof(sysctl_max_map_count), 1113 .maxlen = sizeof(sysctl_max_map_count),
1250 .mode = 0644, 1114 .mode = 0644,
1251 .proc_handler = &proc_dointvec 1115 .proc_handler = proc_dointvec
1252 }, 1116 },
1253#else 1117#else
1254 { 1118 {
1255 .ctl_name = CTL_UNNUMBERED,
1256 .procname = "nr_trim_pages", 1119 .procname = "nr_trim_pages",
1257 .data = &sysctl_nr_trim_pages, 1120 .data = &sysctl_nr_trim_pages,
1258 .maxlen = sizeof(sysctl_nr_trim_pages), 1121 .maxlen = sizeof(sysctl_nr_trim_pages),
1259 .mode = 0644, 1122 .mode = 0644,
1260 .proc_handler = &proc_dointvec_minmax, 1123 .proc_handler = proc_dointvec_minmax,
1261 .strategy = &sysctl_intvec,
1262 .extra1 = &zero, 1124 .extra1 = &zero,
1263 }, 1125 },
1264#endif 1126#endif
1265 { 1127 {
1266 .ctl_name = VM_LAPTOP_MODE,
1267 .procname = "laptop_mode", 1128 .procname = "laptop_mode",
1268 .data = &laptop_mode, 1129 .data = &laptop_mode,
1269 .maxlen = sizeof(laptop_mode), 1130 .maxlen = sizeof(laptop_mode),
1270 .mode = 0644, 1131 .mode = 0644,
1271 .proc_handler = &proc_dointvec_jiffies, 1132 .proc_handler = proc_dointvec_jiffies,
1272 .strategy = &sysctl_jiffies,
1273 }, 1133 },
1274 { 1134 {
1275 .ctl_name = VM_BLOCK_DUMP,
1276 .procname = "block_dump", 1135 .procname = "block_dump",
1277 .data = &block_dump, 1136 .data = &block_dump,
1278 .maxlen = sizeof(block_dump), 1137 .maxlen = sizeof(block_dump),
1279 .mode = 0644, 1138 .mode = 0644,
1280 .proc_handler = &proc_dointvec, 1139 .proc_handler = proc_dointvec,
1281 .strategy = &sysctl_intvec,
1282 .extra1 = &zero, 1140 .extra1 = &zero,
1283 }, 1141 },
1284 { 1142 {
1285 .ctl_name = VM_VFS_CACHE_PRESSURE,
1286 .procname = "vfs_cache_pressure", 1143 .procname = "vfs_cache_pressure",
1287 .data = &sysctl_vfs_cache_pressure, 1144 .data = &sysctl_vfs_cache_pressure,
1288 .maxlen = sizeof(sysctl_vfs_cache_pressure), 1145 .maxlen = sizeof(sysctl_vfs_cache_pressure),
1289 .mode = 0644, 1146 .mode = 0644,
1290 .proc_handler = &proc_dointvec, 1147 .proc_handler = proc_dointvec,
1291 .strategy = &sysctl_intvec,
1292 .extra1 = &zero, 1148 .extra1 = &zero,
1293 }, 1149 },
1294#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT 1150#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
1295 { 1151 {
1296 .ctl_name = VM_LEGACY_VA_LAYOUT,
1297 .procname = "legacy_va_layout", 1152 .procname = "legacy_va_layout",
1298 .data = &sysctl_legacy_va_layout, 1153 .data = &sysctl_legacy_va_layout,
1299 .maxlen = sizeof(sysctl_legacy_va_layout), 1154 .maxlen = sizeof(sysctl_legacy_va_layout),
1300 .mode = 0644, 1155 .mode = 0644,
1301 .proc_handler = &proc_dointvec, 1156 .proc_handler = proc_dointvec,
1302 .strategy = &sysctl_intvec,
1303 .extra1 = &zero, 1157 .extra1 = &zero,
1304 }, 1158 },
1305#endif 1159#endif
1306#ifdef CONFIG_NUMA 1160#ifdef CONFIG_NUMA
1307 { 1161 {
1308 .ctl_name = VM_ZONE_RECLAIM_MODE,
1309 .procname = "zone_reclaim_mode", 1162 .procname = "zone_reclaim_mode",
1310 .data = &zone_reclaim_mode, 1163 .data = &zone_reclaim_mode,
1311 .maxlen = sizeof(zone_reclaim_mode), 1164 .maxlen = sizeof(zone_reclaim_mode),
1312 .mode = 0644, 1165 .mode = 0644,
1313 .proc_handler = &proc_dointvec, 1166 .proc_handler = proc_dointvec,
1314 .strategy = &sysctl_intvec,
1315 .extra1 = &zero, 1167 .extra1 = &zero,
1316 }, 1168 },
1317 { 1169 {
1318 .ctl_name = VM_MIN_UNMAPPED,
1319 .procname = "min_unmapped_ratio", 1170 .procname = "min_unmapped_ratio",
1320 .data = &sysctl_min_unmapped_ratio, 1171 .data = &sysctl_min_unmapped_ratio,
1321 .maxlen = sizeof(sysctl_min_unmapped_ratio), 1172 .maxlen = sizeof(sysctl_min_unmapped_ratio),
1322 .mode = 0644, 1173 .mode = 0644,
1323 .proc_handler = &sysctl_min_unmapped_ratio_sysctl_handler, 1174 .proc_handler = sysctl_min_unmapped_ratio_sysctl_handler,
1324 .strategy = &sysctl_intvec,
1325 .extra1 = &zero, 1175 .extra1 = &zero,
1326 .extra2 = &one_hundred, 1176 .extra2 = &one_hundred,
1327 }, 1177 },
1328 { 1178 {
1329 .ctl_name = VM_MIN_SLAB,
1330 .procname = "min_slab_ratio", 1179 .procname = "min_slab_ratio",
1331 .data = &sysctl_min_slab_ratio, 1180 .data = &sysctl_min_slab_ratio,
1332 .maxlen = sizeof(sysctl_min_slab_ratio), 1181 .maxlen = sizeof(sysctl_min_slab_ratio),
1333 .mode = 0644, 1182 .mode = 0644,
1334 .proc_handler = &sysctl_min_slab_ratio_sysctl_handler, 1183 .proc_handler = sysctl_min_slab_ratio_sysctl_handler,
1335 .strategy = &sysctl_intvec,
1336 .extra1 = &zero, 1184 .extra1 = &zero,
1337 .extra2 = &one_hundred, 1185 .extra2 = &one_hundred,
1338 }, 1186 },
1339#endif 1187#endif
1340#ifdef CONFIG_SMP 1188#ifdef CONFIG_SMP
1341 { 1189 {
1342 .ctl_name = CTL_UNNUMBERED,
1343 .procname = "stat_interval", 1190 .procname = "stat_interval",
1344 .data = &sysctl_stat_interval, 1191 .data = &sysctl_stat_interval,
1345 .maxlen = sizeof(sysctl_stat_interval), 1192 .maxlen = sizeof(sysctl_stat_interval),
1346 .mode = 0644, 1193 .mode = 0644,
1347 .proc_handler = &proc_dointvec_jiffies, 1194 .proc_handler = proc_dointvec_jiffies,
1348 .strategy = &sysctl_jiffies,
1349 }, 1195 },
1350#endif 1196#endif
1351 { 1197 {
1352 .ctl_name = CTL_UNNUMBERED,
1353 .procname = "mmap_min_addr", 1198 .procname = "mmap_min_addr",
1354 .data = &dac_mmap_min_addr, 1199 .data = &dac_mmap_min_addr,
1355 .maxlen = sizeof(unsigned long), 1200 .maxlen = sizeof(unsigned long),
1356 .mode = 0644, 1201 .mode = 0644,
1357 .proc_handler = &mmap_min_addr_handler, 1202 .proc_handler = mmap_min_addr_handler,
1358 }, 1203 },
1359#ifdef CONFIG_NUMA 1204#ifdef CONFIG_NUMA
1360 { 1205 {
1361 .ctl_name = CTL_UNNUMBERED,
1362 .procname = "numa_zonelist_order", 1206 .procname = "numa_zonelist_order",
1363 .data = &numa_zonelist_order, 1207 .data = &numa_zonelist_order,
1364 .maxlen = NUMA_ZONELIST_ORDER_LEN, 1208 .maxlen = NUMA_ZONELIST_ORDER_LEN,
1365 .mode = 0644, 1209 .mode = 0644,
1366 .proc_handler = &numa_zonelist_order_handler, 1210 .proc_handler = numa_zonelist_order_handler,
1367 .strategy = &sysctl_string,
1368 }, 1211 },
1369#endif 1212#endif
1370#if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \ 1213#if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
1371 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) 1214 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
1372 { 1215 {
1373 .ctl_name = VM_VDSO_ENABLED,
1374 .procname = "vdso_enabled", 1216 .procname = "vdso_enabled",
1375 .data = &vdso_enabled, 1217 .data = &vdso_enabled,
1376 .maxlen = sizeof(vdso_enabled), 1218 .maxlen = sizeof(vdso_enabled),
1377 .mode = 0644, 1219 .mode = 0644,
1378 .proc_handler = &proc_dointvec, 1220 .proc_handler = proc_dointvec,
1379 .strategy = &sysctl_intvec,
1380 .extra1 = &zero, 1221 .extra1 = &zero,
1381 }, 1222 },
1382#endif 1223#endif
1383#ifdef CONFIG_HIGHMEM 1224#ifdef CONFIG_HIGHMEM
1384 { 1225 {
1385 .ctl_name = CTL_UNNUMBERED,
1386 .procname = "highmem_is_dirtyable", 1226 .procname = "highmem_is_dirtyable",
1387 .data = &vm_highmem_is_dirtyable, 1227 .data = &vm_highmem_is_dirtyable,
1388 .maxlen = sizeof(vm_highmem_is_dirtyable), 1228 .maxlen = sizeof(vm_highmem_is_dirtyable),
1389 .mode = 0644, 1229 .mode = 0644,
1390 .proc_handler = &proc_dointvec_minmax, 1230 .proc_handler = proc_dointvec_minmax,
1391 .strategy = &sysctl_intvec,
1392 .extra1 = &zero, 1231 .extra1 = &zero,
1393 .extra2 = &one, 1232 .extra2 = &one,
1394 }, 1233 },
1395#endif 1234#endif
1396 { 1235 {
1397 .ctl_name = CTL_UNNUMBERED,
1398 .procname = "scan_unevictable_pages", 1236 .procname = "scan_unevictable_pages",
1399 .data = &scan_unevictable_pages, 1237 .data = &scan_unevictable_pages,
1400 .maxlen = sizeof(scan_unevictable_pages), 1238 .maxlen = sizeof(scan_unevictable_pages),
1401 .mode = 0644, 1239 .mode = 0644,
1402 .proc_handler = &scan_unevictable_handler, 1240 .proc_handler = scan_unevictable_handler,
1403 }, 1241 },
1404#ifdef CONFIG_MEMORY_FAILURE 1242#ifdef CONFIG_MEMORY_FAILURE
1405 { 1243 {
1406 .ctl_name = CTL_UNNUMBERED,
1407 .procname = "memory_failure_early_kill", 1244 .procname = "memory_failure_early_kill",
1408 .data = &sysctl_memory_failure_early_kill, 1245 .data = &sysctl_memory_failure_early_kill,
1409 .maxlen = sizeof(sysctl_memory_failure_early_kill), 1246 .maxlen = sizeof(sysctl_memory_failure_early_kill),
1410 .mode = 0644, 1247 .mode = 0644,
1411 .proc_handler = &proc_dointvec_minmax, 1248 .proc_handler = proc_dointvec_minmax,
1412 .strategy = &sysctl_intvec,
1413 .extra1 = &zero, 1249 .extra1 = &zero,
1414 .extra2 = &one, 1250 .extra2 = &one,
1415 }, 1251 },
1416 { 1252 {
1417 .ctl_name = CTL_UNNUMBERED,
1418 .procname = "memory_failure_recovery", 1253 .procname = "memory_failure_recovery",
1419 .data = &sysctl_memory_failure_recovery, 1254 .data = &sysctl_memory_failure_recovery,
1420 .maxlen = sizeof(sysctl_memory_failure_recovery), 1255 .maxlen = sizeof(sysctl_memory_failure_recovery),
1421 .mode = 0644, 1256 .mode = 0644,
1422 .proc_handler = &proc_dointvec_minmax, 1257 .proc_handler = proc_dointvec_minmax,
1423 .strategy = &sysctl_intvec,
1424 .extra1 = &zero, 1258 .extra1 = &zero,
1425 .extra2 = &one, 1259 .extra2 = &one,
1426 }, 1260 },
@@ -1430,116 +1264,104 @@ static struct ctl_table vm_table[] = {
1430 * NOTE: do not add new entries to this table unless you have read 1264 * NOTE: do not add new entries to this table unless you have read
1431 * Documentation/sysctl/ctl_unnumbered.txt 1265 * Documentation/sysctl/ctl_unnumbered.txt
1432 */ 1266 */
1433 { .ctl_name = 0 } 1267 { }
1434}; 1268};
1435 1269
1436#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) 1270#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
1437static struct ctl_table binfmt_misc_table[] = { 1271static struct ctl_table binfmt_misc_table[] = {
1438 { .ctl_name = 0 } 1272 { }
1439}; 1273};
1440#endif 1274#endif
1441 1275
1442static struct ctl_table fs_table[] = { 1276static struct ctl_table fs_table[] = {
1443 { 1277 {
1444 .ctl_name = FS_NRINODE,
1445 .procname = "inode-nr", 1278 .procname = "inode-nr",
1446 .data = &inodes_stat, 1279 .data = &inodes_stat,
1447 .maxlen = 2*sizeof(int), 1280 .maxlen = 2*sizeof(int),
1448 .mode = 0444, 1281 .mode = 0444,
1449 .proc_handler = &proc_dointvec, 1282 .proc_handler = proc_dointvec,
1450 }, 1283 },
1451 { 1284 {
1452 .ctl_name = FS_STATINODE,
1453 .procname = "inode-state", 1285 .procname = "inode-state",
1454 .data = &inodes_stat, 1286 .data = &inodes_stat,
1455 .maxlen = 7*sizeof(int), 1287 .maxlen = 7*sizeof(int),
1456 .mode = 0444, 1288 .mode = 0444,
1457 .proc_handler = &proc_dointvec, 1289 .proc_handler = proc_dointvec,
1458 }, 1290 },
1459 { 1291 {
1460 .procname = "file-nr", 1292 .procname = "file-nr",
1461 .data = &files_stat, 1293 .data = &files_stat,
1462 .maxlen = 3*sizeof(int), 1294 .maxlen = 3*sizeof(int),
1463 .mode = 0444, 1295 .mode = 0444,
1464 .proc_handler = &proc_nr_files, 1296 .proc_handler = proc_nr_files,
1465 }, 1297 },
1466 { 1298 {
1467 .ctl_name = FS_MAXFILE,
1468 .procname = "file-max", 1299 .procname = "file-max",
1469 .data = &files_stat.max_files, 1300 .data = &files_stat.max_files,
1470 .maxlen = sizeof(int), 1301 .maxlen = sizeof(int),
1471 .mode = 0644, 1302 .mode = 0644,
1472 .proc_handler = &proc_dointvec, 1303 .proc_handler = proc_dointvec,
1473 }, 1304 },
1474 { 1305 {
1475 .ctl_name = CTL_UNNUMBERED,
1476 .procname = "nr_open", 1306 .procname = "nr_open",
1477 .data = &sysctl_nr_open, 1307 .data = &sysctl_nr_open,
1478 .maxlen = sizeof(int), 1308 .maxlen = sizeof(int),
1479 .mode = 0644, 1309 .mode = 0644,
1480 .proc_handler = &proc_dointvec_minmax, 1310 .proc_handler = proc_dointvec_minmax,
1481 .extra1 = &sysctl_nr_open_min, 1311 .extra1 = &sysctl_nr_open_min,
1482 .extra2 = &sysctl_nr_open_max, 1312 .extra2 = &sysctl_nr_open_max,
1483 }, 1313 },
1484 { 1314 {
1485 .ctl_name = FS_DENTRY,
1486 .procname = "dentry-state", 1315 .procname = "dentry-state",
1487 .data = &dentry_stat, 1316 .data = &dentry_stat,
1488 .maxlen = 6*sizeof(int), 1317 .maxlen = 6*sizeof(int),
1489 .mode = 0444, 1318 .mode = 0444,
1490 .proc_handler = &proc_dointvec, 1319 .proc_handler = proc_dointvec,
1491 }, 1320 },
1492 { 1321 {
1493 .ctl_name = FS_OVERFLOWUID,
1494 .procname = "overflowuid", 1322 .procname = "overflowuid",
1495 .data = &fs_overflowuid, 1323 .data = &fs_overflowuid,
1496 .maxlen = sizeof(int), 1324 .maxlen = sizeof(int),
1497 .mode = 0644, 1325 .mode = 0644,
1498 .proc_handler = &proc_dointvec_minmax, 1326 .proc_handler = proc_dointvec_minmax,
1499 .strategy = &sysctl_intvec,
1500 .extra1 = &minolduid, 1327 .extra1 = &minolduid,
1501 .extra2 = &maxolduid, 1328 .extra2 = &maxolduid,
1502 }, 1329 },
1503 { 1330 {
1504 .ctl_name = FS_OVERFLOWGID,
1505 .procname = "overflowgid", 1331 .procname = "overflowgid",
1506 .data = &fs_overflowgid, 1332 .data = &fs_overflowgid,
1507 .maxlen = sizeof(int), 1333 .maxlen = sizeof(int),
1508 .mode = 0644, 1334 .mode = 0644,
1509 .proc_handler = &proc_dointvec_minmax, 1335 .proc_handler = proc_dointvec_minmax,
1510 .strategy = &sysctl_intvec,
1511 .extra1 = &minolduid, 1336 .extra1 = &minolduid,
1512 .extra2 = &maxolduid, 1337 .extra2 = &maxolduid,
1513 }, 1338 },
1514#ifdef CONFIG_FILE_LOCKING 1339#ifdef CONFIG_FILE_LOCKING
1515 { 1340 {
1516 .ctl_name = FS_LEASES,
1517 .procname = "leases-enable", 1341 .procname = "leases-enable",
1518 .data = &leases_enable, 1342 .data = &leases_enable,
1519 .maxlen = sizeof(int), 1343 .maxlen = sizeof(int),
1520 .mode = 0644, 1344 .mode = 0644,
1521 .proc_handler = &proc_dointvec, 1345 .proc_handler = proc_dointvec,
1522 }, 1346 },
1523#endif 1347#endif
1524#ifdef CONFIG_DNOTIFY 1348#ifdef CONFIG_DNOTIFY
1525 { 1349 {
1526 .ctl_name = FS_DIR_NOTIFY,
1527 .procname = "dir-notify-enable", 1350 .procname = "dir-notify-enable",
1528 .data = &dir_notify_enable, 1351 .data = &dir_notify_enable,
1529 .maxlen = sizeof(int), 1352 .maxlen = sizeof(int),
1530 .mode = 0644, 1353 .mode = 0644,
1531 .proc_handler = &proc_dointvec, 1354 .proc_handler = proc_dointvec,
1532 }, 1355 },
1533#endif 1356#endif
1534#ifdef CONFIG_MMU 1357#ifdef CONFIG_MMU
1535#ifdef CONFIG_FILE_LOCKING 1358#ifdef CONFIG_FILE_LOCKING
1536 { 1359 {
1537 .ctl_name = FS_LEASE_TIME,
1538 .procname = "lease-break-time", 1360 .procname = "lease-break-time",
1539 .data = &lease_break_time, 1361 .data = &lease_break_time,
1540 .maxlen = sizeof(int), 1362 .maxlen = sizeof(int),
1541 .mode = 0644, 1363 .mode = 0644,
1542 .proc_handler = &proc_dointvec, 1364 .proc_handler = proc_dointvec,
1543 }, 1365 },
1544#endif 1366#endif
1545#ifdef CONFIG_AIO 1367#ifdef CONFIG_AIO
@@ -1548,19 +1370,18 @@ static struct ctl_table fs_table[] = {
1548 .data = &aio_nr, 1370 .data = &aio_nr,
1549 .maxlen = sizeof(aio_nr), 1371 .maxlen = sizeof(aio_nr),
1550 .mode = 0444, 1372 .mode = 0444,
1551 .proc_handler = &proc_doulongvec_minmax, 1373 .proc_handler = proc_doulongvec_minmax,
1552 }, 1374 },
1553 { 1375 {
1554 .procname = "aio-max-nr", 1376 .procname = "aio-max-nr",
1555 .data = &aio_max_nr, 1377 .data = &aio_max_nr,
1556 .maxlen = sizeof(aio_max_nr), 1378 .maxlen = sizeof(aio_max_nr),
1557 .mode = 0644, 1379 .mode = 0644,
1558 .proc_handler = &proc_doulongvec_minmax, 1380 .proc_handler = proc_doulongvec_minmax,
1559 }, 1381 },
1560#endif /* CONFIG_AIO */ 1382#endif /* CONFIG_AIO */
1561#ifdef CONFIG_INOTIFY_USER 1383#ifdef CONFIG_INOTIFY_USER
1562 { 1384 {
1563 .ctl_name = FS_INOTIFY,
1564 .procname = "inotify", 1385 .procname = "inotify",
1565 .mode = 0555, 1386 .mode = 0555,
1566 .child = inotify_table, 1387 .child = inotify_table,
@@ -1575,19 +1396,16 @@ static struct ctl_table fs_table[] = {
1575#endif 1396#endif
1576#endif 1397#endif
1577 { 1398 {
1578 .ctl_name = KERN_SETUID_DUMPABLE,
1579 .procname = "suid_dumpable", 1399 .procname = "suid_dumpable",
1580 .data = &suid_dumpable, 1400 .data = &suid_dumpable,
1581 .maxlen = sizeof(int), 1401 .maxlen = sizeof(int),
1582 .mode = 0644, 1402 .mode = 0644,
1583 .proc_handler = &proc_dointvec_minmax, 1403 .proc_handler = proc_dointvec_minmax,
1584 .strategy = &sysctl_intvec,
1585 .extra1 = &zero, 1404 .extra1 = &zero,
1586 .extra2 = &two, 1405 .extra2 = &two,
1587 }, 1406 },
1588#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) 1407#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
1589 { 1408 {
1590 .ctl_name = CTL_UNNUMBERED,
1591 .procname = "binfmt_misc", 1409 .procname = "binfmt_misc",
1592 .mode = 0555, 1410 .mode = 0555,
1593 .child = binfmt_misc_table, 1411 .child = binfmt_misc_table,
@@ -1597,13 +1415,12 @@ static struct ctl_table fs_table[] = {
1597 * NOTE: do not add new entries to this table unless you have read 1415 * NOTE: do not add new entries to this table unless you have read
1598 * Documentation/sysctl/ctl_unnumbered.txt 1416 * Documentation/sysctl/ctl_unnumbered.txt
1599 */ 1417 */
1600 { .ctl_name = 0 } 1418 { }
1601}; 1419};
1602 1420
1603static struct ctl_table debug_table[] = { 1421static struct ctl_table debug_table[] = {
1604#if defined(CONFIG_X86) || defined(CONFIG_PPC) 1422#if defined(CONFIG_X86) || defined(CONFIG_PPC)
1605 { 1423 {
1606 .ctl_name = CTL_UNNUMBERED,
1607 .procname = "exception-trace", 1424 .procname = "exception-trace",
1608 .data = &show_unhandled_signals, 1425 .data = &show_unhandled_signals,
1609 .maxlen = sizeof(int), 1426 .maxlen = sizeof(int),
@@ -1611,11 +1428,11 @@ static struct ctl_table debug_table[] = {
1611 .proc_handler = proc_dointvec 1428 .proc_handler = proc_dointvec
1612 }, 1429 },
1613#endif 1430#endif
1614 { .ctl_name = 0 } 1431 { }
1615}; 1432};
1616 1433
1617static struct ctl_table dev_table[] = { 1434static struct ctl_table dev_table[] = {
1618 { .ctl_name = 0 } 1435 { }
1619}; 1436};
1620 1437
1621static DEFINE_SPINLOCK(sysctl_lock); 1438static DEFINE_SPINLOCK(sysctl_lock);
@@ -1769,122 +1586,6 @@ void register_sysctl_root(struct ctl_table_root *root)
1769 spin_unlock(&sysctl_lock); 1586 spin_unlock(&sysctl_lock);
1770} 1587}
1771 1588
1772#ifdef CONFIG_SYSCTL_SYSCALL
1773/* Perform the actual read/write of a sysctl table entry. */
1774static int do_sysctl_strategy(struct ctl_table_root *root,
1775 struct ctl_table *table,
1776 void __user *oldval, size_t __user *oldlenp,
1777 void __user *newval, size_t newlen)
1778{
1779 int op = 0, rc;
1780
1781 if (oldval)
1782 op |= MAY_READ;
1783 if (newval)
1784 op |= MAY_WRITE;
1785 if (sysctl_perm(root, table, op))
1786 return -EPERM;
1787
1788 if (table->strategy) {
1789 rc = table->strategy(table, oldval, oldlenp, newval, newlen);
1790 if (rc < 0)
1791 return rc;
1792 if (rc > 0)
1793 return 0;
1794 }
1795
1796 /* If there is no strategy routine, or if the strategy returns
1797 * zero, proceed with automatic r/w */
1798 if (table->data && table->maxlen) {
1799 rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
1800 if (rc < 0)
1801 return rc;
1802 }
1803 return 0;
1804}
1805
1806static int parse_table(int __user *name, int nlen,
1807 void __user *oldval, size_t __user *oldlenp,
1808 void __user *newval, size_t newlen,
1809 struct ctl_table_root *root,
1810 struct ctl_table *table)
1811{
1812 int n;
1813repeat:
1814 if (!nlen)
1815 return -ENOTDIR;
1816 if (get_user(n, name))
1817 return -EFAULT;
1818 for ( ; table->ctl_name || table->procname; table++) {
1819 if (!table->ctl_name)
1820 continue;
1821 if (n == table->ctl_name) {
1822 int error;
1823 if (table->child) {
1824 if (sysctl_perm(root, table, MAY_EXEC))
1825 return -EPERM;
1826 name++;
1827 nlen--;
1828 table = table->child;
1829 goto repeat;
1830 }
1831 error = do_sysctl_strategy(root, table,
1832 oldval, oldlenp,
1833 newval, newlen);
1834 return error;
1835 }
1836 }
1837 return -ENOTDIR;
1838}
1839
1840int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1841 void __user *newval, size_t newlen)
1842{
1843 struct ctl_table_header *head;
1844 int error = -ENOTDIR;
1845
1846 if (nlen <= 0 || nlen >= CTL_MAXNAME)
1847 return -ENOTDIR;
1848 if (oldval) {
1849 int old_len;
1850 if (!oldlenp || get_user(old_len, oldlenp))
1851 return -EFAULT;
1852 }
1853
1854 for (head = sysctl_head_next(NULL); head;
1855 head = sysctl_head_next(head)) {
1856 error = parse_table(name, nlen, oldval, oldlenp,
1857 newval, newlen,
1858 head->root, head->ctl_table);
1859 if (error != -ENOTDIR) {
1860 sysctl_head_finish(head);
1861 break;
1862 }
1863 }
1864 return error;
1865}
1866
1867SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
1868{
1869 struct __sysctl_args tmp;
1870 int error;
1871
1872 if (copy_from_user(&tmp, args, sizeof(tmp)))
1873 return -EFAULT;
1874
1875 error = deprecated_sysctl_warning(&tmp);
1876 if (error)
1877 goto out;
1878
1879 lock_kernel();
1880 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
1881 tmp.newval, tmp.newlen);
1882 unlock_kernel();
1883out:
1884 return error;
1885}
1886#endif /* CONFIG_SYSCTL_SYSCALL */
1887
1888/* 1589/*
1889 * sysctl_perm does NOT grant the superuser all rights automatically, because 1590 * sysctl_perm does NOT grant the superuser all rights automatically, because
1890 * some sysctl variables are readonly even to root. 1591 * some sysctl variables are readonly even to root.
@@ -1920,7 +1621,7 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
1920 1621
1921static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) 1622static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
1922{ 1623{
1923 for (; table->ctl_name || table->procname; table++) { 1624 for (; table->procname; table++) {
1924 table->parent = parent; 1625 table->parent = parent;
1925 if (table->child) 1626 if (table->child)
1926 sysctl_set_parent(table, table->child); 1627 sysctl_set_parent(table, table->child);
@@ -1952,11 +1653,11 @@ static struct ctl_table *is_branch_in(struct ctl_table *branch,
1952 return NULL; 1653 return NULL;
1953 1654
1954 /* ... and nothing else */ 1655 /* ... and nothing else */
1955 if (branch[1].procname || branch[1].ctl_name) 1656 if (branch[1].procname)
1956 return NULL; 1657 return NULL;
1957 1658
1958 /* table should contain subdirectory with the same name */ 1659 /* table should contain subdirectory with the same name */
1959 for (p = table; p->procname || p->ctl_name; p++) { 1660 for (p = table; p->procname; p++) {
1960 if (!p->child) 1661 if (!p->child)
1961 continue; 1662 continue;
1962 if (p->procname && strcmp(p->procname, s) == 0) 1663 if (p->procname && strcmp(p->procname, s) == 0)
@@ -2001,9 +1702,6 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
2001 * 1702 *
2002 * The members of the &struct ctl_table structure are used as follows: 1703 * The members of the &struct ctl_table structure are used as follows:
2003 * 1704 *
2004 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
2005 * must be unique within that level of sysctl
2006 *
2007 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not 1705 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
2008 * enter a sysctl file 1706 * enter a sysctl file
2009 * 1707 *
@@ -2018,8 +1716,6 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
2018 * 1716 *
2019 * proc_handler - the text handler routine (described below) 1717 * proc_handler - the text handler routine (described below)
2020 * 1718 *
2021 * strategy - the strategy routine (described below)
2022 *
2023 * de - for internal use by the sysctl routines 1719 * de - for internal use by the sysctl routines
2024 * 1720 *
2025 * extra1, extra2 - extra pointers usable by the proc handler routines 1721 * extra1, extra2 - extra pointers usable by the proc handler routines
@@ -2032,19 +1728,6 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
2032 * struct enable minimal validation of the values being written to be 1728 * struct enable minimal validation of the values being written to be
2033 * performed, and the mode field allows minimal authentication. 1729 * performed, and the mode field allows minimal authentication.
2034 * 1730 *
2035 * More sophisticated management can be enabled by the provision of a
2036 * strategy routine with the table entry. This will be called before
2037 * any automatic read or write of the data is performed.
2038 *
2039 * The strategy routine may return
2040 *
2041 * < 0 - Error occurred (error is passed to user process)
2042 *
2043 * 0 - OK - proceed with automatic read or write.
2044 *
2045 * > 0 - OK - read or write has been done by the strategy routine, so
2046 * return immediately.
2047 *
2048 * There must be a proc_handler routine for any terminal nodes 1731 * There must be a proc_handler routine for any terminal nodes
2049 * mirrored under /proc/sys (non-terminals are handled by a built-in 1732 * mirrored under /proc/sys (non-terminals are handled by a built-in
2050 * directory handler). Several default handlers are available to 1733 * directory handler). Several default handlers are available to
@@ -2071,13 +1754,13 @@ struct ctl_table_header *__register_sysctl_paths(
2071 struct ctl_table_set *set; 1754 struct ctl_table_set *set;
2072 1755
2073 /* Count the path components */ 1756 /* Count the path components */
2074 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath) 1757 for (npath = 0; path[npath].procname; ++npath)
2075 ; 1758 ;
2076 1759
2077 /* 1760 /*
2078 * For each path component, allocate a 2-element ctl_table array. 1761 * For each path component, allocate a 2-element ctl_table array.
2079 * The first array element will be filled with the sysctl entry 1762 * The first array element will be filled with the sysctl entry
2080 * for this, the second will be the sentinel (ctl_name == 0). 1763 * for this, the second will be the sentinel (procname == 0).
2081 * 1764 *
2082 * We allocate everything in one go so that we don't have to 1765 * We allocate everything in one go so that we don't have to
2083 * worry about freeing additional memory in unregister_sysctl_table. 1766 * worry about freeing additional memory in unregister_sysctl_table.
@@ -2094,7 +1777,6 @@ struct ctl_table_header *__register_sysctl_paths(
2094 for (n = 0; n < npath; ++n, ++path) { 1777 for (n = 0; n < npath; ++n, ++path) {
2095 /* Copy the procname */ 1778 /* Copy the procname */
2096 new->procname = path->procname; 1779 new->procname = path->procname;
2097 new->ctl_name = path->ctl_name;
2098 new->mode = 0555; 1780 new->mode = 0555;
2099 1781
2100 *prevp = new; 1782 *prevp = new;
@@ -2956,286 +2638,6 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
2956 2638
2957#endif /* CONFIG_PROC_FS */ 2639#endif /* CONFIG_PROC_FS */
2958 2640
2959
2960#ifdef CONFIG_SYSCTL_SYSCALL
2961/*
2962 * General sysctl support routines
2963 */
2964
2965/* The generic sysctl data routine (used if no strategy routine supplied) */
2966int sysctl_data(struct ctl_table *table,
2967 void __user *oldval, size_t __user *oldlenp,
2968 void __user *newval, size_t newlen)
2969{
2970 size_t len;
2971
2972 /* Get out of I don't have a variable */
2973 if (!table->data || !table->maxlen)
2974 return -ENOTDIR;
2975
2976 if (oldval && oldlenp) {
2977 if (get_user(len, oldlenp))
2978 return -EFAULT;
2979 if (len) {
2980 if (len > table->maxlen)
2981 len = table->maxlen;
2982 if (copy_to_user(oldval, table->data, len))
2983 return -EFAULT;
2984 if (put_user(len, oldlenp))
2985 return -EFAULT;
2986 }
2987 }
2988
2989 if (newval && newlen) {
2990 if (newlen > table->maxlen)
2991 newlen = table->maxlen;
2992
2993 if (copy_from_user(table->data, newval, newlen))
2994 return -EFAULT;
2995 }
2996 return 1;
2997}
2998
2999/* The generic string strategy routine: */
3000int sysctl_string(struct ctl_table *table,
3001 void __user *oldval, size_t __user *oldlenp,
3002 void __user *newval, size_t newlen)
3003{
3004 if (!table->data || !table->maxlen)
3005 return -ENOTDIR;
3006
3007 if (oldval && oldlenp) {
3008 size_t bufsize;
3009 if (get_user(bufsize, oldlenp))
3010 return -EFAULT;
3011 if (bufsize) {
3012 size_t len = strlen(table->data), copied;
3013
3014 /* This shouldn't trigger for a well-formed sysctl */
3015 if (len > table->maxlen)
3016 len = table->maxlen;
3017
3018 /* Copy up to a max of bufsize-1 bytes of the string */
3019 copied = (len >= bufsize) ? bufsize - 1 : len;
3020
3021 if (copy_to_user(oldval, table->data, copied) ||
3022 put_user(0, (char __user *)(oldval + copied)))
3023 return -EFAULT;
3024 if (put_user(len, oldlenp))
3025 return -EFAULT;
3026 }
3027 }
3028 if (newval && newlen) {
3029 size_t len = newlen;
3030 if (len > table->maxlen)
3031 len = table->maxlen;
3032 if(copy_from_user(table->data, newval, len))
3033 return -EFAULT;
3034 if (len == table->maxlen)
3035 len--;
3036 ((char *) table->data)[len] = 0;
3037 }
3038 return 1;
3039}
3040
3041/*
3042 * This function makes sure that all of the integers in the vector
3043 * are between the minimum and maximum values given in the arrays
3044 * table->extra1 and table->extra2, respectively.
3045 */
3046int sysctl_intvec(struct ctl_table *table,
3047 void __user *oldval, size_t __user *oldlenp,
3048 void __user *newval, size_t newlen)
3049{
3050
3051 if (newval && newlen) {
3052 int __user *vec = (int __user *) newval;
3053 int *min = (int *) table->extra1;
3054 int *max = (int *) table->extra2;
3055 size_t length;
3056 int i;
3057
3058 if (newlen % sizeof(int) != 0)
3059 return -EINVAL;
3060
3061 if (!table->extra1 && !table->extra2)
3062 return 0;
3063
3064 if (newlen > table->maxlen)
3065 newlen = table->maxlen;
3066 length = newlen / sizeof(int);
3067
3068 for (i = 0; i < length; i++) {
3069 int value;
3070 if (get_user(value, vec + i))
3071 return -EFAULT;
3072 if (min && value < min[i])
3073 return -EINVAL;
3074 if (max && value > max[i])
3075 return -EINVAL;
3076 }
3077 }
3078 return 0;
3079}
3080
3081/* Strategy function to convert jiffies to seconds */
3082int sysctl_jiffies(struct ctl_table *table,
3083 void __user *oldval, size_t __user *oldlenp,
3084 void __user *newval, size_t newlen)
3085{
3086 if (oldval && oldlenp) {
3087 size_t olen;
3088
3089 if (get_user(olen, oldlenp))
3090 return -EFAULT;
3091 if (olen) {
3092 int val;
3093
3094 if (olen < sizeof(int))
3095 return -EINVAL;
3096
3097 val = *(int *)(table->data) / HZ;
3098 if (put_user(val, (int __user *)oldval))
3099 return -EFAULT;
3100 if (put_user(sizeof(int), oldlenp))
3101 return -EFAULT;
3102 }
3103 }
3104 if (newval && newlen) {
3105 int new;
3106 if (newlen != sizeof(int))
3107 return -EINVAL;
3108 if (get_user(new, (int __user *)newval))
3109 return -EFAULT;
3110 *(int *)(table->data) = new*HZ;
3111 }
3112 return 1;
3113}
3114
3115/* Strategy function to convert jiffies to seconds */
3116int sysctl_ms_jiffies(struct ctl_table *table,
3117 void __user *oldval, size_t __user *oldlenp,
3118 void __user *newval, size_t newlen)
3119{
3120 if (oldval && oldlenp) {
3121 size_t olen;
3122
3123 if (get_user(olen, oldlenp))
3124 return -EFAULT;
3125 if (olen) {
3126 int val;
3127
3128 if (olen < sizeof(int))
3129 return -EINVAL;
3130
3131 val = jiffies_to_msecs(*(int *)(table->data));
3132 if (put_user(val, (int __user *)oldval))
3133 return -EFAULT;
3134 if (put_user(sizeof(int), oldlenp))
3135 return -EFAULT;
3136 }
3137 }
3138 if (newval && newlen) {
3139 int new;
3140 if (newlen != sizeof(int))
3141 return -EINVAL;
3142 if (get_user(new, (int __user *)newval))
3143 return -EFAULT;
3144 *(int *)(table->data) = msecs_to_jiffies(new);
3145 }
3146 return 1;
3147}
3148
3149
3150
3151#else /* CONFIG_SYSCTL_SYSCALL */
3152
3153
3154SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
3155{
3156 struct __sysctl_args tmp;
3157 int error;
3158
3159 if (copy_from_user(&tmp, args, sizeof(tmp)))
3160 return -EFAULT;
3161
3162 error = deprecated_sysctl_warning(&tmp);
3163
3164 /* If no error reading the parameters then just -ENOSYS ... */
3165 if (!error)
3166 error = -ENOSYS;
3167
3168 return error;
3169}
3170
3171int sysctl_data(struct ctl_table *table,
3172 void __user *oldval, size_t __user *oldlenp,
3173 void __user *newval, size_t newlen)
3174{
3175 return -ENOSYS;
3176}
3177
3178int sysctl_string(struct ctl_table *table,
3179 void __user *oldval, size_t __user *oldlenp,
3180 void __user *newval, size_t newlen)
3181{
3182 return -ENOSYS;
3183}
3184
3185int sysctl_intvec(struct ctl_table *table,
3186 void __user *oldval, size_t __user *oldlenp,
3187 void __user *newval, size_t newlen)
3188{
3189 return -ENOSYS;
3190}
3191
3192int sysctl_jiffies(struct ctl_table *table,
3193 void __user *oldval, size_t __user *oldlenp,
3194 void __user *newval, size_t newlen)
3195{
3196 return -ENOSYS;
3197}
3198
3199int sysctl_ms_jiffies(struct ctl_table *table,
3200 void __user *oldval, size_t __user *oldlenp,
3201 void __user *newval, size_t newlen)
3202{
3203 return -ENOSYS;
3204}
3205
3206#endif /* CONFIG_SYSCTL_SYSCALL */
3207
3208static int deprecated_sysctl_warning(struct __sysctl_args *args)
3209{
3210 static int msg_count;
3211 int name[CTL_MAXNAME];
3212 int i;
3213
3214 /* Check args->nlen. */
3215 if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
3216 return -ENOTDIR;
3217
3218 /* Read in the sysctl name for better debug message logging */
3219 for (i = 0; i < args->nlen; i++)
3220 if (get_user(name[i], args->name + i))
3221 return -EFAULT;
3222
3223 /* Ignore accesses to kernel.version */
3224 if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
3225 return 0;
3226
3227 if (msg_count < 5) {
3228 msg_count++;
3229 printk(KERN_INFO
3230 "warning: process `%s' used the deprecated sysctl "
3231 "system call with ", current->comm);
3232 for (i = 0; i < args->nlen; i++)
3233 printk("%d.", name[i]);
3234 printk("\n");
3235 }
3236 return 0;
3237}
3238
3239/* 2641/*
3240 * No sense putting this after each symbol definition, twice, 2642 * No sense putting this after each symbol definition, twice,
3241 * exception granted :-) 2643 * exception granted :-)
@@ -3250,9 +2652,4 @@ EXPORT_SYMBOL(proc_doulongvec_minmax);
3250EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); 2652EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
3251EXPORT_SYMBOL(register_sysctl_table); 2653EXPORT_SYMBOL(register_sysctl_table);
3252EXPORT_SYMBOL(register_sysctl_paths); 2654EXPORT_SYMBOL(register_sysctl_paths);
3253EXPORT_SYMBOL(sysctl_intvec);
3254EXPORT_SYMBOL(sysctl_jiffies);
3255EXPORT_SYMBOL(sysctl_ms_jiffies);
3256EXPORT_SYMBOL(sysctl_string);
3257EXPORT_SYMBOL(sysctl_data);
3258EXPORT_SYMBOL(unregister_sysctl_table); 2655EXPORT_SYMBOL(unregister_sysctl_table);
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
new file mode 100644
index 000000000000..b75dbf40f573
--- /dev/null
+++ b/kernel/sysctl_binary.c
@@ -0,0 +1,1507 @@
1#include <linux/stat.h>
2#include <linux/sysctl.h>
3#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
4#include <linux/sunrpc/debug.h>
5#include <linux/string.h>
6#include <net/ip_vs.h>
7#include <linux/syscalls.h>
8#include <linux/namei.h>
9#include <linux/mount.h>
10#include <linux/fs.h>
11#include <linux/nsproxy.h>
12#include <linux/pid_namespace.h>
13#include <linux/file.h>
14#include <linux/ctype.h>
15#include <linux/netdevice.h>
16
17#ifdef CONFIG_SYSCTL_SYSCALL
18
19struct bin_table;
20typedef ssize_t bin_convert_t(struct file *file,
21 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen);
22
23static bin_convert_t bin_dir;
24static bin_convert_t bin_string;
25static bin_convert_t bin_intvec;
26static bin_convert_t bin_ulongvec;
27static bin_convert_t bin_uuid;
28static bin_convert_t bin_dn_node_address;
29
30#define CTL_DIR bin_dir
31#define CTL_STR bin_string
32#define CTL_INT bin_intvec
33#define CTL_ULONG bin_ulongvec
34#define CTL_UUID bin_uuid
35#define CTL_DNADR bin_dn_node_address
36
37#define BUFSZ 256
38
39struct bin_table {
40 bin_convert_t *convert;
41 int ctl_name;
42 const char *procname;
43 const struct bin_table *child;
44};
45
46static const struct bin_table bin_random_table[] = {
47 { CTL_INT, RANDOM_POOLSIZE, "poolsize" },
48 { CTL_INT, RANDOM_ENTROPY_COUNT, "entropy_avail" },
49 { CTL_INT, RANDOM_READ_THRESH, "read_wakeup_threshold" },
50 { CTL_INT, RANDOM_WRITE_THRESH, "write_wakeup_threshold" },
51 { CTL_UUID, RANDOM_BOOT_ID, "boot_id" },
52 { CTL_UUID, RANDOM_UUID, "uuid" },
53 {}
54};
55
56static const struct bin_table bin_pty_table[] = {
57 { CTL_INT, PTY_MAX, "max" },
58 { CTL_INT, PTY_NR, "nr" },
59 {}
60};
61
62static const struct bin_table bin_kern_table[] = {
63 { CTL_STR, KERN_OSTYPE, "ostype" },
64 { CTL_STR, KERN_OSRELEASE, "osrelease" },
65 /* KERN_OSREV not used */
66 { CTL_STR, KERN_VERSION, "version" },
67 /* KERN_SECUREMASK not used */
68 /* KERN_PROF not used */
69 { CTL_STR, KERN_NODENAME, "hostname" },
70 { CTL_STR, KERN_DOMAINNAME, "domainname" },
71
72 { CTL_INT, KERN_PANIC, "panic" },
73 { CTL_INT, KERN_REALROOTDEV, "real-root-dev" },
74
75 { CTL_STR, KERN_SPARC_REBOOT, "reboot-cmd" },
76 { CTL_INT, KERN_CTLALTDEL, "ctrl-alt-del" },
77 { CTL_INT, KERN_PRINTK, "printk" },
78
79 /* KERN_NAMETRANS not used */
80 /* KERN_PPC_HTABRECLAIM not used */
81 /* KERN_PPC_ZEROPAGED not used */
82 { CTL_INT, KERN_PPC_POWERSAVE_NAP, "powersave-nap" },
83
84 { CTL_STR, KERN_MODPROBE, "modprobe" },
85 { CTL_INT, KERN_SG_BIG_BUFF, "sg-big-buff" },
86 { CTL_INT, KERN_ACCT, "acct" },
87 /* KERN_PPC_L2CR "l2cr" no longer used */
88
89 /* KERN_RTSIGNR not used */
90 /* KERN_RTSIGMAX not used */
91
92 { CTL_ULONG, KERN_SHMMAX, "shmmax" },
93 { CTL_INT, KERN_MSGMAX, "msgmax" },
94 { CTL_INT, KERN_MSGMNB, "msgmnb" },
95 /* KERN_MSGPOOL not used*/
96 { CTL_INT, KERN_SYSRQ, "sysrq" },
97 { CTL_INT, KERN_MAX_THREADS, "threads-max" },
98 { CTL_DIR, KERN_RANDOM, "random", bin_random_table },
99 { CTL_ULONG, KERN_SHMALL, "shmall" },
100 { CTL_INT, KERN_MSGMNI, "msgmni" },
101 { CTL_INT, KERN_SEM, "sem" },
102 { CTL_INT, KERN_SPARC_STOP_A, "stop-a" },
103 { CTL_INT, KERN_SHMMNI, "shmmni" },
104
105 { CTL_INT, KERN_OVERFLOWUID, "overflowuid" },
106 { CTL_INT, KERN_OVERFLOWGID, "overflowgid" },
107
108 { CTL_STR, KERN_HOTPLUG, "hotplug", },
109 { CTL_INT, KERN_IEEE_EMULATION_WARNINGS, "ieee_emulation_warnings" },
110
111 { CTL_INT, KERN_S390_USER_DEBUG_LOGGING, "userprocess_debug" },
112 { CTL_INT, KERN_CORE_USES_PID, "core_uses_pid" },
113 /* KERN_TAINTED "tainted" no longer used */
114 { CTL_INT, KERN_CADPID, "cad_pid" },
115 { CTL_INT, KERN_PIDMAX, "pid_max" },
116 { CTL_STR, KERN_CORE_PATTERN, "core_pattern" },
117 { CTL_INT, KERN_PANIC_ON_OOPS, "panic_on_oops" },
118 { CTL_INT, KERN_HPPA_PWRSW, "soft-power" },
119 { CTL_INT, KERN_HPPA_UNALIGNED, "unaligned-trap" },
120
121 { CTL_INT, KERN_PRINTK_RATELIMIT, "printk_ratelimit" },
122 { CTL_INT, KERN_PRINTK_RATELIMIT_BURST, "printk_ratelimit_burst" },
123
124 { CTL_DIR, KERN_PTY, "pty", bin_pty_table },
125 { CTL_INT, KERN_NGROUPS_MAX, "ngroups_max" },
126 { CTL_INT, KERN_SPARC_SCONS_PWROFF, "scons-poweroff" },
127 /* KERN_HZ_TIMER "hz_timer" no longer used */
128 { CTL_INT, KERN_UNKNOWN_NMI_PANIC, "unknown_nmi_panic" },
129 { CTL_INT, KERN_BOOTLOADER_TYPE, "bootloader_type" },
130 { CTL_INT, KERN_RANDOMIZE, "randomize_va_space" },
131
132 { CTL_INT, KERN_SPIN_RETRY, "spin_retry" },
133 /* KERN_ACPI_VIDEO_FLAGS "acpi_video_flags" no longer used */
134 { CTL_INT, KERN_IA64_UNALIGNED, "ignore-unaligned-usertrap" },
135 { CTL_INT, KERN_COMPAT_LOG, "compat-log" },
136 { CTL_INT, KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
137 { CTL_INT, KERN_NMI_WATCHDOG, "nmi_watchdog" },
138 { CTL_INT, KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
139 {}
140};
141
142static const struct bin_table bin_vm_table[] = {
143 { CTL_INT, VM_OVERCOMMIT_MEMORY, "overcommit_memory" },
144 { CTL_INT, VM_PAGE_CLUSTER, "page-cluster" },
145 { CTL_INT, VM_DIRTY_BACKGROUND, "dirty_background_ratio" },
146 { CTL_INT, VM_DIRTY_RATIO, "dirty_ratio" },
147 /* VM_DIRTY_WB_CS "dirty_writeback_centisecs" no longer used */
148 /* VM_DIRTY_EXPIRE_CS "dirty_expire_centisecs" no longer used */
149 { CTL_INT, VM_NR_PDFLUSH_THREADS, "nr_pdflush_threads" },
150 { CTL_INT, VM_OVERCOMMIT_RATIO, "overcommit_ratio" },
151 /* VM_PAGEBUF unused */
152 /* VM_HUGETLB_PAGES "nr_hugepages" no longer used */
153 { CTL_INT, VM_SWAPPINESS, "swappiness" },
154 { CTL_INT, VM_LOWMEM_RESERVE_RATIO, "lowmem_reserve_ratio" },
155 { CTL_INT, VM_MIN_FREE_KBYTES, "min_free_kbytes" },
156 { CTL_INT, VM_MAX_MAP_COUNT, "max_map_count" },
157 { CTL_INT, VM_LAPTOP_MODE, "laptop_mode" },
158 { CTL_INT, VM_BLOCK_DUMP, "block_dump" },
159 { CTL_INT, VM_HUGETLB_GROUP, "hugetlb_shm_group" },
160 { CTL_INT, VM_VFS_CACHE_PRESSURE, "vfs_cache_pressure" },
161 { CTL_INT, VM_LEGACY_VA_LAYOUT, "legacy_va_layout" },
162 /* VM_SWAP_TOKEN_TIMEOUT unused */
163 { CTL_INT, VM_DROP_PAGECACHE, "drop_caches" },
164 { CTL_INT, VM_PERCPU_PAGELIST_FRACTION, "percpu_pagelist_fraction" },
165 { CTL_INT, VM_ZONE_RECLAIM_MODE, "zone_reclaim_mode" },
166 { CTL_INT, VM_MIN_UNMAPPED, "min_unmapped_ratio" },
167 { CTL_INT, VM_PANIC_ON_OOM, "panic_on_oom" },
168 { CTL_INT, VM_VDSO_ENABLED, "vdso_enabled" },
169 { CTL_INT, VM_MIN_SLAB, "min_slab_ratio" },
170
171 {}
172};
173
174static const struct bin_table bin_net_core_table[] = {
175 { CTL_INT, NET_CORE_WMEM_MAX, "wmem_max" },
176 { CTL_INT, NET_CORE_RMEM_MAX, "rmem_max" },
177 { CTL_INT, NET_CORE_WMEM_DEFAULT, "wmem_default" },
178 { CTL_INT, NET_CORE_RMEM_DEFAULT, "rmem_default" },
179 /* NET_CORE_DESTROY_DELAY unused */
180 { CTL_INT, NET_CORE_MAX_BACKLOG, "netdev_max_backlog" },
181 /* NET_CORE_FASTROUTE unused */
182 { CTL_INT, NET_CORE_MSG_COST, "message_cost" },
183 { CTL_INT, NET_CORE_MSG_BURST, "message_burst" },
184 { CTL_INT, NET_CORE_OPTMEM_MAX, "optmem_max" },
185 /* NET_CORE_HOT_LIST_LENGTH unused */
186 /* NET_CORE_DIVERT_VERSION unused */
187 /* NET_CORE_NO_CONG_THRESH unused */
188 /* NET_CORE_NO_CONG unused */
189 /* NET_CORE_LO_CONG unused */
190 /* NET_CORE_MOD_CONG unused */
191 { CTL_INT, NET_CORE_DEV_WEIGHT, "dev_weight" },
192 { CTL_INT, NET_CORE_SOMAXCONN, "somaxconn" },
193 { CTL_INT, NET_CORE_BUDGET, "netdev_budget" },
194 { CTL_INT, NET_CORE_AEVENT_ETIME, "xfrm_aevent_etime" },
195 { CTL_INT, NET_CORE_AEVENT_RSEQTH, "xfrm_aevent_rseqth" },
196 { CTL_INT, NET_CORE_WARNINGS, "warnings" },
197 {},
198};
199
200static const struct bin_table bin_net_unix_table[] = {
201 /* NET_UNIX_DESTROY_DELAY unused */
202 /* NET_UNIX_DELETE_DELAY unused */
203 { CTL_INT, NET_UNIX_MAX_DGRAM_QLEN, "max_dgram_qlen" },
204 {}
205};
206
207static const struct bin_table bin_net_ipv4_route_table[] = {
208 { CTL_INT, NET_IPV4_ROUTE_FLUSH, "flush" },
209 /* NET_IPV4_ROUTE_MIN_DELAY "min_delay" no longer used */
210 /* NET_IPV4_ROUTE_MAX_DELAY "max_delay" no longer used */
211 { CTL_INT, NET_IPV4_ROUTE_GC_THRESH, "gc_thresh" },
212 { CTL_INT, NET_IPV4_ROUTE_MAX_SIZE, "max_size" },
213 { CTL_INT, NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
214 { CTL_INT, NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
215 { CTL_INT, NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout" },
216 { CTL_INT, NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval" },
217 { CTL_INT, NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load" },
218 { CTL_INT, NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number" },
219 { CTL_INT, NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence" },
220 { CTL_INT, NET_IPV4_ROUTE_ERROR_COST, "error_cost" },
221 { CTL_INT, NET_IPV4_ROUTE_ERROR_BURST, "error_burst" },
222 { CTL_INT, NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity" },
223 { CTL_INT, NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires" },
224 { CTL_INT, NET_IPV4_ROUTE_MIN_PMTU, "min_pmtu" },
225 { CTL_INT, NET_IPV4_ROUTE_MIN_ADVMSS, "min_adv_mss" },
226 { CTL_INT, NET_IPV4_ROUTE_SECRET_INTERVAL, "secret_interval" },
227 {}
228};
229
230static const struct bin_table bin_net_ipv4_conf_vars_table[] = {
231 { CTL_INT, NET_IPV4_CONF_FORWARDING, "forwarding" },
232 { CTL_INT, NET_IPV4_CONF_MC_FORWARDING, "mc_forwarding" },
233
234 { CTL_INT, NET_IPV4_CONF_ACCEPT_REDIRECTS, "accept_redirects" },
235 { CTL_INT, NET_IPV4_CONF_SECURE_REDIRECTS, "secure_redirects" },
236 { CTL_INT, NET_IPV4_CONF_SEND_REDIRECTS, "send_redirects" },
237 { CTL_INT, NET_IPV4_CONF_SHARED_MEDIA, "shared_media" },
238 { CTL_INT, NET_IPV4_CONF_RP_FILTER, "rp_filter" },
239 { CTL_INT, NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
240 { CTL_INT, NET_IPV4_CONF_PROXY_ARP, "proxy_arp" },
241 { CTL_INT, NET_IPV4_CONF_MEDIUM_ID, "medium_id" },
242 { CTL_INT, NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay" },
243 { CTL_INT, NET_IPV4_CONF_LOG_MARTIANS, "log_martians" },
244 { CTL_INT, NET_IPV4_CONF_TAG, "tag" },
245 { CTL_INT, NET_IPV4_CONF_ARPFILTER, "arp_filter" },
246 { CTL_INT, NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce" },
247 { CTL_INT, NET_IPV4_CONF_ARP_IGNORE, "arp_ignore" },
248 { CTL_INT, NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" },
249 { CTL_INT, NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" },
250
251 { CTL_INT, NET_IPV4_CONF_NOXFRM, "disable_xfrm" },
252 { CTL_INT, NET_IPV4_CONF_NOPOLICY, "disable_policy" },
253 { CTL_INT, NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version" },
254 { CTL_INT, NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" },
255 {}
256};
257
258static const struct bin_table bin_net_ipv4_conf_table[] = {
259 { CTL_DIR, NET_PROTO_CONF_ALL, "all", bin_net_ipv4_conf_vars_table },
260 { CTL_DIR, NET_PROTO_CONF_DEFAULT, "default", bin_net_ipv4_conf_vars_table },
261 { CTL_DIR, 0, NULL, bin_net_ipv4_conf_vars_table },
262 {}
263};
264
265static const struct bin_table bin_net_neigh_vars_table[] = {
266 { CTL_INT, NET_NEIGH_MCAST_SOLICIT, "mcast_solicit" },
267 { CTL_INT, NET_NEIGH_UCAST_SOLICIT, "ucast_solicit" },
268 { CTL_INT, NET_NEIGH_APP_SOLICIT, "app_solicit" },
269 /* NET_NEIGH_RETRANS_TIME "retrans_time" no longer used */
270 { CTL_INT, NET_NEIGH_REACHABLE_TIME, "base_reachable_time" },
271 { CTL_INT, NET_NEIGH_DELAY_PROBE_TIME, "delay_first_probe_time" },
272 { CTL_INT, NET_NEIGH_GC_STALE_TIME, "gc_stale_time" },
273 { CTL_INT, NET_NEIGH_UNRES_QLEN, "unres_qlen" },
274 { CTL_INT, NET_NEIGH_PROXY_QLEN, "proxy_qlen" },
275 /* NET_NEIGH_ANYCAST_DELAY "anycast_delay" no longer used */
276 /* NET_NEIGH_PROXY_DELAY "proxy_delay" no longer used */
277 /* NET_NEIGH_LOCKTIME "locktime" no longer used */
278 { CTL_INT, NET_NEIGH_GC_INTERVAL, "gc_interval" },
279 { CTL_INT, NET_NEIGH_GC_THRESH1, "gc_thresh1" },
280 { CTL_INT, NET_NEIGH_GC_THRESH2, "gc_thresh2" },
281 { CTL_INT, NET_NEIGH_GC_THRESH3, "gc_thresh3" },
282 { CTL_INT, NET_NEIGH_RETRANS_TIME_MS, "retrans_time_ms" },
283 { CTL_INT, NET_NEIGH_REACHABLE_TIME_MS, "base_reachable_time_ms" },
284 {}
285};
286
287static const struct bin_table bin_net_neigh_table[] = {
288 { CTL_DIR, NET_PROTO_CONF_DEFAULT, "default", bin_net_neigh_vars_table },
289 { CTL_DIR, 0, NULL, bin_net_neigh_vars_table },
290 {}
291};
292
293static const struct bin_table bin_net_ipv4_netfilter_table[] = {
294 { CTL_INT, NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max" },
295
296 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT "ip_conntrack_tcp_timeout_syn_sent" no longer used */
297 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV "ip_conntrack_tcp_timeout_syn_recv" no longer used */
298 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED "ip_conntrack_tcp_timeout_established" no longer used */
299 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT "ip_conntrack_tcp_timeout_fin_wait" no longer used */
300 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT "ip_conntrack_tcp_timeout_close_wait" no longer used */
301 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK "ip_conntrack_tcp_timeout_last_ack" no longer used */
302 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT "ip_conntrack_tcp_timeout_time_wait" no longer used */
303 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE "ip_conntrack_tcp_timeout_close" no longer used */
304
305 /* NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT "ip_conntrack_udp_timeout" no longer used */
306 /* NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM "ip_conntrack_udp_timeout_stream" no longer used */
307 /* NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT "ip_conntrack_icmp_timeout" no longer used */
308 /* NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT "ip_conntrack_generic_timeout" no longer used */
309
310 { CTL_INT, NET_IPV4_NF_CONNTRACK_BUCKETS, "ip_conntrack_buckets" },
311 { CTL_INT, NET_IPV4_NF_CONNTRACK_LOG_INVALID, "ip_conntrack_log_invalid" },
312 /* NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS "ip_conntrack_tcp_timeout_max_retrans" no longer used */
313 { CTL_INT, NET_IPV4_NF_CONNTRACK_TCP_LOOSE, "ip_conntrack_tcp_loose" },
314 { CTL_INT, NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, "ip_conntrack_tcp_be_liberal" },
315 { CTL_INT, NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, "ip_conntrack_tcp_max_retrans" },
316
317 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED "ip_conntrack_sctp_timeout_closed" no longer used */
318 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT "ip_conntrack_sctp_timeout_cookie_wait" no longer used */
319 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED "ip_conntrack_sctp_timeout_cookie_echoed" no longer used */
320 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED "ip_conntrack_sctp_timeout_established" no longer used */
321 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT "ip_conntrack_sctp_timeout_shutdown_sent" no longer used */
322 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD "ip_conntrack_sctp_timeout_shutdown_recd" no longer used */
323 /* NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT "ip_conntrack_sctp_timeout_shutdown_ack_sent" no longer used */
324
325 { CTL_INT, NET_IPV4_NF_CONNTRACK_COUNT, "ip_conntrack_count" },
326 { CTL_INT, NET_IPV4_NF_CONNTRACK_CHECKSUM, "ip_conntrack_checksum" },
327 {}
328};
329
330static const struct bin_table bin_net_ipv4_table[] = {
331 {CTL_INT, NET_IPV4_FORWARD, "ip_forward" },
332
333 { CTL_DIR, NET_IPV4_CONF, "conf", bin_net_ipv4_conf_table },
334 { CTL_DIR, NET_IPV4_NEIGH, "neigh", bin_net_neigh_table },
335 { CTL_DIR, NET_IPV4_ROUTE, "route", bin_net_ipv4_route_table },
336 /* NET_IPV4_FIB_HASH unused */
337 { CTL_DIR, NET_IPV4_NETFILTER, "netfilter", bin_net_ipv4_netfilter_table },
338
339 { CTL_INT, NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps" },
340 { CTL_INT, NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling" },
341 { CTL_INT, NET_IPV4_TCP_SACK, "tcp_sack" },
342 { CTL_INT, NET_IPV4_TCP_RETRANS_COLLAPSE, "tcp_retrans_collapse" },
343 { CTL_INT, NET_IPV4_DEFAULT_TTL, "ip_default_ttl" },
344 /* NET_IPV4_AUTOCONFIG unused */
345 { CTL_INT, NET_IPV4_NO_PMTU_DISC, "ip_no_pmtu_disc" },
346 { CTL_INT, NET_IPV4_NONLOCAL_BIND, "ip_nonlocal_bind" },
347 { CTL_INT, NET_IPV4_TCP_SYN_RETRIES, "tcp_syn_retries" },
348 { CTL_INT, NET_TCP_SYNACK_RETRIES, "tcp_synack_retries" },
349 { CTL_INT, NET_TCP_MAX_ORPHANS, "tcp_max_orphans" },
350 { CTL_INT, NET_TCP_MAX_TW_BUCKETS, "tcp_max_tw_buckets" },
351 { CTL_INT, NET_IPV4_DYNADDR, "ip_dynaddr" },
352 { CTL_INT, NET_IPV4_TCP_KEEPALIVE_TIME, "tcp_keepalive_time" },
353 { CTL_INT, NET_IPV4_TCP_KEEPALIVE_PROBES, "tcp_keepalive_probes" },
354 { CTL_INT, NET_IPV4_TCP_KEEPALIVE_INTVL, "tcp_keepalive_intvl" },
355 { CTL_INT, NET_IPV4_TCP_RETRIES1, "tcp_retries1" },
356 { CTL_INT, NET_IPV4_TCP_RETRIES2, "tcp_retries2" },
357 { CTL_INT, NET_IPV4_TCP_FIN_TIMEOUT, "tcp_fin_timeout" },
358 { CTL_INT, NET_TCP_SYNCOOKIES, "tcp_syncookies" },
359 { CTL_INT, NET_TCP_TW_RECYCLE, "tcp_tw_recycle" },
360 { CTL_INT, NET_TCP_ABORT_ON_OVERFLOW, "tcp_abort_on_overflow" },
361 { CTL_INT, NET_TCP_STDURG, "tcp_stdurg" },
362 { CTL_INT, NET_TCP_RFC1337, "tcp_rfc1337" },
363 { CTL_INT, NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog" },
364 { CTL_INT, NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range" },
365 { CTL_INT, NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships" },
366 { CTL_INT, NET_IPV4_IGMP_MAX_MSF, "igmp_max_msf" },
367 { CTL_INT, NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold" },
368 { CTL_INT, NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl" },
369 { CTL_INT, NET_IPV4_INET_PEER_MAXTTL, "inet_peer_maxttl" },
370 { CTL_INT, NET_IPV4_INET_PEER_GC_MINTIME, "inet_peer_gc_mintime" },
371 { CTL_INT, NET_IPV4_INET_PEER_GC_MAXTIME, "inet_peer_gc_maxtime" },
372 { CTL_INT, NET_TCP_ORPHAN_RETRIES, "tcp_orphan_retries" },
373 { CTL_INT, NET_TCP_FACK, "tcp_fack" },
374 { CTL_INT, NET_TCP_REORDERING, "tcp_reordering" },
375 { CTL_INT, NET_TCP_ECN, "tcp_ecn" },
376 { CTL_INT, NET_TCP_DSACK, "tcp_dsack" },
377 { CTL_INT, NET_TCP_MEM, "tcp_mem" },
378 { CTL_INT, NET_TCP_WMEM, "tcp_wmem" },
379 { CTL_INT, NET_TCP_RMEM, "tcp_rmem" },
380 { CTL_INT, NET_TCP_APP_WIN, "tcp_app_win" },
381 { CTL_INT, NET_TCP_ADV_WIN_SCALE, "tcp_adv_win_scale" },
382 { CTL_INT, NET_TCP_TW_REUSE, "tcp_tw_reuse" },
383 { CTL_INT, NET_TCP_FRTO, "tcp_frto" },
384 { CTL_INT, NET_TCP_FRTO_RESPONSE, "tcp_frto_response" },
385 { CTL_INT, NET_TCP_LOW_LATENCY, "tcp_low_latency" },
386 { CTL_INT, NET_TCP_NO_METRICS_SAVE, "tcp_no_metrics_save" },
387 { CTL_INT, NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf" },
388 { CTL_INT, NET_TCP_TSO_WIN_DIVISOR, "tcp_tso_win_divisor" },
389 { CTL_STR, NET_TCP_CONG_CONTROL, "tcp_congestion_control" },
390 { CTL_INT, NET_TCP_ABC, "tcp_abc" },
391 { CTL_INT, NET_TCP_MTU_PROBING, "tcp_mtu_probing" },
392 { CTL_INT, NET_TCP_BASE_MSS, "tcp_base_mss" },
393 { CTL_INT, NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS, "tcp_workaround_signed_windows" },
394 { CTL_INT, NET_TCP_DMA_COPYBREAK, "tcp_dma_copybreak" },
395 { CTL_INT, NET_TCP_SLOW_START_AFTER_IDLE, "tcp_slow_start_after_idle" },
396 { CTL_INT, NET_CIPSOV4_CACHE_ENABLE, "cipso_cache_enable" },
397 { CTL_INT, NET_CIPSOV4_CACHE_BUCKET_SIZE, "cipso_cache_bucket_size" },
398 { CTL_INT, NET_CIPSOV4_RBM_OPTFMT, "cipso_rbm_optfmt" },
399 { CTL_INT, NET_CIPSOV4_RBM_STRICTVALID, "cipso_rbm_strictvalid" },
400 /* NET_TCP_AVAIL_CONG_CONTROL "tcp_available_congestion_control" no longer used */
401 { CTL_STR, NET_TCP_ALLOWED_CONG_CONTROL, "tcp_allowed_congestion_control" },
402 { CTL_INT, NET_TCP_MAX_SSTHRESH, "tcp_max_ssthresh" },
403
404 { CTL_INT, NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all" },
405 { CTL_INT, NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, "icmp_echo_ignore_broadcasts" },
406 { CTL_INT, NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses" },
407 { CTL_INT, NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR, "icmp_errors_use_inbound_ifaddr" },
408 { CTL_INT, NET_IPV4_ICMP_RATELIMIT, "icmp_ratelimit" },
409 { CTL_INT, NET_IPV4_ICMP_RATEMASK, "icmp_ratemask" },
410
411 { CTL_INT, NET_IPV4_IPFRAG_HIGH_THRESH, "ipfrag_high_thresh" },
412 { CTL_INT, NET_IPV4_IPFRAG_LOW_THRESH, "ipfrag_low_thresh" },
413 { CTL_INT, NET_IPV4_IPFRAG_TIME, "ipfrag_time" },
414
415 { CTL_INT, NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval" },
416 /* NET_IPV4_IPFRAG_MAX_DIST "ipfrag_max_dist" no longer used */
417
418 { CTL_INT, 2088 /* NET_IPQ_QMAX */, "ip_queue_maxlen" },
419
420 /* NET_TCP_DEFAULT_WIN_SCALE unused */
421 /* NET_TCP_BIC_BETA unused */
422 /* NET_IPV4_TCP_MAX_KA_PROBES unused */
423 /* NET_IPV4_IP_MASQ_DEBUG unused */
424 /* NET_TCP_SYN_TAILDROP unused */
425 /* NET_IPV4_ICMP_SOURCEQUENCH_RATE unused */
426 /* NET_IPV4_ICMP_DESTUNREACH_RATE unused */
427 /* NET_IPV4_ICMP_TIMEEXCEED_RATE unused */
428 /* NET_IPV4_ICMP_PARAMPROB_RATE unused */
429 /* NET_IPV4_ICMP_ECHOREPLY_RATE unused */
430 /* NET_IPV4_ALWAYS_DEFRAG unused */
431 {}
432};
433
434static const struct bin_table bin_net_ipx_table[] = {
435 { CTL_INT, NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting" },
436 /* NET_IPX_FORWARDING unused */
437 {}
438};
439
440static const struct bin_table bin_net_atalk_table[] = {
441 { CTL_INT, NET_ATALK_AARP_EXPIRY_TIME, "aarp-expiry-time" },
442 { CTL_INT, NET_ATALK_AARP_TICK_TIME, "aarp-tick-time" },
443 { CTL_INT, NET_ATALK_AARP_RETRANSMIT_LIMIT, "aarp-retransmit-limit" },
444 { CTL_INT, NET_ATALK_AARP_RESOLVE_TIME, "aarp-resolve-time" },
445 {},
446};
447
448static const struct bin_table bin_net_netrom_table[] = {
449 { CTL_INT, NET_NETROM_DEFAULT_PATH_QUALITY, "default_path_quality" },
450 { CTL_INT, NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER, "obsolescence_count_initialiser" },
451 { CTL_INT, NET_NETROM_NETWORK_TTL_INITIALISER, "network_ttl_initialiser" },
452 { CTL_INT, NET_NETROM_TRANSPORT_TIMEOUT, "transport_timeout" },
453 { CTL_INT, NET_NETROM_TRANSPORT_MAXIMUM_TRIES, "transport_maximum_tries" },
454 { CTL_INT, NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY, "transport_acknowledge_delay" },
455 { CTL_INT, NET_NETROM_TRANSPORT_BUSY_DELAY, "transport_busy_delay" },
456 { CTL_INT, NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE, "transport_requested_window_size" },
457 { CTL_INT, NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT, "transport_no_activity_timeout" },
458 { CTL_INT, NET_NETROM_ROUTING_CONTROL, "routing_control" },
459 { CTL_INT, NET_NETROM_LINK_FAILS_COUNT, "link_fails_count" },
460 { CTL_INT, NET_NETROM_RESET, "reset" },
461 {}
462};
463
464static const struct bin_table bin_net_ax25_param_table[] = {
465 { CTL_INT, NET_AX25_IP_DEFAULT_MODE, "ip_default_mode" },
466 { CTL_INT, NET_AX25_DEFAULT_MODE, "ax25_default_mode" },
467 { CTL_INT, NET_AX25_BACKOFF_TYPE, "backoff_type" },
468 { CTL_INT, NET_AX25_CONNECT_MODE, "connect_mode" },
469 { CTL_INT, NET_AX25_STANDARD_WINDOW, "standard_window_size" },
470 { CTL_INT, NET_AX25_EXTENDED_WINDOW, "extended_window_size" },
471 { CTL_INT, NET_AX25_T1_TIMEOUT, "t1_timeout" },
472 { CTL_INT, NET_AX25_T2_TIMEOUT, "t2_timeout" },
473 { CTL_INT, NET_AX25_T3_TIMEOUT, "t3_timeout" },
474 { CTL_INT, NET_AX25_IDLE_TIMEOUT, "idle_timeout" },
475 { CTL_INT, NET_AX25_N2, "maximum_retry_count" },
476 { CTL_INT, NET_AX25_PACLEN, "maximum_packet_length" },
477 { CTL_INT, NET_AX25_PROTOCOL, "protocol" },
478 { CTL_INT, NET_AX25_DAMA_SLAVE_TIMEOUT, "dama_slave_timeout" },
479 {}
480};
481
482static const struct bin_table bin_net_ax25_table[] = {
483 { CTL_DIR, 0, NULL, bin_net_ax25_param_table },
484 {}
485};
486
487static const struct bin_table bin_net_rose_table[] = {
488 { CTL_INT, NET_ROSE_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
489 { CTL_INT, NET_ROSE_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
490 { CTL_INT, NET_ROSE_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
491 { CTL_INT, NET_ROSE_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
492 { CTL_INT, NET_ROSE_ACK_HOLD_BACK_TIMEOUT, "acknowledge_hold_back_timeout" },
493 { CTL_INT, NET_ROSE_ROUTING_CONTROL, "routing_control" },
494 { CTL_INT, NET_ROSE_LINK_FAIL_TIMEOUT, "link_fail_timeout" },
495 { CTL_INT, NET_ROSE_MAX_VCS, "maximum_virtual_circuits" },
496 { CTL_INT, NET_ROSE_WINDOW_SIZE, "window_size" },
497 { CTL_INT, NET_ROSE_NO_ACTIVITY_TIMEOUT, "no_activity_timeout" },
498 {}
499};
500
501static const struct bin_table bin_net_ipv6_conf_var_table[] = {
502 { CTL_INT, NET_IPV6_FORWARDING, "forwarding" },
503 { CTL_INT, NET_IPV6_HOP_LIMIT, "hop_limit" },
504 { CTL_INT, NET_IPV6_MTU, "mtu" },
505 { CTL_INT, NET_IPV6_ACCEPT_RA, "accept_ra" },
506 { CTL_INT, NET_IPV6_ACCEPT_REDIRECTS, "accept_redirects" },
507 { CTL_INT, NET_IPV6_AUTOCONF, "autoconf" },
508 { CTL_INT, NET_IPV6_DAD_TRANSMITS, "dad_transmits" },
509 { CTL_INT, NET_IPV6_RTR_SOLICITS, "router_solicitations" },
510 { CTL_INT, NET_IPV6_RTR_SOLICIT_INTERVAL, "router_solicitation_interval" },
511 { CTL_INT, NET_IPV6_RTR_SOLICIT_DELAY, "router_solicitation_delay" },
512 { CTL_INT, NET_IPV6_USE_TEMPADDR, "use_tempaddr" },
513 { CTL_INT, NET_IPV6_TEMP_VALID_LFT, "temp_valid_lft" },
514 { CTL_INT, NET_IPV6_TEMP_PREFERED_LFT, "temp_prefered_lft" },
515 { CTL_INT, NET_IPV6_REGEN_MAX_RETRY, "regen_max_retry" },
516 { CTL_INT, NET_IPV6_MAX_DESYNC_FACTOR, "max_desync_factor" },
517 { CTL_INT, NET_IPV6_MAX_ADDRESSES, "max_addresses" },
518 { CTL_INT, NET_IPV6_FORCE_MLD_VERSION, "force_mld_version" },
519 { CTL_INT, NET_IPV6_ACCEPT_RA_DEFRTR, "accept_ra_defrtr" },
520 { CTL_INT, NET_IPV6_ACCEPT_RA_PINFO, "accept_ra_pinfo" },
521 { CTL_INT, NET_IPV6_ACCEPT_RA_RTR_PREF, "accept_ra_rtr_pref" },
522 { CTL_INT, NET_IPV6_RTR_PROBE_INTERVAL, "router_probe_interval" },
523 { CTL_INT, NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" },
524 { CTL_INT, NET_IPV6_PROXY_NDP, "proxy_ndp" },
525 { CTL_INT, NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
526 {}
527};
528
529static const struct bin_table bin_net_ipv6_conf_table[] = {
530 { CTL_DIR, NET_PROTO_CONF_ALL, "all", bin_net_ipv6_conf_var_table },
531 { CTL_DIR, NET_PROTO_CONF_DEFAULT, "default", bin_net_ipv6_conf_var_table },
532 { CTL_DIR, 0, NULL, bin_net_ipv6_conf_var_table },
533 {}
534};
535
536static const struct bin_table bin_net_ipv6_route_table[] = {
537 /* NET_IPV6_ROUTE_FLUSH "flush" no longer used */
538 { CTL_INT, NET_IPV6_ROUTE_GC_THRESH, "gc_thresh" },
539 { CTL_INT, NET_IPV6_ROUTE_MAX_SIZE, "max_size" },
540 { CTL_INT, NET_IPV6_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
541 { CTL_INT, NET_IPV6_ROUTE_GC_TIMEOUT, "gc_timeout" },
542 { CTL_INT, NET_IPV6_ROUTE_GC_INTERVAL, "gc_interval" },
543 { CTL_INT, NET_IPV6_ROUTE_GC_ELASTICITY, "gc_elasticity" },
544 { CTL_INT, NET_IPV6_ROUTE_MTU_EXPIRES, "mtu_expires" },
545 { CTL_INT, NET_IPV6_ROUTE_MIN_ADVMSS, "min_adv_mss" },
546 { CTL_INT, NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
547 {}
548};
549
550static const struct bin_table bin_net_ipv6_icmp_table[] = {
551 { CTL_INT, NET_IPV6_ICMP_RATELIMIT, "ratelimit" },
552 {}
553};
554
555static const struct bin_table bin_net_ipv6_table[] = {
556 { CTL_DIR, NET_IPV6_CONF, "conf", bin_net_ipv6_conf_table },
557 { CTL_DIR, NET_IPV6_NEIGH, "neigh", bin_net_neigh_table },
558 { CTL_DIR, NET_IPV6_ROUTE, "route", bin_net_ipv6_route_table },
559 { CTL_DIR, NET_IPV6_ICMP, "icmp", bin_net_ipv6_icmp_table },
560 { CTL_INT, NET_IPV6_BINDV6ONLY, "bindv6only" },
561 { CTL_INT, NET_IPV6_IP6FRAG_HIGH_THRESH, "ip6frag_high_thresh" },
562 { CTL_INT, NET_IPV6_IP6FRAG_LOW_THRESH, "ip6frag_low_thresh" },
563 { CTL_INT, NET_IPV6_IP6FRAG_TIME, "ip6frag_time" },
564 { CTL_INT, NET_IPV6_IP6FRAG_SECRET_INTERVAL, "ip6frag_secret_interval" },
565 { CTL_INT, NET_IPV6_MLD_MAX_MSF, "mld_max_msf" },
566 { CTL_INT, 2088 /* IPQ_QMAX */, "ip6_queue_maxlen" },
567 {}
568};
569
570static const struct bin_table bin_net_x25_table[] = {
571 { CTL_INT, NET_X25_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
572 { CTL_INT, NET_X25_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
573 { CTL_INT, NET_X25_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
574 { CTL_INT, NET_X25_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
575 { CTL_INT, NET_X25_ACK_HOLD_BACK_TIMEOUT, "acknowledgement_hold_back_timeout" },
576 { CTL_INT, NET_X25_FORWARD, "x25_forward" },
577 {}
578};
579
580static const struct bin_table bin_net_tr_table[] = {
581 { CTL_INT, NET_TR_RIF_TIMEOUT, "rif_timeout" },
582 {}
583};
584
585
586static const struct bin_table bin_net_decnet_conf_vars[] = {
587 { CTL_INT, NET_DECNET_CONF_DEV_FORWARDING, "forwarding" },
588 { CTL_INT, NET_DECNET_CONF_DEV_PRIORITY, "priority" },
589 { CTL_INT, NET_DECNET_CONF_DEV_T2, "t2" },
590 { CTL_INT, NET_DECNET_CONF_DEV_T3, "t3" },
591 {}
592};
593
594static const struct bin_table bin_net_decnet_conf[] = {
595 { CTL_DIR, NET_DECNET_CONF_ETHER, "ethernet", bin_net_decnet_conf_vars },
596 { CTL_DIR, NET_DECNET_CONF_GRE, "ipgre", bin_net_decnet_conf_vars },
597 { CTL_DIR, NET_DECNET_CONF_X25, "x25", bin_net_decnet_conf_vars },
598 { CTL_DIR, NET_DECNET_CONF_PPP, "ppp", bin_net_decnet_conf_vars },
599 { CTL_DIR, NET_DECNET_CONF_DDCMP, "ddcmp", bin_net_decnet_conf_vars },
600 { CTL_DIR, NET_DECNET_CONF_LOOPBACK, "loopback", bin_net_decnet_conf_vars },
601 { CTL_DIR, 0, NULL, bin_net_decnet_conf_vars },
602 {}
603};
604
605static const struct bin_table bin_net_decnet_table[] = {
606 { CTL_DIR, NET_DECNET_CONF, "conf", bin_net_decnet_conf },
607 { CTL_DNADR, NET_DECNET_NODE_ADDRESS, "node_address" },
608 { CTL_STR, NET_DECNET_NODE_NAME, "node_name" },
609 { CTL_STR, NET_DECNET_DEFAULT_DEVICE, "default_device" },
610 { CTL_INT, NET_DECNET_TIME_WAIT, "time_wait" },
611 { CTL_INT, NET_DECNET_DN_COUNT, "dn_count" },
612 { CTL_INT, NET_DECNET_DI_COUNT, "di_count" },
613 { CTL_INT, NET_DECNET_DR_COUNT, "dr_count" },
614 { CTL_INT, NET_DECNET_DST_GC_INTERVAL, "dst_gc_interval" },
615 { CTL_INT, NET_DECNET_NO_FC_MAX_CWND, "no_fc_max_cwnd" },
616 { CTL_INT, NET_DECNET_MEM, "decnet_mem" },
617 { CTL_INT, NET_DECNET_RMEM, "decnet_rmem" },
618 { CTL_INT, NET_DECNET_WMEM, "decnet_wmem" },
619 { CTL_INT, NET_DECNET_DEBUG_LEVEL, "debug" },
620 {}
621};
622
623static const struct bin_table bin_net_sctp_table[] = {
624 { CTL_INT, NET_SCTP_RTO_INITIAL, "rto_initial" },
625 { CTL_INT, NET_SCTP_RTO_MIN, "rto_min" },
626 { CTL_INT, NET_SCTP_RTO_MAX, "rto_max" },
627 { CTL_INT, NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor" },
628 { CTL_INT, NET_SCTP_RTO_BETA, "rto_beta_exp_divisor" },
629 { CTL_INT, NET_SCTP_VALID_COOKIE_LIFE, "valid_cookie_life" },
630 { CTL_INT, NET_SCTP_ASSOCIATION_MAX_RETRANS, "association_max_retrans" },
631 { CTL_INT, NET_SCTP_PATH_MAX_RETRANS, "path_max_retrans" },
632 { CTL_INT, NET_SCTP_MAX_INIT_RETRANSMITS, "max_init_retransmits" },
633 { CTL_INT, NET_SCTP_HB_INTERVAL, "hb_interval" },
634 { CTL_INT, NET_SCTP_PRESERVE_ENABLE, "cookie_preserve_enable" },
635 { CTL_INT, NET_SCTP_MAX_BURST, "max_burst" },
636 { CTL_INT, NET_SCTP_ADDIP_ENABLE, "addip_enable" },
637 { CTL_INT, NET_SCTP_PRSCTP_ENABLE, "prsctp_enable" },
638 { CTL_INT, NET_SCTP_SNDBUF_POLICY, "sndbuf_policy" },
639 { CTL_INT, NET_SCTP_SACK_TIMEOUT, "sack_timeout" },
640 { CTL_INT, NET_SCTP_RCVBUF_POLICY, "rcvbuf_policy" },
641 {}
642};
643
644static const struct bin_table bin_net_llc_llc2_timeout_table[] = {
645 { CTL_INT, NET_LLC2_ACK_TIMEOUT, "ack" },
646 { CTL_INT, NET_LLC2_P_TIMEOUT, "p" },
647 { CTL_INT, NET_LLC2_REJ_TIMEOUT, "rej" },
648 { CTL_INT, NET_LLC2_BUSY_TIMEOUT, "busy" },
649 {}
650};
651
652static const struct bin_table bin_net_llc_station_table[] = {
653 { CTL_INT, NET_LLC_STATION_ACK_TIMEOUT, "ack_timeout" },
654 {}
655};
656
657static const struct bin_table bin_net_llc_llc2_table[] = {
658 { CTL_DIR, NET_LLC2, "timeout", bin_net_llc_llc2_timeout_table },
659 {}
660};
661
662static const struct bin_table bin_net_llc_table[] = {
663 { CTL_DIR, NET_LLC2, "llc2", bin_net_llc_llc2_table },
664 { CTL_DIR, NET_LLC_STATION, "station", bin_net_llc_station_table },
665 {}
666};
667
668static const struct bin_table bin_net_netfilter_table[] = {
669 { CTL_INT, NET_NF_CONNTRACK_MAX, "nf_conntrack_max" },
670 /* NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT "nf_conntrack_tcp_timeout_syn_sent" no longer used */
671 /* NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV "nf_conntrack_tcp_timeout_syn_recv" no longer used */
672 /* NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED "nf_conntrack_tcp_timeout_established" no longer used */
673 /* NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT "nf_conntrack_tcp_timeout_fin_wait" no longer used */
674 /* NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT "nf_conntrack_tcp_timeout_close_wait" no longer used */
675 /* NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK "nf_conntrack_tcp_timeout_last_ack" no longer used */
676 /* NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT "nf_conntrack_tcp_timeout_time_wait" no longer used */
677 /* NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE "nf_conntrack_tcp_timeout_close" no longer used */
678 /* NET_NF_CONNTRACK_UDP_TIMEOUT "nf_conntrack_udp_timeout" no longer used */
679 /* NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM "nf_conntrack_udp_timeout_stream" no longer used */
680 /* NET_NF_CONNTRACK_ICMP_TIMEOUT "nf_conntrack_icmp_timeout" no longer used */
681 /* NET_NF_CONNTRACK_GENERIC_TIMEOUT "nf_conntrack_generic_timeout" no longer used */
682 { CTL_INT, NET_NF_CONNTRACK_BUCKETS, "nf_conntrack_buckets" },
683 { CTL_INT, NET_NF_CONNTRACK_LOG_INVALID, "nf_conntrack_log_invalid" },
684 /* NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS "nf_conntrack_tcp_timeout_max_retrans" no longer used */
685 { CTL_INT, NET_NF_CONNTRACK_TCP_LOOSE, "nf_conntrack_tcp_loose" },
686 { CTL_INT, NET_NF_CONNTRACK_TCP_BE_LIBERAL, "nf_conntrack_tcp_be_liberal" },
687 { CTL_INT, NET_NF_CONNTRACK_TCP_MAX_RETRANS, "nf_conntrack_tcp_max_retrans" },
688 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED "nf_conntrack_sctp_timeout_closed" no longer used */
689 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT "nf_conntrack_sctp_timeout_cookie_wait" no longer used */
690 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED "nf_conntrack_sctp_timeout_cookie_echoed" no longer used */
691 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED "nf_conntrack_sctp_timeout_established" no longer used */
692 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT "nf_conntrack_sctp_timeout_shutdown_sent" no longer used */
693 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD "nf_conntrack_sctp_timeout_shutdown_recd" no longer used */
694 /* NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT "nf_conntrack_sctp_timeout_shutdown_ack_sent" no longer used */
695 { CTL_INT, NET_NF_CONNTRACK_COUNT, "nf_conntrack_count" },
696 /* NET_NF_CONNTRACK_ICMPV6_TIMEOUT "nf_conntrack_icmpv6_timeout" no longer used */
697 /* NET_NF_CONNTRACK_FRAG6_TIMEOUT "nf_conntrack_frag6_timeout" no longer used */
698 { CTL_INT, NET_NF_CONNTRACK_FRAG6_LOW_THRESH, "nf_conntrack_frag6_low_thresh" },
699 { CTL_INT, NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, "nf_conntrack_frag6_high_thresh" },
700 { CTL_INT, NET_NF_CONNTRACK_CHECKSUM, "nf_conntrack_checksum" },
701
702 {}
703};
704
705static const struct bin_table bin_net_irda_table[] = {
706 { CTL_INT, NET_IRDA_DISCOVERY, "discovery" },
707 { CTL_STR, NET_IRDA_DEVNAME, "devname" },
708 { CTL_INT, NET_IRDA_DEBUG, "debug" },
709 { CTL_INT, NET_IRDA_FAST_POLL, "fast_poll_increase" },
710 { CTL_INT, NET_IRDA_DISCOVERY_SLOTS, "discovery_slots" },
711 { CTL_INT, NET_IRDA_DISCOVERY_TIMEOUT, "discovery_timeout" },
712 { CTL_INT, NET_IRDA_SLOT_TIMEOUT, "slot_timeout" },
713 { CTL_INT, NET_IRDA_MAX_BAUD_RATE, "max_baud_rate" },
714 { CTL_INT, NET_IRDA_MIN_TX_TURN_TIME, "min_tx_turn_time" },
715 { CTL_INT, NET_IRDA_MAX_TX_DATA_SIZE, "max_tx_data_size" },
716 { CTL_INT, NET_IRDA_MAX_TX_WINDOW, "max_tx_window" },
717 { CTL_INT, NET_IRDA_MAX_NOREPLY_TIME, "max_noreply_time" },
718 { CTL_INT, NET_IRDA_WARN_NOREPLY_TIME, "warn_noreply_time" },
719 { CTL_INT, NET_IRDA_LAP_KEEPALIVE_TIME, "lap_keepalive_time" },
720 {}
721};
722
723static const struct bin_table bin_net_table[] = {
724 { CTL_DIR, NET_CORE, "core", bin_net_core_table },
725 /* NET_ETHER not used */
726 /* NET_802 not used */
727 { CTL_DIR, NET_UNIX, "unix", bin_net_unix_table },
728 { CTL_DIR, NET_IPV4, "ipv4", bin_net_ipv4_table },
729 { CTL_DIR, NET_IPX, "ipx", bin_net_ipx_table },
730 { CTL_DIR, NET_ATALK, "appletalk", bin_net_atalk_table },
731 { CTL_DIR, NET_NETROM, "netrom", bin_net_netrom_table },
732 { CTL_DIR, NET_AX25, "ax25", bin_net_ax25_table },
733 /* NET_BRIDGE "bridge" no longer used */
734 { CTL_DIR, NET_ROSE, "rose", bin_net_rose_table },
735 { CTL_DIR, NET_IPV6, "ipv6", bin_net_ipv6_table },
736 { CTL_DIR, NET_X25, "x25", bin_net_x25_table },
737 { CTL_DIR, NET_TR, "token-ring", bin_net_tr_table },
738 { CTL_DIR, NET_DECNET, "decnet", bin_net_decnet_table },
739 /* NET_ECONET not used */
740 { CTL_DIR, NET_SCTP, "sctp", bin_net_sctp_table },
741 { CTL_DIR, NET_LLC, "llc", bin_net_llc_table },
742 { CTL_DIR, NET_NETFILTER, "netfilter", bin_net_netfilter_table },
743 /* NET_DCCP "dccp" no longer used */
744 { CTL_DIR, NET_IRDA, "irda", bin_net_irda_table },
745 { CTL_INT, 2089, "nf_conntrack_max" },
746 {}
747};
748
749static const struct bin_table bin_fs_quota_table[] = {
750 { CTL_INT, FS_DQ_LOOKUPS, "lookups" },
751 { CTL_INT, FS_DQ_DROPS, "drops" },
752 { CTL_INT, FS_DQ_READS, "reads" },
753 { CTL_INT, FS_DQ_WRITES, "writes" },
754 { CTL_INT, FS_DQ_CACHE_HITS, "cache_hits" },
755 { CTL_INT, FS_DQ_ALLOCATED, "allocated_dquots" },
756 { CTL_INT, FS_DQ_FREE, "free_dquots" },
757 { CTL_INT, FS_DQ_SYNCS, "syncs" },
758 { CTL_INT, FS_DQ_WARNINGS, "warnings" },
759 {}
760};
761
762static const struct bin_table bin_fs_xfs_table[] = {
763 { CTL_INT, XFS_SGID_INHERIT, "irix_sgid_inherit" },
764 { CTL_INT, XFS_SYMLINK_MODE, "irix_symlink_mode" },
765 { CTL_INT, XFS_PANIC_MASK, "panic_mask" },
766
767 { CTL_INT, XFS_ERRLEVEL, "error_level" },
768 { CTL_INT, XFS_SYNCD_TIMER, "xfssyncd_centisecs" },
769 { CTL_INT, XFS_INHERIT_SYNC, "inherit_sync" },
770 { CTL_INT, XFS_INHERIT_NODUMP, "inherit_nodump" },
771 { CTL_INT, XFS_INHERIT_NOATIME, "inherit_noatime" },
772 { CTL_INT, XFS_BUF_TIMER, "xfsbufd_centisecs" },
773 { CTL_INT, XFS_BUF_AGE, "age_buffer_centisecs" },
774 { CTL_INT, XFS_INHERIT_NOSYM, "inherit_nosymlinks" },
775 { CTL_INT, XFS_ROTORSTEP, "rotorstep" },
776 { CTL_INT, XFS_INHERIT_NODFRG, "inherit_nodefrag" },
777 { CTL_INT, XFS_FILESTREAM_TIMER, "filestream_centisecs" },
778 { CTL_INT, XFS_STATS_CLEAR, "stats_clear" },
779 {}
780};
781
782static const struct bin_table bin_fs_ocfs2_nm_table[] = {
783 { CTL_STR, 1, "hb_ctl_path" },
784 {}
785};
786
787static const struct bin_table bin_fs_ocfs2_table[] = {
788 { CTL_DIR, 1, "nm", bin_fs_ocfs2_nm_table },
789 {}
790};
791
792static const struct bin_table bin_inotify_table[] = {
793 { CTL_INT, INOTIFY_MAX_USER_INSTANCES, "max_user_instances" },
794 { CTL_INT, INOTIFY_MAX_USER_WATCHES, "max_user_watches" },
795 { CTL_INT, INOTIFY_MAX_QUEUED_EVENTS, "max_queued_events" },
796 {}
797};
798
799static const struct bin_table bin_fs_table[] = {
800 { CTL_INT, FS_NRINODE, "inode-nr" },
801 { CTL_INT, FS_STATINODE, "inode-state" },
802 /* FS_MAXINODE unused */
803 /* FS_NRDQUOT unused */
804 /* FS_MAXDQUOT unused */
805 /* FS_NRFILE "file-nr" no longer used */
806 { CTL_INT, FS_MAXFILE, "file-max" },
807 { CTL_INT, FS_DENTRY, "dentry-state" },
808 /* FS_NRSUPER unused */
809 /* FS_MAXUPSER unused */
810 { CTL_INT, FS_OVERFLOWUID, "overflowuid" },
811 { CTL_INT, FS_OVERFLOWGID, "overflowgid" },
812 { CTL_INT, FS_LEASES, "leases-enable" },
813 { CTL_INT, FS_DIR_NOTIFY, "dir-notify-enable" },
814 { CTL_INT, FS_LEASE_TIME, "lease-break-time" },
815 { CTL_DIR, FS_DQSTATS, "quota", bin_fs_quota_table },
816 { CTL_DIR, FS_XFS, "xfs", bin_fs_xfs_table },
817 { CTL_ULONG, FS_AIO_NR, "aio-nr" },
818 { CTL_ULONG, FS_AIO_MAX_NR, "aio-max-nr" },
819 { CTL_DIR, FS_INOTIFY, "inotify", bin_inotify_table },
820 { CTL_DIR, FS_OCFS2, "ocfs2", bin_fs_ocfs2_table },
821 { CTL_INT, KERN_SETUID_DUMPABLE, "suid_dumpable" },
822 {}
823};
824
825static const struct bin_table bin_ipmi_table[] = {
826 { CTL_INT, DEV_IPMI_POWEROFF_POWERCYCLE, "poweroff_powercycle" },
827 {}
828};
829
830static const struct bin_table bin_mac_hid_files[] = {
831 /* DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES unused */
832 /* DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES unused */
833 { CTL_INT, DEV_MAC_HID_MOUSE_BUTTON_EMULATION, "mouse_button_emulation" },
834 { CTL_INT, DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, "mouse_button2_keycode" },
835 { CTL_INT, DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, "mouse_button3_keycode" },
836 /* DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES unused */
837 {}
838};
839
840static const struct bin_table bin_raid_table[] = {
841 { CTL_INT, DEV_RAID_SPEED_LIMIT_MIN, "speed_limit_min" },
842 { CTL_INT, DEV_RAID_SPEED_LIMIT_MAX, "speed_limit_max" },
843 {}
844};
845
846static const struct bin_table bin_scsi_table[] = {
847 { CTL_INT, DEV_SCSI_LOGGING_LEVEL, "logging_level" },
848 {}
849};
850
851static const struct bin_table bin_dev_table[] = {
852 /* DEV_CDROM "cdrom" no longer used */
853 /* DEV_HWMON unused */
854 /* DEV_PARPORT "parport" no longer used */
855 { CTL_DIR, DEV_RAID, "raid", bin_raid_table },
856 { CTL_DIR, DEV_MAC_HID, "mac_hid", bin_mac_hid_files },
857 { CTL_DIR, DEV_SCSI, "scsi", bin_scsi_table },
858 { CTL_DIR, DEV_IPMI, "ipmi", bin_ipmi_table },
859 {}
860};
861
862static const struct bin_table bin_bus_isa_table[] = {
863 { CTL_INT, BUS_ISA_MEM_BASE, "membase" },
864 { CTL_INT, BUS_ISA_PORT_BASE, "portbase" },
865 { CTL_INT, BUS_ISA_PORT_SHIFT, "portshift" },
866 {}
867};
868
869static const struct bin_table bin_bus_table[] = {
870 { CTL_DIR, CTL_BUS_ISA, "isa", bin_bus_isa_table },
871 {}
872};
873
874
875static const struct bin_table bin_s390dbf_table[] = {
876 { CTL_INT, 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" },
877 { CTL_INT, 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" },
878 {}
879};
880
881static const struct bin_table bin_sunrpc_table[] = {
882 /* CTL_RPCDEBUG "rpc_debug" no longer used */
883 /* CTL_NFSDEBUG "nfs_debug" no longer used */
884 /* CTL_NFSDDEBUG "nfsd_debug" no longer used */
885 /* CTL_NLMDEBUG "nlm_debug" no longer used */
886
887 { CTL_INT, CTL_SLOTTABLE_UDP, "udp_slot_table_entries" },
888 { CTL_INT, CTL_SLOTTABLE_TCP, "tcp_slot_table_entries" },
889 { CTL_INT, CTL_MIN_RESVPORT, "min_resvport" },
890 { CTL_INT, CTL_MAX_RESVPORT, "max_resvport" },
891 {}
892};
893
894static const struct bin_table bin_pm_table[] = {
895 /* frv specific */
896 /* 1 == CTL_PM_SUSPEND "suspend" no longer used" */
897 { CTL_INT, 2 /* CTL_PM_CMODE */, "cmode" },
898 { CTL_INT, 3 /* CTL_PM_P0 */, "p0" },
899 { CTL_INT, 4 /* CTL_PM_CM */, "cm" },
900 {}
901};
902
903static const struct bin_table bin_root_table[] = {
904 { CTL_DIR, CTL_KERN, "kernel", bin_kern_table },
905 { CTL_DIR, CTL_VM, "vm", bin_vm_table },
906 { CTL_DIR, CTL_NET, "net", bin_net_table },
907 /* CTL_PROC not used */
908 { CTL_DIR, CTL_FS, "fs", bin_fs_table },
909 /* CTL_DEBUG "debug" no longer used */
910 { CTL_DIR, CTL_DEV, "dev", bin_dev_table },
911 { CTL_DIR, CTL_BUS, "bus", bin_bus_table },
912 { CTL_DIR, CTL_ABI, "abi" },
913 /* CTL_CPU not used */
914 /* CTL_ARLAN "arlan" no longer used */
915 { CTL_DIR, CTL_S390DBF, "s390dbf", bin_s390dbf_table },
916 { CTL_DIR, CTL_SUNRPC, "sunrpc", bin_sunrpc_table },
917 { CTL_DIR, CTL_PM, "pm", bin_pm_table },
918 {}
919};
920
921static ssize_t bin_dir(struct file *file,
922 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
923{
924 return -ENOTDIR;
925}
926
927
928static ssize_t bin_string(struct file *file,
929 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
930{
931 ssize_t result, copied = 0;
932
933 if (oldval && oldlen) {
934 char __user *lastp;
935 loff_t pos = 0;
936 int ch;
937
938 result = vfs_read(file, oldval, oldlen, &pos);
939 if (result < 0)
940 goto out;
941
942 copied = result;
943 lastp = oldval + copied - 1;
944
945 result = -EFAULT;
946 if (get_user(ch, lastp))
947 goto out;
948
949 /* Trim off the trailing newline */
950 if (ch == '\n') {
951 result = -EFAULT;
952 if (put_user('\0', lastp))
953 goto out;
954 copied -= 1;
955 }
956 }
957
958 if (newval && newlen) {
959 loff_t pos = 0;
960
961 result = vfs_write(file, newval, newlen, &pos);
962 if (result < 0)
963 goto out;
964 }
965
966 result = copied;
967out:
968 return result;
969}
970
971static ssize_t bin_intvec(struct file *file,
972 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
973{
974 mm_segment_t old_fs = get_fs();
975 ssize_t copied = 0;
976 char *buffer;
977 ssize_t result;
978
979 result = -ENOMEM;
980 buffer = kmalloc(BUFSZ, GFP_KERNEL);
981 if (!buffer)
982 goto out;
983
984 if (oldval && oldlen) {
985 unsigned __user *vec = oldval;
986 size_t length = oldlen / sizeof(*vec);
987 loff_t pos = 0;
988 char *str, *end;
989 int i;
990
991 set_fs(KERNEL_DS);
992 result = vfs_read(file, buffer, BUFSZ - 1, &pos);
993 set_fs(old_fs);
994 if (result < 0)
995 goto out_kfree;
996
997 str = buffer;
998 end = str + result;
999 *end++ = '\0';
1000 for (i = 0; i < length; i++) {
1001 unsigned long value;
1002
1003 value = simple_strtoul(str, &str, 10);
1004 while (isspace(*str))
1005 str++;
1006
1007 result = -EFAULT;
1008 if (put_user(value, vec + i))
1009 goto out_kfree;
1010
1011 copied += sizeof(*vec);
1012 if (!isdigit(*str))
1013 break;
1014 }
1015 }
1016
1017 if (newval && newlen) {
1018 unsigned __user *vec = newval;
1019 size_t length = newlen / sizeof(*vec);
1020 loff_t pos = 0;
1021 char *str, *end;
1022 int i;
1023
1024 str = buffer;
1025 end = str + BUFSZ;
1026 for (i = 0; i < length; i++) {
1027 unsigned long value;
1028
1029 result = -EFAULT;
1030 if (get_user(value, vec + i))
1031 goto out_kfree;
1032
1033 str += snprintf(str, end - str, "%lu\t", value);
1034 }
1035
1036 set_fs(KERNEL_DS);
1037 result = vfs_write(file, buffer, str - buffer, &pos);
1038 set_fs(old_fs);
1039 if (result < 0)
1040 goto out_kfree;
1041 }
1042 result = copied;
1043out_kfree:
1044 kfree(buffer);
1045out:
1046 return result;
1047}
1048
1049static ssize_t bin_ulongvec(struct file *file,
1050 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1051{
1052 mm_segment_t old_fs = get_fs();
1053 ssize_t copied = 0;
1054 char *buffer;
1055 ssize_t result;
1056
1057 result = -ENOMEM;
1058 buffer = kmalloc(BUFSZ, GFP_KERNEL);
1059 if (!buffer)
1060 goto out;
1061
1062 if (oldval && oldlen) {
1063 unsigned long __user *vec = oldval;
1064 size_t length = oldlen / sizeof(*vec);
1065 loff_t pos = 0;
1066 char *str, *end;
1067 int i;
1068
1069 set_fs(KERNEL_DS);
1070 result = vfs_read(file, buffer, BUFSZ - 1, &pos);
1071 set_fs(old_fs);
1072 if (result < 0)
1073 goto out_kfree;
1074
1075 str = buffer;
1076 end = str + result;
1077 *end++ = '\0';
1078 for (i = 0; i < length; i++) {
1079 unsigned long value;
1080
1081 value = simple_strtoul(str, &str, 10);
1082 while (isspace(*str))
1083 str++;
1084
1085 result = -EFAULT;
1086 if (put_user(value, vec + i))
1087 goto out_kfree;
1088
1089 copied += sizeof(*vec);
1090 if (!isdigit(*str))
1091 break;
1092 }
1093 }
1094
1095 if (newval && newlen) {
1096 unsigned long __user *vec = newval;
1097 size_t length = newlen / sizeof(*vec);
1098 loff_t pos = 0;
1099 char *str, *end;
1100 int i;
1101
1102 str = buffer;
1103 end = str + BUFSZ;
1104 for (i = 0; i < length; i++) {
1105 unsigned long value;
1106
1107 result = -EFAULT;
1108 if (get_user(value, vec + i))
1109 goto out_kfree;
1110
1111 str += snprintf(str, end - str, "%lu\t", value);
1112 }
1113
1114 set_fs(KERNEL_DS);
1115 result = vfs_write(file, buffer, str - buffer, &pos);
1116 set_fs(old_fs);
1117 if (result < 0)
1118 goto out_kfree;
1119 }
1120 result = copied;
1121out_kfree:
1122 kfree(buffer);
1123out:
1124 return result;
1125}
1126
1127static unsigned hex_value(int ch)
1128{
1129 return isdigit(ch) ? ch - '0' : ((ch | 0x20) - 'a') + 10;
1130}
1131
1132static ssize_t bin_uuid(struct file *file,
1133 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1134{
1135 mm_segment_t old_fs = get_fs();
1136 ssize_t result, copied = 0;
1137
1138 /* Only supports reads */
1139 if (oldval && oldlen) {
1140 loff_t pos = 0;
1141 char buf[40], *str = buf;
1142 unsigned char uuid[16];
1143 int i;
1144
1145 set_fs(KERNEL_DS);
1146 result = vfs_read(file, buf, sizeof(buf) - 1, &pos);
1147 set_fs(old_fs);
1148 if (result < 0)
1149 goto out;
1150
1151 buf[result] = '\0';
1152
1153 /* Convert the uuid to from a string to binary */
1154 for (i = 0; i < 16; i++) {
1155 result = -EIO;
1156 if (!isxdigit(str[0]) || !isxdigit(str[1]))
1157 goto out;
1158
1159 uuid[i] = (hex_value(str[0]) << 4) | hex_value(str[1]);
1160 str += 2;
1161 if (*str == '-')
1162 str++;
1163 }
1164
1165 if (oldlen > 16)
1166 oldlen = 16;
1167
1168 result = -EFAULT;
1169 if (copy_to_user(oldval, uuid, oldlen))
1170 goto out;
1171
1172 copied = oldlen;
1173 }
1174 result = copied;
1175out:
1176 return result;
1177}
1178
1179static ssize_t bin_dn_node_address(struct file *file,
1180 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1181{
1182 mm_segment_t old_fs = get_fs();
1183 ssize_t result, copied = 0;
1184
1185 if (oldval && oldlen) {
1186 loff_t pos = 0;
1187 char buf[15], *nodep;
1188 unsigned long area, node;
1189 __le16 dnaddr;
1190
1191 set_fs(KERNEL_DS);
1192 result = vfs_read(file, buf, sizeof(buf) - 1, &pos);
1193 set_fs(old_fs);
1194 if (result < 0)
1195 goto out;
1196
1197 buf[result] = '\0';
1198
1199 /* Convert the decnet addresss to binary */
1200 result = -EIO;
1201 nodep = strchr(buf, '.') + 1;
1202 if (!nodep)
1203 goto out;
1204
1205 area = simple_strtoul(buf, NULL, 10);
1206 node = simple_strtoul(nodep, NULL, 10);
1207
1208 result = -EIO;
1209 if ((area > 63)||(node > 1023))
1210 goto out;
1211
1212 dnaddr = cpu_to_le16((area << 10) | node);
1213
1214 result = -EFAULT;
1215 if (put_user(dnaddr, (__le16 __user *)oldval))
1216 goto out;
1217
1218 copied = sizeof(dnaddr);
1219 }
1220
1221 if (newval && newlen) {
1222 loff_t pos = 0;
1223 __le16 dnaddr;
1224 char buf[15];
1225 int len;
1226
1227 result = -EINVAL;
1228 if (newlen != sizeof(dnaddr))
1229 goto out;
1230
1231 result = -EFAULT;
1232 if (get_user(dnaddr, (__le16 __user *)newval))
1233 goto out;
1234
1235 len = snprintf(buf, sizeof(buf), "%hu.%hu",
1236 le16_to_cpu(dnaddr) >> 10,
1237 le16_to_cpu(dnaddr) & 0x3ff);
1238
1239 set_fs(KERNEL_DS);
1240 result = vfs_write(file, buf, len, &pos);
1241 set_fs(old_fs);
1242 if (result < 0)
1243 goto out;
1244 }
1245
1246 result = copied;
1247out:
1248 return result;
1249}
1250
1251static const struct bin_table *get_sysctl(const int *name, int nlen, char *path)
1252{
1253 const struct bin_table *table = &bin_root_table[0];
1254 int ctl_name;
1255
1256 /* The binary sysctl tables have a small maximum depth so
1257 * there is no danger of overflowing our path as it PATH_MAX
1258 * bytes long.
1259 */
1260 memcpy(path, "sys/", 4);
1261 path += 4;
1262
1263repeat:
1264 if (!nlen)
1265 return ERR_PTR(-ENOTDIR);
1266 ctl_name = *name;
1267 name++;
1268 nlen--;
1269 for ( ; table->convert; table++) {
1270 int len = 0;
1271
1272 /*
1273 * For a wild card entry map from ifindex to network
1274 * device name.
1275 */
1276 if (!table->ctl_name) {
1277#ifdef CONFIG_NET
1278 struct net *net = current->nsproxy->net_ns;
1279 struct net_device *dev;
1280 dev = dev_get_by_index(net, ctl_name);
1281 if (dev) {
1282 len = strlen(dev->name);
1283 memcpy(path, dev->name, len);
1284 dev_put(dev);
1285 }
1286#endif
1287 /* Use the well known sysctl number to proc name mapping */
1288 } else if (ctl_name == table->ctl_name) {
1289 len = strlen(table->procname);
1290 memcpy(path, table->procname, len);
1291 }
1292 if (len) {
1293 path += len;
1294 if (table->child) {
1295 *path++ = '/';
1296 table = table->child;
1297 goto repeat;
1298 }
1299 *path = '\0';
1300 return table;
1301 }
1302 }
1303 return ERR_PTR(-ENOTDIR);
1304}
1305
1306static char *sysctl_getname(const int *name, int nlen, const struct bin_table **tablep)
1307{
1308 char *tmp, *result;
1309
1310 result = ERR_PTR(-ENOMEM);
1311 tmp = __getname();
1312 if (tmp) {
1313 const struct bin_table *table = get_sysctl(name, nlen, tmp);
1314 result = tmp;
1315 *tablep = table;
1316 if (IS_ERR(table)) {
1317 __putname(tmp);
1318 result = ERR_CAST(table);
1319 }
1320 }
1321 return result;
1322}
1323
1324static ssize_t binary_sysctl(const int *name, int nlen,
1325 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1326{
1327 const struct bin_table *table = NULL;
1328 struct nameidata nd;
1329 struct vfsmount *mnt;
1330 struct file *file;
1331 ssize_t result;
1332 char *pathname;
1333 int flags;
1334 int acc_mode, fmode;
1335
1336 pathname = sysctl_getname(name, nlen, &table);
1337 result = PTR_ERR(pathname);
1338 if (IS_ERR(pathname))
1339 goto out;
1340
1341 /* How should the sysctl be accessed? */
1342 if (oldval && oldlen && newval && newlen) {
1343 flags = O_RDWR;
1344 acc_mode = MAY_READ | MAY_WRITE;
1345 fmode = FMODE_READ | FMODE_WRITE;
1346 } else if (newval && newlen) {
1347 flags = O_WRONLY;
1348 acc_mode = MAY_WRITE;
1349 fmode = FMODE_WRITE;
1350 } else if (oldval && oldlen) {
1351 flags = O_RDONLY;
1352 acc_mode = MAY_READ;
1353 fmode = FMODE_READ;
1354 } else {
1355 result = 0;
1356 goto out_putname;
1357 }
1358
1359 mnt = current->nsproxy->pid_ns->proc_mnt;
1360 result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
1361 if (result)
1362 goto out_putname;
1363
1364 result = may_open(&nd.path, acc_mode, fmode);
1365 if (result)
1366 goto out_putpath;
1367
1368 file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
1369 result = PTR_ERR(file);
1370 if (IS_ERR(file))
1371 goto out_putname;
1372
1373 result = table->convert(file, oldval, oldlen, newval, newlen);
1374
1375 fput(file);
1376out_putname:
1377 putname(pathname);
1378out:
1379 return result;
1380
1381out_putpath:
1382 path_put(&nd.path);
1383 goto out_putname;
1384}
1385
1386
1387#else /* CONFIG_SYSCTL_SYSCALL */
1388
1389static ssize_t binary_sysctl(const int *name, int nlen,
1390 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1391{
1392 return -ENOSYS;
1393}
1394
1395#endif /* CONFIG_SYSCTL_SYSCALL */
1396
1397
1398static void deprecated_sysctl_warning(const int *name, int nlen)
1399{
1400 int i;
1401
1402 if (printk_ratelimit()) {
1403 printk(KERN_INFO
1404 "warning: process `%s' used the deprecated sysctl "
1405 "system call with ", current->comm);
1406 for (i = 0; i < nlen; i++)
1407 printk("%d.", name[i]);
1408 printk("\n");
1409 }
1410 return;
1411}
1412
1413static ssize_t do_sysctl(int __user *args_name, int nlen,
1414 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1415{
1416 int name[CTL_MAXNAME];
1417 int i;
1418
1419 /* Check args->nlen. */
1420 if (nlen < 0 || nlen > CTL_MAXNAME)
1421 return -ENOTDIR;
1422 /* Read in the sysctl name for simplicity */
1423 for (i = 0; i < nlen; i++)
1424 if (get_user(name[i], args_name + i))
1425 return -EFAULT;
1426
1427 deprecated_sysctl_warning(name, nlen);
1428
1429 return binary_sysctl(name, nlen, oldval, oldlen, newval, newlen);
1430}
1431
1432SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
1433{
1434 struct __sysctl_args tmp;
1435 size_t oldlen = 0;
1436 ssize_t result;
1437
1438 if (copy_from_user(&tmp, args, sizeof(tmp)))
1439 return -EFAULT;
1440
1441 if (tmp.oldval && !tmp.oldlenp)
1442 return -EFAULT;
1443
1444 if (tmp.oldlenp && get_user(oldlen, tmp.oldlenp))
1445 return -EFAULT;
1446
1447 result = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, oldlen,
1448 tmp.newval, tmp.newlen);
1449
1450 if (result >= 0) {
1451 oldlen = result;
1452 result = 0;
1453 }
1454
1455 if (tmp.oldlenp && put_user(oldlen, tmp.oldlenp))
1456 return -EFAULT;
1457
1458 return result;
1459}
1460
1461
1462#ifdef CONFIG_COMPAT
1463#include <asm/compat.h>
1464
1465struct compat_sysctl_args {
1466 compat_uptr_t name;
1467 int nlen;
1468 compat_uptr_t oldval;
1469 compat_uptr_t oldlenp;
1470 compat_uptr_t newval;
1471 compat_size_t newlen;
1472 compat_ulong_t __unused[4];
1473};
1474
1475asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args)
1476{
1477 struct compat_sysctl_args tmp;
1478 compat_size_t __user *compat_oldlenp;
1479 size_t oldlen = 0;
1480 ssize_t result;
1481
1482 if (copy_from_user(&tmp, args, sizeof(tmp)))
1483 return -EFAULT;
1484
1485 if (tmp.oldval && !tmp.oldlenp)
1486 return -EFAULT;
1487
1488 compat_oldlenp = compat_ptr(tmp.oldlenp);
1489 if (compat_oldlenp && get_user(oldlen, compat_oldlenp))
1490 return -EFAULT;
1491
1492 result = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
1493 compat_ptr(tmp.oldval), oldlen,
1494 compat_ptr(tmp.newval), tmp.newlen);
1495
1496 if (result >= 0) {
1497 oldlen = result;
1498 result = 0;
1499 }
1500
1501 if (compat_oldlenp && put_user(oldlen, compat_oldlenp))
1502 return -EFAULT;
1503
1504 return result;
1505}
1506
1507#endif /* CONFIG_COMPAT */
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index f1d676e4b368..04cdcf72c827 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -5,1240 +5,6 @@
5#include <linux/string.h> 5#include <linux/string.h>
6#include <net/ip_vs.h> 6#include <net/ip_vs.h>
7 7
8struct trans_ctl_table {
9 int ctl_name;
10 const char *procname;
11 const struct trans_ctl_table *child;
12};
13
14static const struct trans_ctl_table trans_random_table[] = {
15 { RANDOM_POOLSIZE, "poolsize" },
16 { RANDOM_ENTROPY_COUNT, "entropy_avail" },
17 { RANDOM_READ_THRESH, "read_wakeup_threshold" },
18 { RANDOM_WRITE_THRESH, "write_wakeup_threshold" },
19 { RANDOM_BOOT_ID, "boot_id" },
20 { RANDOM_UUID, "uuid" },
21 {}
22};
23
24static const struct trans_ctl_table trans_pty_table[] = {
25 { PTY_MAX, "max" },
26 { PTY_NR, "nr" },
27 {}
28};
29
30static const struct trans_ctl_table trans_kern_table[] = {
31 { KERN_OSTYPE, "ostype" },
32 { KERN_OSRELEASE, "osrelease" },
33 /* KERN_OSREV not used */
34 { KERN_VERSION, "version" },
35 /* KERN_SECUREMASK not used */
36 /* KERN_PROF not used */
37 { KERN_NODENAME, "hostname" },
38 { KERN_DOMAINNAME, "domainname" },
39
40 { KERN_PANIC, "panic" },
41 { KERN_REALROOTDEV, "real-root-dev" },
42
43 { KERN_SPARC_REBOOT, "reboot-cmd" },
44 { KERN_CTLALTDEL, "ctrl-alt-del" },
45 { KERN_PRINTK, "printk" },
46
47 /* KERN_NAMETRANS not used */
48 /* KERN_PPC_HTABRECLAIM not used */
49 /* KERN_PPC_ZEROPAGED not used */
50 { KERN_PPC_POWERSAVE_NAP, "powersave-nap" },
51
52 { KERN_MODPROBE, "modprobe" },
53 { KERN_SG_BIG_BUFF, "sg-big-buff" },
54 { KERN_ACCT, "acct" },
55 { KERN_PPC_L2CR, "l2cr" },
56
57 /* KERN_RTSIGNR not used */
58 /* KERN_RTSIGMAX not used */
59
60 { KERN_SHMMAX, "shmmax" },
61 { KERN_MSGMAX, "msgmax" },
62 { KERN_MSGMNB, "msgmnb" },
63 /* KERN_MSGPOOL not used*/
64 { KERN_SYSRQ, "sysrq" },
65 { KERN_MAX_THREADS, "threads-max" },
66 { KERN_RANDOM, "random", trans_random_table },
67 { KERN_SHMALL, "shmall" },
68 { KERN_MSGMNI, "msgmni" },
69 { KERN_SEM, "sem" },
70 { KERN_SPARC_STOP_A, "stop-a" },
71 { KERN_SHMMNI, "shmmni" },
72
73 { KERN_OVERFLOWUID, "overflowuid" },
74 { KERN_OVERFLOWGID, "overflowgid" },
75
76 { KERN_HOTPLUG, "hotplug", },
77 { KERN_IEEE_EMULATION_WARNINGS, "ieee_emulation_warnings" },
78
79 { KERN_S390_USER_DEBUG_LOGGING, "userprocess_debug" },
80 { KERN_CORE_USES_PID, "core_uses_pid" },
81 { KERN_TAINTED, "tainted" },
82 { KERN_CADPID, "cad_pid" },
83 { KERN_PIDMAX, "pid_max" },
84 { KERN_CORE_PATTERN, "core_pattern" },
85 { KERN_PANIC_ON_OOPS, "panic_on_oops" },
86 { KERN_HPPA_PWRSW, "soft-power" },
87 { KERN_HPPA_UNALIGNED, "unaligned-trap" },
88
89 { KERN_PRINTK_RATELIMIT, "printk_ratelimit" },
90 { KERN_PRINTK_RATELIMIT_BURST, "printk_ratelimit_burst" },
91
92 { KERN_PTY, "pty", trans_pty_table },
93 { KERN_NGROUPS_MAX, "ngroups_max" },
94 { KERN_SPARC_SCONS_PWROFF, "scons-poweroff" },
95 { KERN_HZ_TIMER, "hz_timer" },
96 { KERN_UNKNOWN_NMI_PANIC, "unknown_nmi_panic" },
97 { KERN_BOOTLOADER_TYPE, "bootloader_type" },
98 { KERN_RANDOMIZE, "randomize_va_space" },
99
100 { KERN_SPIN_RETRY, "spin_retry" },
101 { KERN_ACPI_VIDEO_FLAGS, "acpi_video_flags" },
102 { KERN_IA64_UNALIGNED, "ignore-unaligned-usertrap" },
103 { KERN_COMPAT_LOG, "compat-log" },
104 { KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
105 { KERN_NMI_WATCHDOG, "nmi_watchdog" },
106 { KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
107 {}
108};
109
110static const struct trans_ctl_table trans_vm_table[] = {
111 { VM_OVERCOMMIT_MEMORY, "overcommit_memory" },
112 { VM_PAGE_CLUSTER, "page-cluster" },
113 { VM_DIRTY_BACKGROUND, "dirty_background_ratio" },
114 { VM_DIRTY_RATIO, "dirty_ratio" },
115 { VM_DIRTY_WB_CS, "dirty_writeback_centisecs" },
116 { VM_DIRTY_EXPIRE_CS, "dirty_expire_centisecs" },
117 { VM_NR_PDFLUSH_THREADS, "nr_pdflush_threads" },
118 { VM_OVERCOMMIT_RATIO, "overcommit_ratio" },
119 /* VM_PAGEBUF unused */
120 { VM_HUGETLB_PAGES, "nr_hugepages" },
121 { VM_SWAPPINESS, "swappiness" },
122 { VM_LOWMEM_RESERVE_RATIO, "lowmem_reserve_ratio" },
123 { VM_MIN_FREE_KBYTES, "min_free_kbytes" },
124 { VM_MAX_MAP_COUNT, "max_map_count" },
125 { VM_LAPTOP_MODE, "laptop_mode" },
126 { VM_BLOCK_DUMP, "block_dump" },
127 { VM_HUGETLB_GROUP, "hugetlb_shm_group" },
128 { VM_VFS_CACHE_PRESSURE, "vfs_cache_pressure" },
129 { VM_LEGACY_VA_LAYOUT, "legacy_va_layout" },
130 /* VM_SWAP_TOKEN_TIMEOUT unused */
131 { VM_DROP_PAGECACHE, "drop_caches" },
132 { VM_PERCPU_PAGELIST_FRACTION, "percpu_pagelist_fraction" },
133 { VM_ZONE_RECLAIM_MODE, "zone_reclaim_mode" },
134 { VM_MIN_UNMAPPED, "min_unmapped_ratio" },
135 { VM_PANIC_ON_OOM, "panic_on_oom" },
136 { VM_VDSO_ENABLED, "vdso_enabled" },
137 { VM_MIN_SLAB, "min_slab_ratio" },
138
139 {}
140};
141
142static const struct trans_ctl_table trans_net_core_table[] = {
143 { NET_CORE_WMEM_MAX, "wmem_max" },
144 { NET_CORE_RMEM_MAX, "rmem_max" },
145 { NET_CORE_WMEM_DEFAULT, "wmem_default" },
146 { NET_CORE_RMEM_DEFAULT, "rmem_default" },
147 /* NET_CORE_DESTROY_DELAY unused */
148 { NET_CORE_MAX_BACKLOG, "netdev_max_backlog" },
149 /* NET_CORE_FASTROUTE unused */
150 { NET_CORE_MSG_COST, "message_cost" },
151 { NET_CORE_MSG_BURST, "message_burst" },
152 { NET_CORE_OPTMEM_MAX, "optmem_max" },
153 /* NET_CORE_HOT_LIST_LENGTH unused */
154 /* NET_CORE_DIVERT_VERSION unused */
155 /* NET_CORE_NO_CONG_THRESH unused */
156 /* NET_CORE_NO_CONG unused */
157 /* NET_CORE_LO_CONG unused */
158 /* NET_CORE_MOD_CONG unused */
159 { NET_CORE_DEV_WEIGHT, "dev_weight" },
160 { NET_CORE_SOMAXCONN, "somaxconn" },
161 { NET_CORE_BUDGET, "netdev_budget" },
162 { NET_CORE_AEVENT_ETIME, "xfrm_aevent_etime" },
163 { NET_CORE_AEVENT_RSEQTH, "xfrm_aevent_rseqth" },
164 { NET_CORE_WARNINGS, "warnings" },
165 {},
166};
167
168static const struct trans_ctl_table trans_net_unix_table[] = {
169 /* NET_UNIX_DESTROY_DELAY unused */
170 /* NET_UNIX_DELETE_DELAY unused */
171 { NET_UNIX_MAX_DGRAM_QLEN, "max_dgram_qlen" },
172 {}
173};
174
175static const struct trans_ctl_table trans_net_ipv4_route_table[] = {
176 { NET_IPV4_ROUTE_FLUSH, "flush" },
177 { NET_IPV4_ROUTE_MIN_DELAY, "min_delay" },
178 { NET_IPV4_ROUTE_MAX_DELAY, "max_delay" },
179 { NET_IPV4_ROUTE_GC_THRESH, "gc_thresh" },
180 { NET_IPV4_ROUTE_MAX_SIZE, "max_size" },
181 { NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
182 { NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout" },
183 { NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval" },
184 { NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load" },
185 { NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number" },
186 { NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence" },
187 { NET_IPV4_ROUTE_ERROR_COST, "error_cost" },
188 { NET_IPV4_ROUTE_ERROR_BURST, "error_burst" },
189 { NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity" },
190 { NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires" },
191 { NET_IPV4_ROUTE_MIN_PMTU, "min_pmtu" },
192 { NET_IPV4_ROUTE_MIN_ADVMSS, "min_adv_mss" },
193 { NET_IPV4_ROUTE_SECRET_INTERVAL, "secret_interval" },
194 { NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
195 {}
196};
197
198static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = {
199 { NET_IPV4_CONF_FORWARDING, "forwarding" },
200 { NET_IPV4_CONF_MC_FORWARDING, "mc_forwarding" },
201
202 { NET_IPV4_CONF_PROXY_ARP, "proxy_arp" },
203 { NET_IPV4_CONF_ACCEPT_REDIRECTS, "accept_redirects" },
204 { NET_IPV4_CONF_SECURE_REDIRECTS, "secure_redirects" },
205 { NET_IPV4_CONF_SEND_REDIRECTS, "send_redirects" },
206 { NET_IPV4_CONF_SHARED_MEDIA, "shared_media" },
207 { NET_IPV4_CONF_RP_FILTER, "rp_filter" },
208 { NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
209 { NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay" },
210 { NET_IPV4_CONF_LOG_MARTIANS, "log_martians" },
211 { NET_IPV4_CONF_TAG, "tag" },
212 { NET_IPV4_CONF_ARPFILTER, "arp_filter" },
213 { NET_IPV4_CONF_MEDIUM_ID, "medium_id" },
214 { NET_IPV4_CONF_NOXFRM, "disable_xfrm" },
215 { NET_IPV4_CONF_NOPOLICY, "disable_policy" },
216 { NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version" },
217
218 { NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce" },
219 { NET_IPV4_CONF_ARP_IGNORE, "arp_ignore" },
220 { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" },
221 { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" },
222 { NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" },
223 { NET_IPV4_CONF_ACCEPT_LOCAL, "accept_local" },
224 {}
225};
226
227static const struct trans_ctl_table trans_net_ipv4_conf_table[] = {
228 { NET_PROTO_CONF_ALL, "all", trans_net_ipv4_conf_vars_table },
229 { NET_PROTO_CONF_DEFAULT, "default", trans_net_ipv4_conf_vars_table },
230 { 0, NULL, trans_net_ipv4_conf_vars_table },
231 {}
232};
233
234static const struct trans_ctl_table trans_net_neigh_vars_table[] = {
235 { NET_NEIGH_MCAST_SOLICIT, "mcast_solicit" },
236 { NET_NEIGH_UCAST_SOLICIT, "ucast_solicit" },
237 { NET_NEIGH_APP_SOLICIT, "app_solicit" },
238 { NET_NEIGH_RETRANS_TIME, "retrans_time" },
239 { NET_NEIGH_REACHABLE_TIME, "base_reachable_time" },
240 { NET_NEIGH_DELAY_PROBE_TIME, "delay_first_probe_time" },
241 { NET_NEIGH_GC_STALE_TIME, "gc_stale_time" },
242 { NET_NEIGH_UNRES_QLEN, "unres_qlen" },
243 { NET_NEIGH_PROXY_QLEN, "proxy_qlen" },
244 { NET_NEIGH_ANYCAST_DELAY, "anycast_delay" },
245 { NET_NEIGH_PROXY_DELAY, "proxy_delay" },
246 { NET_NEIGH_LOCKTIME, "locktime" },
247 { NET_NEIGH_GC_INTERVAL, "gc_interval" },
248 { NET_NEIGH_GC_THRESH1, "gc_thresh1" },
249 { NET_NEIGH_GC_THRESH2, "gc_thresh2" },
250 { NET_NEIGH_GC_THRESH3, "gc_thresh3" },
251 { NET_NEIGH_RETRANS_TIME_MS, "retrans_time_ms" },
252 { NET_NEIGH_REACHABLE_TIME_MS, "base_reachable_time_ms" },
253 {}
254};
255
256static const struct trans_ctl_table trans_net_neigh_table[] = {
257 { NET_PROTO_CONF_DEFAULT, "default", trans_net_neigh_vars_table },
258 { 0, NULL, trans_net_neigh_vars_table },
259 {}
260};
261
262static const struct trans_ctl_table trans_net_ipv4_netfilter_table[] = {
263 { NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max" },
264
265 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent" },
266 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv" },
267 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established" },
268 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait" },
269 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait" },
270 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack" },
271 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait" },
272 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close" },
273
274 { NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout" },
275 { NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream" },
276 { NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout" },
277 { NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout" },
278
279 { NET_IPV4_NF_CONNTRACK_BUCKETS, "ip_conntrack_buckets" },
280 { NET_IPV4_NF_CONNTRACK_LOG_INVALID, "ip_conntrack_log_invalid" },
281 { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, "ip_conntrack_tcp_timeout_max_retrans" },
282 { NET_IPV4_NF_CONNTRACK_TCP_LOOSE, "ip_conntrack_tcp_loose" },
283 { NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, "ip_conntrack_tcp_be_liberal" },
284 { NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, "ip_conntrack_tcp_max_retrans" },
285
286 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, "ip_conntrack_sctp_timeout_closed" },
287 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, "ip_conntrack_sctp_timeout_cookie_wait" },
288 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, "ip_conntrack_sctp_timeout_cookie_echoed" },
289 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, "ip_conntrack_sctp_timeout_established" },
290 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, "ip_conntrack_sctp_timeout_shutdown_sent" },
291 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, "ip_conntrack_sctp_timeout_shutdown_recd" },
292 { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, "ip_conntrack_sctp_timeout_shutdown_ack_sent" },
293
294 { NET_IPV4_NF_CONNTRACK_COUNT, "ip_conntrack_count" },
295 { NET_IPV4_NF_CONNTRACK_CHECKSUM, "ip_conntrack_checksum" },
296 {}
297};
298
299static const struct trans_ctl_table trans_net_ipv4_table[] = {
300 { NET_IPV4_FORWARD, "ip_forward" },
301 { NET_IPV4_DYNADDR, "ip_dynaddr" },
302
303 { NET_IPV4_CONF, "conf", trans_net_ipv4_conf_table },
304 { NET_IPV4_NEIGH, "neigh", trans_net_neigh_table },
305 { NET_IPV4_ROUTE, "route", trans_net_ipv4_route_table },
306 /* NET_IPV4_FIB_HASH unused */
307 { NET_IPV4_NETFILTER, "netfilter", trans_net_ipv4_netfilter_table },
308
309 { NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps" },
310 { NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling" },
311 { NET_IPV4_TCP_SACK, "tcp_sack" },
312 { NET_IPV4_TCP_RETRANS_COLLAPSE, "tcp_retrans_collapse" },
313 { NET_IPV4_DEFAULT_TTL, "ip_default_ttl" },
314 /* NET_IPV4_AUTOCONFIG unused */
315 { NET_IPV4_NO_PMTU_DISC, "ip_no_pmtu_disc" },
316 { NET_IPV4_TCP_SYN_RETRIES, "tcp_syn_retries" },
317 { NET_IPV4_IPFRAG_HIGH_THRESH, "ipfrag_high_thresh" },
318 { NET_IPV4_IPFRAG_LOW_THRESH, "ipfrag_low_thresh" },
319 { NET_IPV4_IPFRAG_TIME, "ipfrag_time" },
320 /* NET_IPV4_TCP_MAX_KA_PROBES unused */
321 { NET_IPV4_TCP_KEEPALIVE_TIME, "tcp_keepalive_time" },
322 { NET_IPV4_TCP_KEEPALIVE_PROBES, "tcp_keepalive_probes" },
323 { NET_IPV4_TCP_RETRIES1, "tcp_retries1" },
324 { NET_IPV4_TCP_RETRIES2, "tcp_retries2" },
325 { NET_IPV4_TCP_FIN_TIMEOUT, "tcp_fin_timeout" },
326 /* NET_IPV4_IP_MASQ_DEBUG unused */
327 { NET_TCP_SYNCOOKIES, "tcp_syncookies" },
328 { NET_TCP_STDURG, "tcp_stdurg" },
329 { NET_TCP_RFC1337, "tcp_rfc1337" },
330 /* NET_TCP_SYN_TAILDROP unused */
331 { NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog" },
332 { NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range" },
333 { NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all" },
334 { NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, "icmp_echo_ignore_broadcasts" },
335 /* NET_IPV4_ICMP_SOURCEQUENCH_RATE unused */
336 /* NET_IPV4_ICMP_DESTUNREACH_RATE unused */
337 /* NET_IPV4_ICMP_TIMEEXCEED_RATE unused */
338 /* NET_IPV4_ICMP_PARAMPROB_RATE unused */
339 /* NET_IPV4_ICMP_ECHOREPLY_RATE unused */
340 { NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses" },
341 { NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships" },
342 { NET_TCP_TW_RECYCLE, "tcp_tw_recycle" },
343 /* NET_IPV4_ALWAYS_DEFRAG unused */
344 { NET_IPV4_TCP_KEEPALIVE_INTVL, "tcp_keepalive_intvl" },
345 { NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold" },
346 { NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl" },
347 { NET_IPV4_INET_PEER_MAXTTL, "inet_peer_maxttl" },
348 { NET_IPV4_INET_PEER_GC_MINTIME, "inet_peer_gc_mintime" },
349 { NET_IPV4_INET_PEER_GC_MAXTIME, "inet_peer_gc_maxtime" },
350 { NET_TCP_ORPHAN_RETRIES, "tcp_orphan_retries" },
351 { NET_TCP_ABORT_ON_OVERFLOW, "tcp_abort_on_overflow" },
352 { NET_TCP_SYNACK_RETRIES, "tcp_synack_retries" },
353 { NET_TCP_MAX_ORPHANS, "tcp_max_orphans" },
354 { NET_TCP_MAX_TW_BUCKETS, "tcp_max_tw_buckets" },
355 { NET_TCP_FACK, "tcp_fack" },
356 { NET_TCP_REORDERING, "tcp_reordering" },
357 { NET_TCP_ECN, "tcp_ecn" },
358 { NET_TCP_DSACK, "tcp_dsack" },
359 { NET_TCP_MEM, "tcp_mem" },
360 { NET_TCP_WMEM, "tcp_wmem" },
361 { NET_TCP_RMEM, "tcp_rmem" },
362 { NET_TCP_APP_WIN, "tcp_app_win" },
363 { NET_TCP_ADV_WIN_SCALE, "tcp_adv_win_scale" },
364 { NET_IPV4_NONLOCAL_BIND, "ip_nonlocal_bind" },
365 { NET_IPV4_ICMP_RATELIMIT, "icmp_ratelimit" },
366 { NET_IPV4_ICMP_RATEMASK, "icmp_ratemask" },
367 { NET_TCP_TW_REUSE, "tcp_tw_reuse" },
368 { NET_TCP_FRTO, "tcp_frto" },
369 { NET_TCP_LOW_LATENCY, "tcp_low_latency" },
370 { NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval" },
371 { NET_IPV4_IGMP_MAX_MSF, "igmp_max_msf" },
372 { NET_TCP_NO_METRICS_SAVE, "tcp_no_metrics_save" },
373 /* NET_TCP_DEFAULT_WIN_SCALE unused */
374 { NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf" },
375 { NET_TCP_TSO_WIN_DIVISOR, "tcp_tso_win_divisor" },
376 /* NET_TCP_BIC_BETA unused */
377 { NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR, "icmp_errors_use_inbound_ifaddr" },
378 { NET_TCP_CONG_CONTROL, "tcp_congestion_control" },
379 { NET_TCP_ABC, "tcp_abc" },
380 { NET_IPV4_IPFRAG_MAX_DIST, "ipfrag_max_dist" },
381 { NET_TCP_MTU_PROBING, "tcp_mtu_probing" },
382 { NET_TCP_BASE_MSS, "tcp_base_mss" },
383 { NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS, "tcp_workaround_signed_windows" },
384 { NET_TCP_DMA_COPYBREAK, "tcp_dma_copybreak" },
385 { NET_TCP_SLOW_START_AFTER_IDLE, "tcp_slow_start_after_idle" },
386 { NET_CIPSOV4_CACHE_ENABLE, "cipso_cache_enable" },
387 { NET_CIPSOV4_CACHE_BUCKET_SIZE, "cipso_cache_bucket_size" },
388 { NET_CIPSOV4_RBM_OPTFMT, "cipso_rbm_optfmt" },
389 { NET_CIPSOV4_RBM_STRICTVALID, "cipso_rbm_strictvalid" },
390 { NET_TCP_AVAIL_CONG_CONTROL, "tcp_available_congestion_control" },
391 { NET_TCP_ALLOWED_CONG_CONTROL, "tcp_allowed_congestion_control" },
392 { NET_TCP_MAX_SSTHRESH, "tcp_max_ssthresh" },
393 { NET_TCP_FRTO_RESPONSE, "tcp_frto_response" },
394 { 2088 /* NET_IPQ_QMAX */, "ip_queue_maxlen" },
395 {}
396};
397
398static const struct trans_ctl_table trans_net_ipx_table[] = {
399 { NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting" },
400 /* NET_IPX_FORWARDING unused */
401 {}
402};
403
404static const struct trans_ctl_table trans_net_atalk_table[] = {
405 { NET_ATALK_AARP_EXPIRY_TIME, "aarp-expiry-time" },
406 { NET_ATALK_AARP_TICK_TIME, "aarp-tick-time" },
407 { NET_ATALK_AARP_RETRANSMIT_LIMIT, "aarp-retransmit-limit" },
408 { NET_ATALK_AARP_RESOLVE_TIME, "aarp-resolve-time" },
409 {},
410};
411
412static const struct trans_ctl_table trans_net_netrom_table[] = {
413 { NET_NETROM_DEFAULT_PATH_QUALITY, "default_path_quality" },
414 { NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER, "obsolescence_count_initialiser" },
415 { NET_NETROM_NETWORK_TTL_INITIALISER, "network_ttl_initialiser" },
416 { NET_NETROM_TRANSPORT_TIMEOUT, "transport_timeout" },
417 { NET_NETROM_TRANSPORT_MAXIMUM_TRIES, "transport_maximum_tries" },
418 { NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY, "transport_acknowledge_delay" },
419 { NET_NETROM_TRANSPORT_BUSY_DELAY, "transport_busy_delay" },
420 { NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE, "transport_requested_window_size" },
421 { NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT, "transport_no_activity_timeout" },
422 { NET_NETROM_ROUTING_CONTROL, "routing_control" },
423 { NET_NETROM_LINK_FAILS_COUNT, "link_fails_count" },
424 { NET_NETROM_RESET, "reset" },
425 {}
426};
427
428static const struct trans_ctl_table trans_net_ax25_param_table[] = {
429 { NET_AX25_IP_DEFAULT_MODE, "ip_default_mode" },
430 { NET_AX25_DEFAULT_MODE, "ax25_default_mode" },
431 { NET_AX25_BACKOFF_TYPE, "backoff_type" },
432 { NET_AX25_CONNECT_MODE, "connect_mode" },
433 { NET_AX25_STANDARD_WINDOW, "standard_window_size" },
434 { NET_AX25_EXTENDED_WINDOW, "extended_window_size" },
435 { NET_AX25_T1_TIMEOUT, "t1_timeout" },
436 { NET_AX25_T2_TIMEOUT, "t2_timeout" },
437 { NET_AX25_T3_TIMEOUT, "t3_timeout" },
438 { NET_AX25_IDLE_TIMEOUT, "idle_timeout" },
439 { NET_AX25_N2, "maximum_retry_count" },
440 { NET_AX25_PACLEN, "maximum_packet_length" },
441 { NET_AX25_PROTOCOL, "protocol" },
442 { NET_AX25_DAMA_SLAVE_TIMEOUT, "dama_slave_timeout" },
443 {}
444};
445
446static const struct trans_ctl_table trans_net_ax25_table[] = {
447 { 0, NULL, trans_net_ax25_param_table },
448 {}
449};
450
451static const struct trans_ctl_table trans_net_bridge_table[] = {
452 { NET_BRIDGE_NF_CALL_ARPTABLES, "bridge-nf-call-arptables" },
453 { NET_BRIDGE_NF_CALL_IPTABLES, "bridge-nf-call-iptables" },
454 { NET_BRIDGE_NF_CALL_IP6TABLES, "bridge-nf-call-ip6tables" },
455 { NET_BRIDGE_NF_FILTER_VLAN_TAGGED, "bridge-nf-filter-vlan-tagged" },
456 { NET_BRIDGE_NF_FILTER_PPPOE_TAGGED, "bridge-nf-filter-pppoe-tagged" },
457 {}
458};
459
460static const struct trans_ctl_table trans_net_rose_table[] = {
461 { NET_ROSE_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
462 { NET_ROSE_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
463 { NET_ROSE_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
464 { NET_ROSE_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
465 { NET_ROSE_ACK_HOLD_BACK_TIMEOUT, "acknowledge_hold_back_timeout" },
466 { NET_ROSE_ROUTING_CONTROL, "routing_control" },
467 { NET_ROSE_LINK_FAIL_TIMEOUT, "link_fail_timeout" },
468 { NET_ROSE_MAX_VCS, "maximum_virtual_circuits" },
469 { NET_ROSE_WINDOW_SIZE, "window_size" },
470 { NET_ROSE_NO_ACTIVITY_TIMEOUT, "no_activity_timeout" },
471 {}
472};
473
474static const struct trans_ctl_table trans_net_ipv6_conf_var_table[] = {
475 { NET_IPV6_FORWARDING, "forwarding" },
476 { NET_IPV6_HOP_LIMIT, "hop_limit" },
477 { NET_IPV6_MTU, "mtu" },
478 { NET_IPV6_ACCEPT_RA, "accept_ra" },
479 { NET_IPV6_ACCEPT_REDIRECTS, "accept_redirects" },
480 { NET_IPV6_AUTOCONF, "autoconf" },
481 { NET_IPV6_DAD_TRANSMITS, "dad_transmits" },
482 { NET_IPV6_RTR_SOLICITS, "router_solicitations" },
483 { NET_IPV6_RTR_SOLICIT_INTERVAL, "router_solicitation_interval" },
484 { NET_IPV6_RTR_SOLICIT_DELAY, "router_solicitation_delay" },
485 { NET_IPV6_USE_TEMPADDR, "use_tempaddr" },
486 { NET_IPV6_TEMP_VALID_LFT, "temp_valid_lft" },
487 { NET_IPV6_TEMP_PREFERED_LFT, "temp_prefered_lft" },
488 { NET_IPV6_REGEN_MAX_RETRY, "regen_max_retry" },
489 { NET_IPV6_MAX_DESYNC_FACTOR, "max_desync_factor" },
490 { NET_IPV6_MAX_ADDRESSES, "max_addresses" },
491 { NET_IPV6_FORCE_MLD_VERSION, "force_mld_version" },
492 { NET_IPV6_ACCEPT_RA_DEFRTR, "accept_ra_defrtr" },
493 { NET_IPV6_ACCEPT_RA_PINFO, "accept_ra_pinfo" },
494 { NET_IPV6_ACCEPT_RA_RTR_PREF, "accept_ra_rtr_pref" },
495 { NET_IPV6_RTR_PROBE_INTERVAL, "router_probe_interval" },
496 { NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" },
497 { NET_IPV6_PROXY_NDP, "proxy_ndp" },
498 { NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
499 {}
500};
501
502static const struct trans_ctl_table trans_net_ipv6_conf_table[] = {
503 { NET_PROTO_CONF_ALL, "all", trans_net_ipv6_conf_var_table },
504 { NET_PROTO_CONF_DEFAULT, "default", trans_net_ipv6_conf_var_table },
505 { 0, NULL, trans_net_ipv6_conf_var_table },
506 {}
507};
508
509static const struct trans_ctl_table trans_net_ipv6_route_table[] = {
510 { NET_IPV6_ROUTE_FLUSH, "flush" },
511 { NET_IPV6_ROUTE_GC_THRESH, "gc_thresh" },
512 { NET_IPV6_ROUTE_MAX_SIZE, "max_size" },
513 { NET_IPV6_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
514 { NET_IPV6_ROUTE_GC_TIMEOUT, "gc_timeout" },
515 { NET_IPV6_ROUTE_GC_INTERVAL, "gc_interval" },
516 { NET_IPV6_ROUTE_GC_ELASTICITY, "gc_elasticity" },
517 { NET_IPV6_ROUTE_MTU_EXPIRES, "mtu_expires" },
518 { NET_IPV6_ROUTE_MIN_ADVMSS, "min_adv_mss" },
519 { NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
520 {}
521};
522
523static const struct trans_ctl_table trans_net_ipv6_icmp_table[] = {
524 { NET_IPV6_ICMP_RATELIMIT, "ratelimit" },
525 {}
526};
527
528static const struct trans_ctl_table trans_net_ipv6_table[] = {
529 { NET_IPV6_CONF, "conf", trans_net_ipv6_conf_table },
530 { NET_IPV6_NEIGH, "neigh", trans_net_neigh_table },
531 { NET_IPV6_ROUTE, "route", trans_net_ipv6_route_table },
532 { NET_IPV6_ICMP, "icmp", trans_net_ipv6_icmp_table },
533 { NET_IPV6_BINDV6ONLY, "bindv6only" },
534 { NET_IPV6_IP6FRAG_HIGH_THRESH, "ip6frag_high_thresh" },
535 { NET_IPV6_IP6FRAG_LOW_THRESH, "ip6frag_low_thresh" },
536 { NET_IPV6_IP6FRAG_TIME, "ip6frag_time" },
537 { NET_IPV6_IP6FRAG_SECRET_INTERVAL, "ip6frag_secret_interval" },
538 { NET_IPV6_MLD_MAX_MSF, "mld_max_msf" },
539 { 2088 /* IPQ_QMAX */, "ip6_queue_maxlen" },
540 {}
541};
542
543static const struct trans_ctl_table trans_net_x25_table[] = {
544 { NET_X25_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
545 { NET_X25_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
546 { NET_X25_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
547 { NET_X25_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
548 { NET_X25_ACK_HOLD_BACK_TIMEOUT, "acknowledgement_hold_back_timeout" },
549 { NET_X25_FORWARD, "x25_forward" },
550 {}
551};
552
553static const struct trans_ctl_table trans_net_tr_table[] = {
554 { NET_TR_RIF_TIMEOUT, "rif_timeout" },
555 {}
556};
557
558
559static const struct trans_ctl_table trans_net_decnet_conf_vars[] = {
560 { NET_DECNET_CONF_DEV_FORWARDING, "forwarding" },
561 { NET_DECNET_CONF_DEV_PRIORITY, "priority" },
562 { NET_DECNET_CONF_DEV_T2, "t2" },
563 { NET_DECNET_CONF_DEV_T3, "t3" },
564 {}
565};
566
567static const struct trans_ctl_table trans_net_decnet_conf[] = {
568 { 0, NULL, trans_net_decnet_conf_vars },
569 {}
570};
571
572static const struct trans_ctl_table trans_net_decnet_table[] = {
573 { NET_DECNET_CONF, "conf", trans_net_decnet_conf },
574 { NET_DECNET_NODE_ADDRESS, "node_address" },
575 { NET_DECNET_NODE_NAME, "node_name" },
576 { NET_DECNET_DEFAULT_DEVICE, "default_device" },
577 { NET_DECNET_TIME_WAIT, "time_wait" },
578 { NET_DECNET_DN_COUNT, "dn_count" },
579 { NET_DECNET_DI_COUNT, "di_count" },
580 { NET_DECNET_DR_COUNT, "dr_count" },
581 { NET_DECNET_DST_GC_INTERVAL, "dst_gc_interval" },
582 { NET_DECNET_NO_FC_MAX_CWND, "no_fc_max_cwnd" },
583 { NET_DECNET_MEM, "decnet_mem" },
584 { NET_DECNET_RMEM, "decnet_rmem" },
585 { NET_DECNET_WMEM, "decnet_wmem" },
586 { NET_DECNET_DEBUG_LEVEL, "debug" },
587 {}
588};
589
590static const struct trans_ctl_table trans_net_sctp_table[] = {
591 { NET_SCTP_RTO_INITIAL, "rto_initial" },
592 { NET_SCTP_RTO_MIN, "rto_min" },
593 { NET_SCTP_RTO_MAX, "rto_max" },
594 { NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor" },
595 { NET_SCTP_RTO_BETA, "rto_beta_exp_divisor" },
596 { NET_SCTP_VALID_COOKIE_LIFE, "valid_cookie_life" },
597 { NET_SCTP_ASSOCIATION_MAX_RETRANS, "association_max_retrans" },
598 { NET_SCTP_PATH_MAX_RETRANS, "path_max_retrans" },
599 { NET_SCTP_MAX_INIT_RETRANSMITS, "max_init_retransmits" },
600 { NET_SCTP_HB_INTERVAL, "hb_interval" },
601 { NET_SCTP_PRESERVE_ENABLE, "cookie_preserve_enable" },
602 { NET_SCTP_MAX_BURST, "max_burst" },
603 { NET_SCTP_ADDIP_ENABLE, "addip_enable" },
604 { NET_SCTP_PRSCTP_ENABLE, "prsctp_enable" },
605 { NET_SCTP_SNDBUF_POLICY, "sndbuf_policy" },
606 { NET_SCTP_SACK_TIMEOUT, "sack_timeout" },
607 { NET_SCTP_RCVBUF_POLICY, "rcvbuf_policy" },
608 {}
609};
610
611static const struct trans_ctl_table trans_net_llc_llc2_timeout_table[] = {
612 { NET_LLC2_ACK_TIMEOUT, "ack" },
613 { NET_LLC2_P_TIMEOUT, "p" },
614 { NET_LLC2_REJ_TIMEOUT, "rej" },
615 { NET_LLC2_BUSY_TIMEOUT, "busy" },
616 {}
617};
618
619static const struct trans_ctl_table trans_net_llc_station_table[] = {
620 { NET_LLC_STATION_ACK_TIMEOUT, "ack_timeout" },
621 {}
622};
623
624static const struct trans_ctl_table trans_net_llc_llc2_table[] = {
625 { NET_LLC2, "timeout", trans_net_llc_llc2_timeout_table },
626 {}
627};
628
629static const struct trans_ctl_table trans_net_llc_table[] = {
630 { NET_LLC2, "llc2", trans_net_llc_llc2_table },
631 { NET_LLC_STATION, "station", trans_net_llc_station_table },
632 {}
633};
634
635static const struct trans_ctl_table trans_net_netfilter_table[] = {
636 { NET_NF_CONNTRACK_MAX, "nf_conntrack_max" },
637 { NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "nf_conntrack_tcp_timeout_syn_sent" },
638 { NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "nf_conntrack_tcp_timeout_syn_recv" },
639 { NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "nf_conntrack_tcp_timeout_established" },
640 { NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "nf_conntrack_tcp_timeout_fin_wait" },
641 { NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "nf_conntrack_tcp_timeout_close_wait" },
642 { NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "nf_conntrack_tcp_timeout_last_ack" },
643 { NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "nf_conntrack_tcp_timeout_time_wait" },
644 { NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "nf_conntrack_tcp_timeout_close" },
645 { NET_NF_CONNTRACK_UDP_TIMEOUT, "nf_conntrack_udp_timeout" },
646 { NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "nf_conntrack_udp_timeout_stream" },
647 { NET_NF_CONNTRACK_ICMP_TIMEOUT, "nf_conntrack_icmp_timeout" },
648 { NET_NF_CONNTRACK_GENERIC_TIMEOUT, "nf_conntrack_generic_timeout" },
649 { NET_NF_CONNTRACK_BUCKETS, "nf_conntrack_buckets" },
650 { NET_NF_CONNTRACK_LOG_INVALID, "nf_conntrack_log_invalid" },
651 { NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, "nf_conntrack_tcp_timeout_max_retrans" },
652 { NET_NF_CONNTRACK_TCP_LOOSE, "nf_conntrack_tcp_loose" },
653 { NET_NF_CONNTRACK_TCP_BE_LIBERAL, "nf_conntrack_tcp_be_liberal" },
654 { NET_NF_CONNTRACK_TCP_MAX_RETRANS, "nf_conntrack_tcp_max_retrans" },
655 { NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, "nf_conntrack_sctp_timeout_closed" },
656 { NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, "nf_conntrack_sctp_timeout_cookie_wait" },
657 { NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, "nf_conntrack_sctp_timeout_cookie_echoed" },
658 { NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, "nf_conntrack_sctp_timeout_established" },
659 { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, "nf_conntrack_sctp_timeout_shutdown_sent" },
660 { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, "nf_conntrack_sctp_timeout_shutdown_recd" },
661 { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, "nf_conntrack_sctp_timeout_shutdown_ack_sent" },
662 { NET_NF_CONNTRACK_COUNT, "nf_conntrack_count" },
663 { NET_NF_CONNTRACK_ICMPV6_TIMEOUT, "nf_conntrack_icmpv6_timeout" },
664 { NET_NF_CONNTRACK_FRAG6_TIMEOUT, "nf_conntrack_frag6_timeout" },
665 { NET_NF_CONNTRACK_FRAG6_LOW_THRESH, "nf_conntrack_frag6_low_thresh" },
666 { NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, "nf_conntrack_frag6_high_thresh" },
667 { NET_NF_CONNTRACK_CHECKSUM, "nf_conntrack_checksum" },
668
669 {}
670};
671
672static const struct trans_ctl_table trans_net_dccp_table[] = {
673 { NET_DCCP_DEFAULT, "default" },
674 {}
675};
676
677static const struct trans_ctl_table trans_net_irda_table[] = {
678 { NET_IRDA_DISCOVERY, "discovery" },
679 { NET_IRDA_DEVNAME, "devname" },
680 { NET_IRDA_DEBUG, "debug" },
681 { NET_IRDA_FAST_POLL, "fast_poll_increase" },
682 { NET_IRDA_DISCOVERY_SLOTS, "discovery_slots" },
683 { NET_IRDA_DISCOVERY_TIMEOUT, "discovery_timeout" },
684 { NET_IRDA_SLOT_TIMEOUT, "slot_timeout" },
685 { NET_IRDA_MAX_BAUD_RATE, "max_baud_rate" },
686 { NET_IRDA_MIN_TX_TURN_TIME, "min_tx_turn_time" },
687 { NET_IRDA_MAX_TX_DATA_SIZE, "max_tx_data_size" },
688 { NET_IRDA_MAX_TX_WINDOW, "max_tx_window" },
689 { NET_IRDA_MAX_NOREPLY_TIME, "max_noreply_time" },
690 { NET_IRDA_WARN_NOREPLY_TIME, "warn_noreply_time" },
691 { NET_IRDA_LAP_KEEPALIVE_TIME, "lap_keepalive_time" },
692 {}
693};
694
695static const struct trans_ctl_table trans_net_table[] = {
696 { NET_CORE, "core", trans_net_core_table },
697 /* NET_ETHER not used */
698 /* NET_802 not used */
699 { NET_UNIX, "unix", trans_net_unix_table },
700 { NET_IPV4, "ipv4", trans_net_ipv4_table },
701 { NET_IPX, "ipx", trans_net_ipx_table },
702 { NET_ATALK, "appletalk", trans_net_atalk_table },
703 { NET_NETROM, "netrom", trans_net_netrom_table },
704 { NET_AX25, "ax25", trans_net_ax25_table },
705 { NET_BRIDGE, "bridge", trans_net_bridge_table },
706 { NET_ROSE, "rose", trans_net_rose_table },
707 { NET_IPV6, "ipv6", trans_net_ipv6_table },
708 { NET_X25, "x25", trans_net_x25_table },
709 { NET_TR, "token-ring", trans_net_tr_table },
710 { NET_DECNET, "decnet", trans_net_decnet_table },
711 /* NET_ECONET not used */
712 { NET_SCTP, "sctp", trans_net_sctp_table },
713 { NET_LLC, "llc", trans_net_llc_table },
714 { NET_NETFILTER, "netfilter", trans_net_netfilter_table },
715 { NET_DCCP, "dccp", trans_net_dccp_table },
716 { NET_IRDA, "irda", trans_net_irda_table },
717 { 2089, "nf_conntrack_max" },
718 {}
719};
720
721static const struct trans_ctl_table trans_fs_quota_table[] = {
722 { FS_DQ_LOOKUPS, "lookups" },
723 { FS_DQ_DROPS, "drops" },
724 { FS_DQ_READS, "reads" },
725 { FS_DQ_WRITES, "writes" },
726 { FS_DQ_CACHE_HITS, "cache_hits" },
727 { FS_DQ_ALLOCATED, "allocated_dquots" },
728 { FS_DQ_FREE, "free_dquots" },
729 { FS_DQ_SYNCS, "syncs" },
730 { FS_DQ_WARNINGS, "warnings" },
731 {}
732};
733
734static const struct trans_ctl_table trans_fs_xfs_table[] = {
735 { XFS_SGID_INHERIT, "irix_sgid_inherit" },
736 { XFS_SYMLINK_MODE, "irix_symlink_mode" },
737 { XFS_PANIC_MASK, "panic_mask" },
738
739 { XFS_ERRLEVEL, "error_level" },
740 { XFS_SYNCD_TIMER, "xfssyncd_centisecs" },
741 { XFS_INHERIT_SYNC, "inherit_sync" },
742 { XFS_INHERIT_NODUMP, "inherit_nodump" },
743 { XFS_INHERIT_NOATIME, "inherit_noatime" },
744 { XFS_BUF_TIMER, "xfsbufd_centisecs" },
745 { XFS_BUF_AGE, "age_buffer_centisecs" },
746 { XFS_INHERIT_NOSYM, "inherit_nosymlinks" },
747 { XFS_ROTORSTEP, "rotorstep" },
748 { XFS_INHERIT_NODFRG, "inherit_nodefrag" },
749 { XFS_FILESTREAM_TIMER, "filestream_centisecs" },
750 { XFS_STATS_CLEAR, "stats_clear" },
751 {}
752};
753
754static const struct trans_ctl_table trans_fs_ocfs2_nm_table[] = {
755 { 1, "hb_ctl_path" },
756 {}
757};
758
759static const struct trans_ctl_table trans_fs_ocfs2_table[] = {
760 { 1, "nm", trans_fs_ocfs2_nm_table },
761 {}
762};
763
764static const struct trans_ctl_table trans_inotify_table[] = {
765 { INOTIFY_MAX_USER_INSTANCES, "max_user_instances" },
766 { INOTIFY_MAX_USER_WATCHES, "max_user_watches" },
767 { INOTIFY_MAX_QUEUED_EVENTS, "max_queued_events" },
768 {}
769};
770
771static const struct trans_ctl_table trans_fs_table[] = {
772 { FS_NRINODE, "inode-nr" },
773 { FS_STATINODE, "inode-state" },
774 /* FS_MAXINODE unused */
775 /* FS_NRDQUOT unused */
776 /* FS_MAXDQUOT unused */
777 { FS_NRFILE, "file-nr" },
778 { FS_MAXFILE, "file-max" },
779 { FS_DENTRY, "dentry-state" },
780 /* FS_NRSUPER unused */
781 /* FS_MAXUPSER unused */
782 { FS_OVERFLOWUID, "overflowuid" },
783 { FS_OVERFLOWGID, "overflowgid" },
784 { FS_LEASES, "leases-enable" },
785 { FS_DIR_NOTIFY, "dir-notify-enable" },
786 { FS_LEASE_TIME, "lease-break-time" },
787 { FS_DQSTATS, "quota", trans_fs_quota_table },
788 { FS_XFS, "xfs", trans_fs_xfs_table },
789 { FS_AIO_NR, "aio-nr" },
790 { FS_AIO_MAX_NR, "aio-max-nr" },
791 { FS_INOTIFY, "inotify", trans_inotify_table },
792 { FS_OCFS2, "ocfs2", trans_fs_ocfs2_table },
793 { KERN_SETUID_DUMPABLE, "suid_dumpable" },
794 {}
795};
796
797static const struct trans_ctl_table trans_debug_table[] = {
798 {}
799};
800
801static const struct trans_ctl_table trans_cdrom_table[] = {
802 { DEV_CDROM_INFO, "info" },
803 { DEV_CDROM_AUTOCLOSE, "autoclose" },
804 { DEV_CDROM_AUTOEJECT, "autoeject" },
805 { DEV_CDROM_DEBUG, "debug" },
806 { DEV_CDROM_LOCK, "lock" },
807 { DEV_CDROM_CHECK_MEDIA, "check_media" },
808 {}
809};
810
811static const struct trans_ctl_table trans_ipmi_table[] = {
812 { DEV_IPMI_POWEROFF_POWERCYCLE, "poweroff_powercycle" },
813 {}
814};
815
816static const struct trans_ctl_table trans_mac_hid_files[] = {
817 /* DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES unused */
818 /* DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES unused */
819 { DEV_MAC_HID_MOUSE_BUTTON_EMULATION, "mouse_button_emulation" },
820 { DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, "mouse_button2_keycode" },
821 { DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, "mouse_button3_keycode" },
822 /* DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES unused */
823 {}
824};
825
826static const struct trans_ctl_table trans_raid_table[] = {
827 { DEV_RAID_SPEED_LIMIT_MIN, "speed_limit_min" },
828 { DEV_RAID_SPEED_LIMIT_MAX, "speed_limit_max" },
829 {}
830};
831
832static const struct trans_ctl_table trans_scsi_table[] = {
833 { DEV_SCSI_LOGGING_LEVEL, "logging_level" },
834 {}
835};
836
837static const struct trans_ctl_table trans_parport_default_table[] = {
838 { DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice" },
839 { DEV_PARPORT_DEFAULT_SPINTIME, "spintime" },
840 {}
841};
842
843static const struct trans_ctl_table trans_parport_device_table[] = {
844 { DEV_PARPORT_DEVICE_TIMESLICE, "timeslice" },
845 {}
846};
847
848static const struct trans_ctl_table trans_parport_devices_table[] = {
849 { DEV_PARPORT_DEVICES_ACTIVE, "active" },
850 { 0, NULL, trans_parport_device_table },
851 {}
852};
853
854static const struct trans_ctl_table trans_parport_parport_table[] = {
855 { DEV_PARPORT_SPINTIME, "spintime" },
856 { DEV_PARPORT_BASE_ADDR, "base-addr" },
857 { DEV_PARPORT_IRQ, "irq" },
858 { DEV_PARPORT_DMA, "dma" },
859 { DEV_PARPORT_MODES, "modes" },
860 { DEV_PARPORT_DEVICES, "devices", trans_parport_devices_table },
861 { DEV_PARPORT_AUTOPROBE, "autoprobe" },
862 { DEV_PARPORT_AUTOPROBE + 1, "autoprobe0" },
863 { DEV_PARPORT_AUTOPROBE + 2, "autoprobe1" },
864 { DEV_PARPORT_AUTOPROBE + 3, "autoprobe2" },
865 { DEV_PARPORT_AUTOPROBE + 4, "autoprobe3" },
866 {}
867};
868static const struct trans_ctl_table trans_parport_table[] = {
869 { DEV_PARPORT_DEFAULT, "default", trans_parport_default_table },
870 { 0, NULL, trans_parport_parport_table },
871 {}
872};
873
874static const struct trans_ctl_table trans_dev_table[] = {
875 { DEV_CDROM, "cdrom", trans_cdrom_table },
876 /* DEV_HWMON unused */
877 { DEV_PARPORT, "parport", trans_parport_table },
878 { DEV_RAID, "raid", trans_raid_table },
879 { DEV_MAC_HID, "mac_hid", trans_mac_hid_files },
880 { DEV_SCSI, "scsi", trans_scsi_table },
881 { DEV_IPMI, "ipmi", trans_ipmi_table },
882 {}
883};
884
885static const struct trans_ctl_table trans_bus_isa_table[] = {
886 { BUS_ISA_MEM_BASE, "membase" },
887 { BUS_ISA_PORT_BASE, "portbase" },
888 { BUS_ISA_PORT_SHIFT, "portshift" },
889 {}
890};
891
892static const struct trans_ctl_table trans_bus_table[] = {
893 { CTL_BUS_ISA, "isa", trans_bus_isa_table },
894 {}
895};
896
897static const struct trans_ctl_table trans_arlan_conf_table0[] = {
898 { 1, "spreadingCode" },
899 { 2, "channelNumber" },
900 { 3, "scramblingDisable" },
901 { 4, "txAttenuation" },
902 { 5, "systemId" },
903 { 6, "maxDatagramSize" },
904 { 7, "maxFrameSize" },
905 { 8, "maxRetries" },
906 { 9, "receiveMode" },
907 { 10, "priority" },
908 { 11, "rootOrRepeater" },
909 { 12, "SID" },
910 { 13, "registrationMode" },
911 { 14, "registrationFill" },
912 { 15, "localTalkAddress" },
913 { 16, "codeFormat" },
914 { 17, "numChannels" },
915 { 18, "channel1" },
916 { 19, "channel2" },
917 { 20, "channel3" },
918 { 21, "channel4" },
919 { 22, "txClear" },
920 { 23, "txRetries" },
921 { 24, "txRouting" },
922 { 25, "txScrambled" },
923 { 26, "rxParameter" },
924 { 27, "txTimeoutMs" },
925 { 28, "waitCardTimeout" },
926 { 29, "channelSet" },
927 { 30, "name" },
928 { 31, "waitTime" },
929 { 32, "lParameter" },
930 { 33, "_15" },
931 { 34, "headerSize" },
932 { 36, "tx_delay_ms" },
933 { 37, "retries" },
934 { 38, "ReTransmitPacketMaxSize" },
935 { 39, "waitReTransmitPacketMaxSize" },
936 { 40, "fastReTransCount" },
937 { 41, "driverRetransmissions" },
938 { 42, "txAckTimeoutMs" },
939 { 43, "registrationInterrupts" },
940 { 44, "hardwareType" },
941 { 45, "radioType" },
942 { 46, "writeEEPROM" },
943 { 47, "writeRadioType" },
944 { 48, "entry_exit_debug" },
945 { 49, "debug" },
946 { 50, "in_speed" },
947 { 51, "out_speed" },
948 { 52, "in_speed10" },
949 { 53, "out_speed10" },
950 { 54, "in_speed_max" },
951 { 55, "out_speed_max" },
952 { 56, "measure_rate" },
953 { 57, "pre_Command_Wait" },
954 { 58, "rx_tweak1" },
955 { 59, "rx_tweak2" },
956 { 60, "tx_queue_len" },
957
958 { 150, "arlan0-txRing" },
959 { 151, "arlan0-rxRing" },
960 { 152, "arlan0-18" },
961 { 153, "arlan0-ring" },
962 { 154, "arlan0-shm-cpy" },
963 { 155, "config0" },
964 { 156, "reset0" },
965 {}
966};
967
968static const struct trans_ctl_table trans_arlan_conf_table1[] = {
969 { 1, "spreadingCode" },
970 { 2, "channelNumber" },
971 { 3, "scramblingDisable" },
972 { 4, "txAttenuation" },
973 { 5, "systemId" },
974 { 6, "maxDatagramSize" },
975 { 7, "maxFrameSize" },
976 { 8, "maxRetries" },
977 { 9, "receiveMode" },
978 { 10, "priority" },
979 { 11, "rootOrRepeater" },
980 { 12, "SID" },
981 { 13, "registrationMode" },
982 { 14, "registrationFill" },
983 { 15, "localTalkAddress" },
984 { 16, "codeFormat" },
985 { 17, "numChannels" },
986 { 18, "channel1" },
987 { 19, "channel2" },
988 { 20, "channel3" },
989 { 21, "channel4" },
990 { 22, "txClear" },
991 { 23, "txRetries" },
992 { 24, "txRouting" },
993 { 25, "txScrambled" },
994 { 26, "rxParameter" },
995 { 27, "txTimeoutMs" },
996 { 28, "waitCardTimeout" },
997 { 29, "channelSet" },
998 { 30, "name" },
999 { 31, "waitTime" },
1000 { 32, "lParameter" },
1001 { 33, "_15" },
1002 { 34, "headerSize" },
1003 { 36, "tx_delay_ms" },
1004 { 37, "retries" },
1005 { 38, "ReTransmitPacketMaxSize" },
1006 { 39, "waitReTransmitPacketMaxSize" },
1007 { 40, "fastReTransCount" },
1008 { 41, "driverRetransmissions" },
1009 { 42, "txAckTimeoutMs" },
1010 { 43, "registrationInterrupts" },
1011 { 44, "hardwareType" },
1012 { 45, "radioType" },
1013 { 46, "writeEEPROM" },
1014 { 47, "writeRadioType" },
1015 { 48, "entry_exit_debug" },
1016 { 49, "debug" },
1017 { 50, "in_speed" },
1018 { 51, "out_speed" },
1019 { 52, "in_speed10" },
1020 { 53, "out_speed10" },
1021 { 54, "in_speed_max" },
1022 { 55, "out_speed_max" },
1023 { 56, "measure_rate" },
1024 { 57, "pre_Command_Wait" },
1025 { 58, "rx_tweak1" },
1026 { 59, "rx_tweak2" },
1027 { 60, "tx_queue_len" },
1028
1029 { 150, "arlan1-txRing" },
1030 { 151, "arlan1-rxRing" },
1031 { 152, "arlan1-18" },
1032 { 153, "arlan1-ring" },
1033 { 154, "arlan1-shm-cpy" },
1034 { 155, "config1" },
1035 { 156, "reset1" },
1036 {}
1037};
1038
1039static const struct trans_ctl_table trans_arlan_conf_table2[] = {
1040 { 1, "spreadingCode" },
1041 { 2, "channelNumber" },
1042 { 3, "scramblingDisable" },
1043 { 4, "txAttenuation" },
1044 { 5, "systemId" },
1045 { 6, "maxDatagramSize" },
1046 { 7, "maxFrameSize" },
1047 { 8, "maxRetries" },
1048 { 9, "receiveMode" },
1049 { 10, "priority" },
1050 { 11, "rootOrRepeater" },
1051 { 12, "SID" },
1052 { 13, "registrationMode" },
1053 { 14, "registrationFill" },
1054 { 15, "localTalkAddress" },
1055 { 16, "codeFormat" },
1056 { 17, "numChannels" },
1057 { 18, "channel1" },
1058 { 19, "channel2" },
1059 { 20, "channel3" },
1060 { 21, "channel4" },
1061 { 22, "txClear" },
1062 { 23, "txRetries" },
1063 { 24, "txRouting" },
1064 { 25, "txScrambled" },
1065 { 26, "rxParameter" },
1066 { 27, "txTimeoutMs" },
1067 { 28, "waitCardTimeout" },
1068 { 29, "channelSet" },
1069 { 30, "name" },
1070 { 31, "waitTime" },
1071 { 32, "lParameter" },
1072 { 33, "_15" },
1073 { 34, "headerSize" },
1074 { 36, "tx_delay_ms" },
1075 { 37, "retries" },
1076 { 38, "ReTransmitPacketMaxSize" },
1077 { 39, "waitReTransmitPacketMaxSize" },
1078 { 40, "fastReTransCount" },
1079 { 41, "driverRetransmissions" },
1080 { 42, "txAckTimeoutMs" },
1081 { 43, "registrationInterrupts" },
1082 { 44, "hardwareType" },
1083 { 45, "radioType" },
1084 { 46, "writeEEPROM" },
1085 { 47, "writeRadioType" },
1086 { 48, "entry_exit_debug" },
1087 { 49, "debug" },
1088 { 50, "in_speed" },
1089 { 51, "out_speed" },
1090 { 52, "in_speed10" },
1091 { 53, "out_speed10" },
1092 { 54, "in_speed_max" },
1093 { 55, "out_speed_max" },
1094 { 56, "measure_rate" },
1095 { 57, "pre_Command_Wait" },
1096 { 58, "rx_tweak1" },
1097 { 59, "rx_tweak2" },
1098 { 60, "tx_queue_len" },
1099
1100 { 150, "arlan2-txRing" },
1101 { 151, "arlan2-rxRing" },
1102 { 152, "arlan2-18" },
1103 { 153, "arlan2-ring" },
1104 { 154, "arlan2-shm-cpy" },
1105 { 155, "config2" },
1106 { 156, "reset2" },
1107 {}
1108};
1109
1110static const struct trans_ctl_table trans_arlan_conf_table3[] = {
1111 { 1, "spreadingCode" },
1112 { 2, "channelNumber" },
1113 { 3, "scramblingDisable" },
1114 { 4, "txAttenuation" },
1115 { 5, "systemId" },
1116 { 6, "maxDatagramSize" },
1117 { 7, "maxFrameSize" },
1118 { 8, "maxRetries" },
1119 { 9, "receiveMode" },
1120 { 10, "priority" },
1121 { 11, "rootOrRepeater" },
1122 { 12, "SID" },
1123 { 13, "registrationMode" },
1124 { 14, "registrationFill" },
1125 { 15, "localTalkAddress" },
1126 { 16, "codeFormat" },
1127 { 17, "numChannels" },
1128 { 18, "channel1" },
1129 { 19, "channel2" },
1130 { 20, "channel3" },
1131 { 21, "channel4" },
1132 { 22, "txClear" },
1133 { 23, "txRetries" },
1134 { 24, "txRouting" },
1135 { 25, "txScrambled" },
1136 { 26, "rxParameter" },
1137 { 27, "txTimeoutMs" },
1138 { 28, "waitCardTimeout" },
1139 { 29, "channelSet" },
1140 { 30, "name" },
1141 { 31, "waitTime" },
1142 { 32, "lParameter" },
1143 { 33, "_15" },
1144 { 34, "headerSize" },
1145 { 36, "tx_delay_ms" },
1146 { 37, "retries" },
1147 { 38, "ReTransmitPacketMaxSize" },
1148 { 39, "waitReTransmitPacketMaxSize" },
1149 { 40, "fastReTransCount" },
1150 { 41, "driverRetransmissions" },
1151 { 42, "txAckTimeoutMs" },
1152 { 43, "registrationInterrupts" },
1153 { 44, "hardwareType" },
1154 { 45, "radioType" },
1155 { 46, "writeEEPROM" },
1156 { 47, "writeRadioType" },
1157 { 48, "entry_exit_debug" },
1158 { 49, "debug" },
1159 { 50, "in_speed" },
1160 { 51, "out_speed" },
1161 { 52, "in_speed10" },
1162 { 53, "out_speed10" },
1163 { 54, "in_speed_max" },
1164 { 55, "out_speed_max" },
1165 { 56, "measure_rate" },
1166 { 57, "pre_Command_Wait" },
1167 { 58, "rx_tweak1" },
1168 { 59, "rx_tweak2" },
1169 { 60, "tx_queue_len" },
1170
1171 { 150, "arlan3-txRing" },
1172 { 151, "arlan3-rxRing" },
1173 { 152, "arlan3-18" },
1174 { 153, "arlan3-ring" },
1175 { 154, "arlan3-shm-cpy" },
1176 { 155, "config3" },
1177 { 156, "reset3" },
1178 {}
1179};
1180
1181static const struct trans_ctl_table trans_arlan_table[] = {
1182 { 1, "arlan0", trans_arlan_conf_table0 },
1183 { 2, "arlan1", trans_arlan_conf_table1 },
1184 { 3, "arlan2", trans_arlan_conf_table2 },
1185 { 4, "arlan3", trans_arlan_conf_table3 },
1186 {}
1187};
1188
1189static const struct trans_ctl_table trans_s390dbf_table[] = {
1190 { 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" },
1191 { 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" },
1192 {}
1193};
1194
1195static const struct trans_ctl_table trans_sunrpc_table[] = {
1196 { CTL_RPCDEBUG, "rpc_debug" },
1197 { CTL_NFSDEBUG, "nfs_debug" },
1198 { CTL_NFSDDEBUG, "nfsd_debug" },
1199 { CTL_NLMDEBUG, "nlm_debug" },
1200 { CTL_SLOTTABLE_UDP, "udp_slot_table_entries" },
1201 { CTL_SLOTTABLE_TCP, "tcp_slot_table_entries" },
1202 { CTL_MIN_RESVPORT, "min_resvport" },
1203 { CTL_MAX_RESVPORT, "max_resvport" },
1204 {}
1205};
1206
1207static const struct trans_ctl_table trans_pm_table[] = {
1208 { 1 /* CTL_PM_SUSPEND */, "suspend" },
1209 { 2 /* CTL_PM_CMODE */, "cmode" },
1210 { 3 /* CTL_PM_P0 */, "p0" },
1211 { 4 /* CTL_PM_CM */, "cm" },
1212 {}
1213};
1214
1215static const struct trans_ctl_table trans_frv_table[] = {
1216 { 1, "cache-mode" },
1217 { 2, "pin-cxnr" },
1218 {}
1219};
1220
1221static const struct trans_ctl_table trans_root_table[] = {
1222 { CTL_KERN, "kernel", trans_kern_table },
1223 { CTL_VM, "vm", trans_vm_table },
1224 { CTL_NET, "net", trans_net_table },
1225 /* CTL_PROC not used */
1226 { CTL_FS, "fs", trans_fs_table },
1227 { CTL_DEBUG, "debug", trans_debug_table },
1228 { CTL_DEV, "dev", trans_dev_table },
1229 { CTL_BUS, "bus", trans_bus_table },
1230 { CTL_ABI, "abi" },
1231 /* CTL_CPU not used */
1232 { CTL_ARLAN, "arlan", trans_arlan_table },
1233 { CTL_S390DBF, "s390dbf", trans_s390dbf_table },
1234 { CTL_SUNRPC, "sunrpc", trans_sunrpc_table },
1235 { CTL_PM, "pm", trans_pm_table },
1236 { CTL_FRV, "frv", trans_frv_table },
1237 {}
1238};
1239
1240
1241
1242 8
1243static int sysctl_depth(struct ctl_table *table) 9static int sysctl_depth(struct ctl_table *table)
1244{ 10{
@@ -1262,47 +28,6 @@ static struct ctl_table *sysctl_parent(struct ctl_table *table, int n)
1262 return table; 28 return table;
1263} 29}
1264 30
1265static const struct trans_ctl_table *sysctl_binary_lookup(struct ctl_table *table)
1266{
1267 struct ctl_table *test;
1268 const struct trans_ctl_table *ref;
1269 int cur_depth;
1270
1271 cur_depth = sysctl_depth(table);
1272
1273 ref = trans_root_table;
1274repeat:
1275 test = sysctl_parent(table, cur_depth);
1276 for (; ref->ctl_name || ref->procname || ref->child; ref++) {
1277 int match = 0;
1278
1279 if (cur_depth && !ref->child)
1280 continue;
1281
1282 if (test->procname && ref->procname &&
1283 (strcmp(test->procname, ref->procname) == 0))
1284 match++;
1285
1286 if (test->ctl_name && ref->ctl_name &&
1287 (test->ctl_name == ref->ctl_name))
1288 match++;
1289
1290 if (!ref->ctl_name && !ref->procname)
1291 match++;
1292
1293 if (match) {
1294 if (cur_depth != 0) {
1295 cur_depth--;
1296 ref = ref->child;
1297 goto repeat;
1298 }
1299 goto out;
1300 }
1301 }
1302 ref = NULL;
1303out:
1304 return ref;
1305}
1306 31
1307static void sysctl_print_path(struct ctl_table *table) 32static void sysctl_print_path(struct ctl_table *table)
1308{ 33{
@@ -1316,26 +41,6 @@ static void sysctl_print_path(struct ctl_table *table)
1316 } 41 }
1317 } 42 }
1318 printk(" "); 43 printk(" ");
1319 if (table->ctl_name) {
1320 for (i = depth; i >= 0; i--) {
1321 tmp = sysctl_parent(table, i);
1322 printk(".%d", tmp->ctl_name);
1323 }
1324 }
1325}
1326
1327static void sysctl_repair_table(struct ctl_table *table)
1328{
1329 /* Don't complain about the classic default
1330 * sysctl strategy routine. Maybe later we
1331 * can get the tables fixed and complain about
1332 * this.
1333 */
1334 if (table->ctl_name && table->procname &&
1335 (table->proc_handler == proc_dointvec) &&
1336 (!table->strategy)) {
1337 table->strategy = sysctl_data;
1338 }
1339} 44}
1340 45
1341static struct ctl_table *sysctl_check_lookup(struct nsproxy *namespaces, 46static struct ctl_table *sysctl_check_lookup(struct nsproxy *namespaces,
@@ -1353,7 +58,7 @@ static struct ctl_table *sysctl_check_lookup(struct nsproxy *namespaces,
1353 ref = head->ctl_table; 58 ref = head->ctl_table;
1354repeat: 59repeat:
1355 test = sysctl_parent(table, cur_depth); 60 test = sysctl_parent(table, cur_depth);
1356 for (; ref->ctl_name || ref->procname; ref++) { 61 for (; ref->procname; ref++) {
1357 int match = 0; 62 int match = 0;
1358 if (cur_depth && !ref->child) 63 if (cur_depth && !ref->child)
1359 continue; 64 continue;
@@ -1362,10 +67,6 @@ repeat:
1362 (strcmp(test->procname, ref->procname) == 0)) 67 (strcmp(test->procname, ref->procname) == 0))
1363 match++; 68 match++;
1364 69
1365 if (test->ctl_name && ref->ctl_name &&
1366 (test->ctl_name == ref->ctl_name))
1367 match++;
1368
1369 if (match) { 70 if (match) {
1370 if (cur_depth != 0) { 71 if (cur_depth != 0) {
1371 cur_depth--; 72 cur_depth--;
@@ -1393,38 +94,6 @@ static void set_fail(const char **fail, struct ctl_table *table, const char *str
1393 *fail = str; 94 *fail = str;
1394} 95}
1395 96
1396static int sysctl_check_dir(struct nsproxy *namespaces,
1397 struct ctl_table *table)
1398{
1399 struct ctl_table *ref;
1400 int error;
1401
1402 error = 0;
1403 ref = sysctl_check_lookup(namespaces, table);
1404 if (ref) {
1405 int match = 0;
1406 if ((!table->procname && !ref->procname) ||
1407 (table->procname && ref->procname &&
1408 (strcmp(table->procname, ref->procname) == 0)))
1409 match++;
1410
1411 if ((!table->ctl_name && !ref->ctl_name) ||
1412 (table->ctl_name && ref->ctl_name &&
1413 (table->ctl_name == ref->ctl_name)))
1414 match++;
1415
1416 if (match != 2) {
1417 printk(KERN_ERR "%s: failed: ", __func__);
1418 sysctl_print_path(table);
1419 printk(" ref: ");
1420 sysctl_print_path(ref);
1421 printk("\n");
1422 error = -EINVAL;
1423 }
1424 }
1425 return error;
1426}
1427
1428static void sysctl_check_leaf(struct nsproxy *namespaces, 97static void sysctl_check_leaf(struct nsproxy *namespaces,
1429 struct ctl_table *table, const char **fail) 98 struct ctl_table *table, const char **fail)
1430{ 99{
@@ -1435,37 +104,15 @@ static void sysctl_check_leaf(struct nsproxy *namespaces,
1435 set_fail(fail, table, "Sysctl already exists"); 104 set_fail(fail, table, "Sysctl already exists");
1436} 105}
1437 106
1438static void sysctl_check_bin_path(struct ctl_table *table, const char **fail)
1439{
1440 const struct trans_ctl_table *ref;
1441
1442 ref = sysctl_binary_lookup(table);
1443 if (table->ctl_name && !ref)
1444 set_fail(fail, table, "Unknown sysctl binary path");
1445 if (ref) {
1446 if (ref->procname &&
1447 (!table->procname ||
1448 (strcmp(table->procname, ref->procname) != 0)))
1449 set_fail(fail, table, "procname does not match binary path procname");
1450
1451 if (ref->ctl_name && table->ctl_name &&
1452 (table->ctl_name != ref->ctl_name))
1453 set_fail(fail, table, "ctl_name does not match binary path ctl_name");
1454 }
1455}
1456
1457int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table) 107int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1458{ 108{
1459 int error = 0; 109 int error = 0;
1460 for (; table->ctl_name || table->procname; table++) { 110 for (; table->procname; table++) {
1461 const char *fail = NULL; 111 const char *fail = NULL;
1462 112
1463 sysctl_repair_table(table);
1464 if (table->parent) { 113 if (table->parent) {
1465 if (table->procname && !table->parent->procname) 114 if (table->procname && !table->parent->procname)
1466 set_fail(&fail, table, "Parent without procname"); 115 set_fail(&fail, table, "Parent without procname");
1467 if (table->ctl_name && !table->parent->ctl_name)
1468 set_fail(&fail, table, "Parent without ctl_name");
1469 } 116 }
1470 if (!table->procname) 117 if (!table->procname)
1471 set_fail(&fail, table, "No procname"); 118 set_fail(&fail, table, "No procname");
@@ -1478,21 +125,12 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1478 set_fail(&fail, table, "Writable sysctl directory"); 125 set_fail(&fail, table, "Writable sysctl directory");
1479 if (table->proc_handler) 126 if (table->proc_handler)
1480 set_fail(&fail, table, "Directory with proc_handler"); 127 set_fail(&fail, table, "Directory with proc_handler");
1481 if (table->strategy)
1482 set_fail(&fail, table, "Directory with strategy");
1483 if (table->extra1) 128 if (table->extra1)
1484 set_fail(&fail, table, "Directory with extra1"); 129 set_fail(&fail, table, "Directory with extra1");
1485 if (table->extra2) 130 if (table->extra2)
1486 set_fail(&fail, table, "Directory with extra2"); 131 set_fail(&fail, table, "Directory with extra2");
1487 if (sysctl_check_dir(namespaces, table))
1488 set_fail(&fail, table, "Inconsistent directory names");
1489 } else { 132 } else {
1490 if ((table->strategy == sysctl_data) || 133 if ((table->proc_handler == proc_dostring) ||
1491 (table->strategy == sysctl_string) ||
1492 (table->strategy == sysctl_intvec) ||
1493 (table->strategy == sysctl_jiffies) ||
1494 (table->strategy == sysctl_ms_jiffies) ||
1495 (table->proc_handler == proc_dostring) ||
1496 (table->proc_handler == proc_dointvec) || 134 (table->proc_handler == proc_dointvec) ||
1497 (table->proc_handler == proc_dointvec_minmax) || 135 (table->proc_handler == proc_dointvec_minmax) ||
1498 (table->proc_handler == proc_dointvec_jiffies) || 136 (table->proc_handler == proc_dointvec_jiffies) ||
@@ -1514,14 +152,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1514 set_fail(&fail, table, "No max"); 152 set_fail(&fail, table, "No max");
1515 } 153 }
1516 } 154 }
1517#ifdef CONFIG_SYSCTL_SYSCALL
1518 if (table->ctl_name && !table->strategy)
1519 set_fail(&fail, table, "Missing strategy");
1520#endif
1521#if 0
1522 if (!table->ctl_name && table->strategy)
1523 set_fail(&fail, table, "Strategy without ctl_name");
1524#endif
1525#ifdef CONFIG_PROC_SYSCTL 155#ifdef CONFIG_PROC_SYSCTL
1526 if (table->procname && !table->proc_handler) 156 if (table->procname && !table->proc_handler)
1527 set_fail(&fail, table, "No proc_handler"); 157 set_fail(&fail, table, "No proc_handler");
@@ -1532,7 +162,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1532#endif 162#endif
1533 sysctl_check_leaf(namespaces, table, &fail); 163 sysctl_check_leaf(namespaces, table, &fail);
1534 } 164 }
1535 sysctl_check_bin_path(table, &fail);
1536 if (table->mode > 0777) 165 if (table->mode > 0777)
1537 set_fail(&fail, table, "bogus .mode"); 166 set_fail(&fail, table, "bogus .mode");
1538 if (fail) { 167 if (fail) {
diff --git a/kernel/time.c b/kernel/time.c
index 2e2e469a7fec..804798005d19 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -662,6 +662,36 @@ u64 nsec_to_clock_t(u64 x)
662#endif 662#endif
663} 663}
664 664
665/**
666 * nsecs_to_jiffies - Convert nsecs in u64 to jiffies
667 *
668 * @n: nsecs in u64
669 *
670 * Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64.
671 * And this doesn't return MAX_JIFFY_OFFSET since this function is designed
672 * for scheduler, not for use in device drivers to calculate timeout value.
673 *
674 * note:
675 * NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
676 * ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
677 */
678unsigned long nsecs_to_jiffies(u64 n)
679{
680#if (NSEC_PER_SEC % HZ) == 0
681 /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
682 return div_u64(n, NSEC_PER_SEC / HZ);
683#elif (HZ % 512) == 0
684 /* overflow after 292 years if HZ = 1024 */
685 return div_u64(n * HZ / 512, NSEC_PER_SEC / 512);
686#else
687 /*
688 * Generic case - optimized for cases where HZ is a multiple of 3.
689 * overflow after 64.99 years, exact for HZ = 60, 72, 90, 120 etc.
690 */
691 return div_u64(n * 9, (9ull * NSEC_PER_SEC + HZ / 2) / HZ);
692#endif
693}
694
665#if (BITS_PER_LONG < 64) 695#if (BITS_PER_LONG < 64)
666u64 get_jiffies_64(void) 696u64 get_jiffies_64(void)
667{ 697{
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index b416512ad17f..d006554888dc 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -339,6 +339,27 @@ config POWER_TRACER
339 power management decisions, specifically the C-state and P-state 339 power management decisions, specifically the C-state and P-state
340 behavior. 340 behavior.
341 341
342config KSYM_TRACER
343 bool "Trace read and write access on kernel memory locations"
344 depends on HAVE_HW_BREAKPOINT
345 select TRACING
346 help
347 This tracer helps find read and write operations on any given kernel
348 symbol i.e. /proc/kallsyms.
349
350config PROFILE_KSYM_TRACER
351 bool "Profile all kernel memory accesses on 'watched' variables"
352 depends on KSYM_TRACER
353 help
354 This tracer profiles kernel accesses on variables watched through the
355 ksym tracer ftrace plugin. Depending upon the hardware, all read
356 and write operations on kernel variables can be monitored for
357 accesses.
358
359 The results will be displayed in:
360 /debugfs/tracing/profile_ksym
361
362 Say N if unsure.
342 363
343config STACK_TRACER 364config STACK_TRACER
344 bool "Trace max stack" 365 bool "Trace max stack"
@@ -428,6 +449,23 @@ config BLK_DEV_IO_TRACE
428 449
429 If unsure, say N. 450 If unsure, say N.
430 451
452config KPROBE_EVENT
453 depends on KPROBES
454 depends on X86
455 bool "Enable kprobes-based dynamic events"
456 select TRACING
457 default y
458 help
459 This allows the user to add tracing events (similar to tracepoints) on the fly
460 via the ftrace interface. See Documentation/trace/kprobetrace.txt
461 for more details.
462
463 Those events can be inserted wherever kprobes can probe, and record
464 various register and memory values.
465
466 This option is also required by perf-probe subcommand of perf tools. If
467 you want to use perf tools, this option is strongly recommended.
468
431config DYNAMIC_FTRACE 469config DYNAMIC_FTRACE
432 bool "enable/disable ftrace tracepoints dynamically" 470 bool "enable/disable ftrace tracepoints dynamically"
433 depends on FUNCTION_TRACER 471 depends on FUNCTION_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 26f03ac07c2b..cd9ecd89ec77 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_EVENT_TRACING) += trace_export.o
53obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o 53obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
54obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o 54obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
55obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o 55obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
56obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
57obj-$(CONFIG_KSYM_TRACER) += trace_ksym.o
56obj-$(CONFIG_EVENT_TRACING) += power-traces.o 58obj-$(CONFIG_EVENT_TRACING) += power-traces.o
57 59
58libftrace-y := ftrace.o 60libftrace-y := ftrace.o
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index a72c6e03deec..a1ca4956ab5e 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -397,18 +397,21 @@ int ring_buffer_print_page_header(struct trace_seq *s)
397 int ret; 397 int ret;
398 398
399 ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t" 399 ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t"
400 "offset:0;\tsize:%u;\n", 400 "offset:0;\tsize:%u;\tsigned:%u;\n",
401 (unsigned int)sizeof(field.time_stamp)); 401 (unsigned int)sizeof(field.time_stamp),
402 (unsigned int)is_signed_type(u64));
402 403
403 ret = trace_seq_printf(s, "\tfield: local_t commit;\t" 404 ret = trace_seq_printf(s, "\tfield: local_t commit;\t"
404 "offset:%u;\tsize:%u;\n", 405 "offset:%u;\tsize:%u;\tsigned:%u;\n",
405 (unsigned int)offsetof(typeof(field), commit), 406 (unsigned int)offsetof(typeof(field), commit),
406 (unsigned int)sizeof(field.commit)); 407 (unsigned int)sizeof(field.commit),
408 (unsigned int)is_signed_type(long));
407 409
408 ret = trace_seq_printf(s, "\tfield: char data;\t" 410 ret = trace_seq_printf(s, "\tfield: char data;\t"
409 "offset:%u;\tsize:%u;\n", 411 "offset:%u;\tsize:%u;\tsigned:%u;\n",
410 (unsigned int)offsetof(typeof(field), data), 412 (unsigned int)offsetof(typeof(field), data),
411 (unsigned int)BUF_PAGE_SIZE); 413 (unsigned int)BUF_PAGE_SIZE,
414 (unsigned int)is_signed_type(char));
412 415
413 return ret; 416 return ret;
414} 417}
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index acef8b4636f0..1d7f4830a80d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -11,6 +11,7 @@
11#include <linux/ftrace.h> 11#include <linux/ftrace.h>
12#include <trace/boot.h> 12#include <trace/boot.h>
13#include <linux/kmemtrace.h> 13#include <linux/kmemtrace.h>
14#include <linux/hw_breakpoint.h>
14 15
15#include <linux/trace_seq.h> 16#include <linux/trace_seq.h>
16#include <linux/ftrace_event.h> 17#include <linux/ftrace_event.h>
@@ -37,6 +38,7 @@ enum trace_type {
37 TRACE_KMEM_ALLOC, 38 TRACE_KMEM_ALLOC,
38 TRACE_KMEM_FREE, 39 TRACE_KMEM_FREE,
39 TRACE_BLK, 40 TRACE_BLK,
41 TRACE_KSYM,
40 42
41 __TRACE_LAST_TYPE, 43 __TRACE_LAST_TYPE,
42}; 44};
@@ -98,9 +100,32 @@ struct syscall_trace_enter {
98struct syscall_trace_exit { 100struct syscall_trace_exit {
99 struct trace_entry ent; 101 struct trace_entry ent;
100 int nr; 102 int nr;
101 unsigned long ret; 103 long ret;
102}; 104};
103 105
106struct kprobe_trace_entry {
107 struct trace_entry ent;
108 unsigned long ip;
109 int nargs;
110 unsigned long args[];
111};
112
113#define SIZEOF_KPROBE_TRACE_ENTRY(n) \
114 (offsetof(struct kprobe_trace_entry, args) + \
115 (sizeof(unsigned long) * (n)))
116
117struct kretprobe_trace_entry {
118 struct trace_entry ent;
119 unsigned long func;
120 unsigned long ret_ip;
121 int nargs;
122 unsigned long args[];
123};
124
125#define SIZEOF_KRETPROBE_TRACE_ENTRY(n) \
126 (offsetof(struct kretprobe_trace_entry, args) + \
127 (sizeof(unsigned long) * (n)))
128
104/* 129/*
105 * trace_flag_type is an enumeration that holds different 130 * trace_flag_type is an enumeration that holds different
106 * states when a trace occurs. These are: 131 * states when a trace occurs. These are:
@@ -209,6 +234,7 @@ extern void __ftrace_bad_type(void);
209 TRACE_KMEM_ALLOC); \ 234 TRACE_KMEM_ALLOC); \
210 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ 235 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
211 TRACE_KMEM_FREE); \ 236 TRACE_KMEM_FREE); \
237 IF_ASSIGN(var, ent, struct ksym_trace_entry, TRACE_KSYM);\
212 __ftrace_bad_type(); \ 238 __ftrace_bad_type(); \
213 } while (0) 239 } while (0)
214 240
@@ -364,6 +390,8 @@ int register_tracer(struct tracer *type);
364void unregister_tracer(struct tracer *type); 390void unregister_tracer(struct tracer *type);
365int is_tracing_stopped(void); 391int is_tracing_stopped(void);
366 392
393extern int process_new_ksym_entry(char *ksymname, int op, unsigned long addr);
394
367extern unsigned long nsecs_to_usecs(unsigned long nsecs); 395extern unsigned long nsecs_to_usecs(unsigned long nsecs);
368 396
369#ifdef CONFIG_TRACER_MAX_TRACE 397#ifdef CONFIG_TRACER_MAX_TRACE
@@ -438,6 +466,8 @@ extern int trace_selftest_startup_branch(struct tracer *trace,
438 struct trace_array *tr); 466 struct trace_array *tr);
439extern int trace_selftest_startup_hw_branches(struct tracer *trace, 467extern int trace_selftest_startup_hw_branches(struct tracer *trace,
440 struct trace_array *tr); 468 struct trace_array *tr);
469extern int trace_selftest_startup_ksym(struct tracer *trace,
470 struct trace_array *tr);
441#endif /* CONFIG_FTRACE_STARTUP_TEST */ 471#endif /* CONFIG_FTRACE_STARTUP_TEST */
442 472
443extern void *head_page(struct trace_array_cpu *data); 473extern void *head_page(struct trace_array_cpu *data);
@@ -683,7 +713,6 @@ struct event_filter {
683 int n_preds; 713 int n_preds;
684 struct filter_pred **preds; 714 struct filter_pred **preds;
685 char *filter_string; 715 char *filter_string;
686 bool no_reset;
687}; 716};
688 717
689struct event_subsystem { 718struct event_subsystem {
@@ -703,7 +732,7 @@ typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
703typedef int (*regex_match_func)(char *str, struct regex *r, int len); 732typedef int (*regex_match_func)(char *str, struct regex *r, int len);
704 733
705enum regex_type { 734enum regex_type {
706 MATCH_FULL, 735 MATCH_FULL = 0,
707 MATCH_FRONT_ONLY, 736 MATCH_FRONT_ONLY,
708 MATCH_MIDDLE_ONLY, 737 MATCH_MIDDLE_ONLY,
709 MATCH_END_ONLY, 738 MATCH_END_ONLY,
@@ -744,7 +773,8 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
744 struct ring_buffer *buffer, 773 struct ring_buffer *buffer,
745 struct ring_buffer_event *event) 774 struct ring_buffer_event *event)
746{ 775{
747 if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) { 776 if (unlikely(call->filter_active) &&
777 !filter_match_preds(call->filter, rec)) {
748 ring_buffer_discard_commit(buffer, event); 778 ring_buffer_discard_commit(buffer, event);
749 return 1; 779 return 1;
750 } 780 }
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index ead3d724599d..c16a08f399df 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -364,3 +364,19 @@ FTRACE_ENTRY(kmem_free, kmemtrace_free_entry,
364 F_printk("type:%u call_site:%lx ptr:%p", 364 F_printk("type:%u call_site:%lx ptr:%p",
365 __entry->type_id, __entry->call_site, __entry->ptr) 365 __entry->type_id, __entry->call_site, __entry->ptr)
366); 366);
367
368FTRACE_ENTRY(ksym_trace, ksym_trace_entry,
369
370 TRACE_KSYM,
371
372 F_STRUCT(
373 __field( unsigned long, ip )
374 __field( unsigned char, type )
375 __array( char , cmd, TASK_COMM_LEN )
376 __field( unsigned long, addr )
377 ),
378
379 F_printk("ip: %pF type: %d ksym_name: %pS cmd: %s",
380 (void *)__entry->ip, (unsigned int)__entry->type,
381 (void *)__entry->addr, __entry->cmd)
382);
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index 8d5c171cc998..d9c60f80aa0d 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -8,17 +8,14 @@
8#include <linux/module.h> 8#include <linux/module.h>
9#include "trace.h" 9#include "trace.h"
10 10
11/*
12 * We can't use a size but a type in alloc_percpu()
13 * So let's create a dummy type that matches the desired size
14 */
15typedef struct {char buf[FTRACE_MAX_PROFILE_SIZE];} profile_buf_t;
16 11
17char *trace_profile_buf; 12char *perf_trace_buf;
18EXPORT_SYMBOL_GPL(trace_profile_buf); 13EXPORT_SYMBOL_GPL(perf_trace_buf);
14
15char *perf_trace_buf_nmi;
16EXPORT_SYMBOL_GPL(perf_trace_buf_nmi);
19 17
20char *trace_profile_buf_nmi; 18typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ;
21EXPORT_SYMBOL_GPL(trace_profile_buf_nmi);
22 19
23/* Count the events in use (per event id, not per instance) */ 20/* Count the events in use (per event id, not per instance) */
24static int total_profile_count; 21static int total_profile_count;
@@ -32,20 +29,20 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event)
32 return 0; 29 return 0;
33 30
34 if (!total_profile_count) { 31 if (!total_profile_count) {
35 buf = (char *)alloc_percpu(profile_buf_t); 32 buf = (char *)alloc_percpu(perf_trace_t);
36 if (!buf) 33 if (!buf)
37 goto fail_buf; 34 goto fail_buf;
38 35
39 rcu_assign_pointer(trace_profile_buf, buf); 36 rcu_assign_pointer(perf_trace_buf, buf);
40 37
41 buf = (char *)alloc_percpu(profile_buf_t); 38 buf = (char *)alloc_percpu(perf_trace_t);
42 if (!buf) 39 if (!buf)
43 goto fail_buf_nmi; 40 goto fail_buf_nmi;
44 41
45 rcu_assign_pointer(trace_profile_buf_nmi, buf); 42 rcu_assign_pointer(perf_trace_buf_nmi, buf);
46 } 43 }
47 44
48 ret = event->profile_enable(); 45 ret = event->profile_enable(event);
49 if (!ret) { 46 if (!ret) {
50 total_profile_count++; 47 total_profile_count++;
51 return 0; 48 return 0;
@@ -53,10 +50,10 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event)
53 50
54fail_buf_nmi: 51fail_buf_nmi:
55 if (!total_profile_count) { 52 if (!total_profile_count) {
56 free_percpu(trace_profile_buf_nmi); 53 free_percpu(perf_trace_buf_nmi);
57 free_percpu(trace_profile_buf); 54 free_percpu(perf_trace_buf);
58 trace_profile_buf_nmi = NULL; 55 perf_trace_buf_nmi = NULL;
59 trace_profile_buf = NULL; 56 perf_trace_buf = NULL;
60 } 57 }
61fail_buf: 58fail_buf:
62 atomic_dec(&event->profile_count); 59 atomic_dec(&event->profile_count);
@@ -89,14 +86,14 @@ static void ftrace_profile_disable_event(struct ftrace_event_call *event)
89 if (!atomic_add_negative(-1, &event->profile_count)) 86 if (!atomic_add_negative(-1, &event->profile_count))
90 return; 87 return;
91 88
92 event->profile_disable(); 89 event->profile_disable(event);
93 90
94 if (!--total_profile_count) { 91 if (!--total_profile_count) {
95 buf = trace_profile_buf; 92 buf = perf_trace_buf;
96 rcu_assign_pointer(trace_profile_buf, NULL); 93 rcu_assign_pointer(perf_trace_buf, NULL);
97 94
98 nmi_buf = trace_profile_buf_nmi; 95 nmi_buf = perf_trace_buf_nmi;
99 rcu_assign_pointer(trace_profile_buf_nmi, NULL); 96 rcu_assign_pointer(perf_trace_buf_nmi, NULL);
100 97
101 /* 98 /*
102 * Ensure every events in profiling have finished before 99 * Ensure every events in profiling have finished before
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 5e9ffc33f6db..1d18315dc836 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -93,9 +93,7 @@ int trace_define_common_fields(struct ftrace_event_call *call)
93} 93}
94EXPORT_SYMBOL_GPL(trace_define_common_fields); 94EXPORT_SYMBOL_GPL(trace_define_common_fields);
95 95
96#ifdef CONFIG_MODULES 96void trace_destroy_fields(struct ftrace_event_call *call)
97
98static void trace_destroy_fields(struct ftrace_event_call *call)
99{ 97{
100 struct ftrace_event_field *field, *next; 98 struct ftrace_event_field *field, *next;
101 99
@@ -107,8 +105,6 @@ static void trace_destroy_fields(struct ftrace_event_call *call)
107 } 105 }
108} 106}
109 107
110#endif /* CONFIG_MODULES */
111
112static void ftrace_event_enable_disable(struct ftrace_event_call *call, 108static void ftrace_event_enable_disable(struct ftrace_event_call *call,
113 int enable) 109 int enable)
114{ 110{
@@ -117,14 +113,14 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
117 if (call->enabled) { 113 if (call->enabled) {
118 call->enabled = 0; 114 call->enabled = 0;
119 tracing_stop_cmdline_record(); 115 tracing_stop_cmdline_record();
120 call->unregfunc(call->data); 116 call->unregfunc(call);
121 } 117 }
122 break; 118 break;
123 case 1: 119 case 1:
124 if (!call->enabled) { 120 if (!call->enabled) {
125 call->enabled = 1; 121 call->enabled = 1;
126 tracing_start_cmdline_record(); 122 tracing_start_cmdline_record();
127 call->regfunc(call->data); 123 call->regfunc(call);
128 } 124 }
129 break; 125 break;
130 } 126 }
@@ -507,7 +503,7 @@ extern char *__bad_type_size(void);
507#define FIELD(type, name) \ 503#define FIELD(type, name) \
508 sizeof(type) != sizeof(field.name) ? __bad_type_size() : \ 504 sizeof(type) != sizeof(field.name) ? __bad_type_size() : \
509 #type, "common_" #name, offsetof(typeof(field), name), \ 505 #type, "common_" #name, offsetof(typeof(field), name), \
510 sizeof(field.name) 506 sizeof(field.name), is_signed_type(type)
511 507
512static int trace_write_header(struct trace_seq *s) 508static int trace_write_header(struct trace_seq *s)
513{ 509{
@@ -515,17 +511,17 @@ static int trace_write_header(struct trace_seq *s)
515 511
516 /* struct trace_entry */ 512 /* struct trace_entry */
517 return trace_seq_printf(s, 513 return trace_seq_printf(s,
518 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 514 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
519 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 515 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
520 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 516 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
521 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 517 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
522 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 518 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
523 "\n", 519 "\n",
524 FIELD(unsigned short, type), 520 FIELD(unsigned short, type),
525 FIELD(unsigned char, flags), 521 FIELD(unsigned char, flags),
526 FIELD(unsigned char, preempt_count), 522 FIELD(unsigned char, preempt_count),
527 FIELD(int, pid), 523 FIELD(int, pid),
528 FIELD(int, lock_depth)); 524 FIELD(int, lock_depth));
529} 525}
530 526
531static ssize_t 527static ssize_t
@@ -937,27 +933,46 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
937 return 0; 933 return 0;
938} 934}
939 935
940#define for_each_event(event, start, end) \ 936static int __trace_add_event_call(struct ftrace_event_call *call)
941 for (event = start; \ 937{
942 (unsigned long)event < (unsigned long)end; \ 938 struct dentry *d_events;
943 event++) 939 int ret;
944 940
945#ifdef CONFIG_MODULES 941 if (!call->name)
942 return -EINVAL;
946 943
947static LIST_HEAD(ftrace_module_file_list); 944 if (call->raw_init) {
945 ret = call->raw_init(call);
946 if (ret < 0) {
947 if (ret != -ENOSYS)
948 pr_warning("Could not initialize trace "
949 "events/%s\n", call->name);
950 return ret;
951 }
952 }
948 953
949/* 954 d_events = event_trace_events_dir();
950 * Modules must own their file_operations to keep up with 955 if (!d_events)
951 * reference counting. 956 return -ENOENT;
952 */ 957
953struct ftrace_module_file_ops { 958 ret = event_create_dir(call, d_events, &ftrace_event_id_fops,
954 struct list_head list; 959 &ftrace_enable_fops, &ftrace_event_filter_fops,
955 struct module *mod; 960 &ftrace_event_format_fops);
956 struct file_operations id; 961 if (!ret)
957 struct file_operations enable; 962 list_add(&call->list, &ftrace_events);
958 struct file_operations format; 963
959 struct file_operations filter; 964 return ret;
960}; 965}
966
967/* Add an additional event_call dynamically */
968int trace_add_event_call(struct ftrace_event_call *call)
969{
970 int ret;
971 mutex_lock(&event_mutex);
972 ret = __trace_add_event_call(call);
973 mutex_unlock(&event_mutex);
974 return ret;
975}
961 976
962static void remove_subsystem_dir(const char *name) 977static void remove_subsystem_dir(const char *name)
963{ 978{
@@ -985,6 +1000,53 @@ static void remove_subsystem_dir(const char *name)
985 } 1000 }
986} 1001}
987 1002
1003/*
1004 * Must be called under locking both of event_mutex and trace_event_mutex.
1005 */
1006static void __trace_remove_event_call(struct ftrace_event_call *call)
1007{
1008 ftrace_event_enable_disable(call, 0);
1009 if (call->event)
1010 __unregister_ftrace_event(call->event);
1011 debugfs_remove_recursive(call->dir);
1012 list_del(&call->list);
1013 trace_destroy_fields(call);
1014 destroy_preds(call);
1015 remove_subsystem_dir(call->system);
1016}
1017
1018/* Remove an event_call */
1019void trace_remove_event_call(struct ftrace_event_call *call)
1020{
1021 mutex_lock(&event_mutex);
1022 down_write(&trace_event_mutex);
1023 __trace_remove_event_call(call);
1024 up_write(&trace_event_mutex);
1025 mutex_unlock(&event_mutex);
1026}
1027
1028#define for_each_event(event, start, end) \
1029 for (event = start; \
1030 (unsigned long)event < (unsigned long)end; \
1031 event++)
1032
1033#ifdef CONFIG_MODULES
1034
1035static LIST_HEAD(ftrace_module_file_list);
1036
1037/*
1038 * Modules must own their file_operations to keep up with
1039 * reference counting.
1040 */
1041struct ftrace_module_file_ops {
1042 struct list_head list;
1043 struct module *mod;
1044 struct file_operations id;
1045 struct file_operations enable;
1046 struct file_operations format;
1047 struct file_operations filter;
1048};
1049
988static struct ftrace_module_file_ops * 1050static struct ftrace_module_file_ops *
989trace_create_file_ops(struct module *mod) 1051trace_create_file_ops(struct module *mod)
990{ 1052{
@@ -1042,7 +1104,7 @@ static void trace_module_add_events(struct module *mod)
1042 if (!call->name) 1104 if (!call->name)
1043 continue; 1105 continue;
1044 if (call->raw_init) { 1106 if (call->raw_init) {
1045 ret = call->raw_init(); 1107 ret = call->raw_init(call);
1046 if (ret < 0) { 1108 if (ret < 0) {
1047 if (ret != -ENOSYS) 1109 if (ret != -ENOSYS)
1048 pr_warning("Could not initialize trace " 1110 pr_warning("Could not initialize trace "
@@ -1060,10 +1122,11 @@ static void trace_module_add_events(struct module *mod)
1060 return; 1122 return;
1061 } 1123 }
1062 call->mod = mod; 1124 call->mod = mod;
1063 list_add(&call->list, &ftrace_events); 1125 ret = event_create_dir(call, d_events,
1064 event_create_dir(call, d_events, 1126 &file_ops->id, &file_ops->enable,
1065 &file_ops->id, &file_ops->enable, 1127 &file_ops->filter, &file_ops->format);
1066 &file_ops->filter, &file_ops->format); 1128 if (!ret)
1129 list_add(&call->list, &ftrace_events);
1067 } 1130 }
1068} 1131}
1069 1132
@@ -1077,14 +1140,7 @@ static void trace_module_remove_events(struct module *mod)
1077 list_for_each_entry_safe(call, p, &ftrace_events, list) { 1140 list_for_each_entry_safe(call, p, &ftrace_events, list) {
1078 if (call->mod == mod) { 1141 if (call->mod == mod) {
1079 found = true; 1142 found = true;
1080 ftrace_event_enable_disable(call, 0); 1143 __trace_remove_event_call(call);
1081 if (call->event)
1082 __unregister_ftrace_event(call->event);
1083 debugfs_remove_recursive(call->dir);
1084 list_del(&call->list);
1085 trace_destroy_fields(call);
1086 destroy_preds(call);
1087 remove_subsystem_dir(call->system);
1088 } 1144 }
1089 } 1145 }
1090 1146
@@ -1202,7 +1258,7 @@ static __init int event_trace_init(void)
1202 if (!call->name) 1258 if (!call->name)
1203 continue; 1259 continue;
1204 if (call->raw_init) { 1260 if (call->raw_init) {
1205 ret = call->raw_init(); 1261 ret = call->raw_init(call);
1206 if (ret < 0) { 1262 if (ret < 0) {
1207 if (ret != -ENOSYS) 1263 if (ret != -ENOSYS)
1208 pr_warning("Could not initialize trace " 1264 pr_warning("Could not initialize trace "
@@ -1210,10 +1266,12 @@ static __init int event_trace_init(void)
1210 continue; 1266 continue;
1211 } 1267 }
1212 } 1268 }
1213 list_add(&call->list, &ftrace_events); 1269 ret = event_create_dir(call, d_events, &ftrace_event_id_fops,
1214 event_create_dir(call, d_events, &ftrace_event_id_fops, 1270 &ftrace_enable_fops,
1215 &ftrace_enable_fops, &ftrace_event_filter_fops, 1271 &ftrace_event_filter_fops,
1216 &ftrace_event_format_fops); 1272 &ftrace_event_format_fops);
1273 if (!ret)
1274 list_add(&call->list, &ftrace_events);
1217 } 1275 }
1218 1276
1219 while (true) { 1277 while (true) {
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 92672016da28..50504cb228de 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -21,6 +21,7 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/ctype.h> 22#include <linux/ctype.h>
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/perf_event.h>
24 25
25#include "trace.h" 26#include "trace.h"
26#include "trace_output.h" 27#include "trace_output.h"
@@ -29,6 +30,7 @@ enum filter_op_ids
29{ 30{
30 OP_OR, 31 OP_OR,
31 OP_AND, 32 OP_AND,
33 OP_GLOB,
32 OP_NE, 34 OP_NE,
33 OP_EQ, 35 OP_EQ,
34 OP_LT, 36 OP_LT,
@@ -46,16 +48,17 @@ struct filter_op {
46}; 48};
47 49
48static struct filter_op filter_ops[] = { 50static struct filter_op filter_ops[] = {
49 { OP_OR, "||", 1 }, 51 { OP_OR, "||", 1 },
50 { OP_AND, "&&", 2 }, 52 { OP_AND, "&&", 2 },
51 { OP_NE, "!=", 4 }, 53 { OP_GLOB, "~", 4 },
52 { OP_EQ, "==", 4 }, 54 { OP_NE, "!=", 4 },
53 { OP_LT, "<", 5 }, 55 { OP_EQ, "==", 4 },
54 { OP_LE, "<=", 5 }, 56 { OP_LT, "<", 5 },
55 { OP_GT, ">", 5 }, 57 { OP_LE, "<=", 5 },
56 { OP_GE, ">=", 5 }, 58 { OP_GT, ">", 5 },
57 { OP_NONE, "OP_NONE", 0 }, 59 { OP_GE, ">=", 5 },
58 { OP_OPEN_PAREN, "(", 0 }, 60 { OP_NONE, "OP_NONE", 0 },
61 { OP_OPEN_PAREN, "(", 0 },
59}; 62};
60 63
61enum { 64enum {
@@ -329,22 +332,18 @@ enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
329 return type; 332 return type;
330} 333}
331 334
332static int filter_build_regex(struct filter_pred *pred) 335static void filter_build_regex(struct filter_pred *pred)
333{ 336{
334 struct regex *r = &pred->regex; 337 struct regex *r = &pred->regex;
335 char *search, *dup; 338 char *search;
336 enum regex_type type; 339 enum regex_type type = MATCH_FULL;
337 int not; 340 int not = 0;
338 341
339 type = filter_parse_regex(r->pattern, r->len, &search, &not); 342 if (pred->op == OP_GLOB) {
340 dup = kstrdup(search, GFP_KERNEL); 343 type = filter_parse_regex(r->pattern, r->len, &search, &not);
341 if (!dup) 344 r->len = strlen(search);
342 return -ENOMEM; 345 memmove(r->pattern, search, r->len+1);
343 346 }
344 strcpy(r->pattern, dup);
345 kfree(dup);
346
347 r->len = strlen(r->pattern);
348 347
349 switch (type) { 348 switch (type) {
350 case MATCH_FULL: 349 case MATCH_FULL:
@@ -362,14 +361,11 @@ static int filter_build_regex(struct filter_pred *pred)
362 } 361 }
363 362
364 pred->not ^= not; 363 pred->not ^= not;
365
366 return 0;
367} 364}
368 365
369/* return 1 if event matches, 0 otherwise (discard) */ 366/* return 1 if event matches, 0 otherwise (discard) */
370int filter_match_preds(struct ftrace_event_call *call, void *rec) 367int filter_match_preds(struct event_filter *filter, void *rec)
371{ 368{
372 struct event_filter *filter = call->filter;
373 int match, top = 0, val1 = 0, val2 = 0; 369 int match, top = 0, val1 = 0, val2 = 0;
374 int stack[MAX_FILTER_PRED]; 370 int stack[MAX_FILTER_PRED];
375 struct filter_pred *pred; 371 struct filter_pred *pred;
@@ -542,9 +538,8 @@ static void filter_disable_preds(struct ftrace_event_call *call)
542 filter->preds[i]->fn = filter_pred_none; 538 filter->preds[i]->fn = filter_pred_none;
543} 539}
544 540
545void destroy_preds(struct ftrace_event_call *call) 541static void __free_preds(struct event_filter *filter)
546{ 542{
547 struct event_filter *filter = call->filter;
548 int i; 543 int i;
549 544
550 if (!filter) 545 if (!filter)
@@ -557,21 +552,24 @@ void destroy_preds(struct ftrace_event_call *call)
557 kfree(filter->preds); 552 kfree(filter->preds);
558 kfree(filter->filter_string); 553 kfree(filter->filter_string);
559 kfree(filter); 554 kfree(filter);
555}
556
557void destroy_preds(struct ftrace_event_call *call)
558{
559 __free_preds(call->filter);
560 call->filter = NULL; 560 call->filter = NULL;
561 call->filter_active = 0;
561} 562}
562 563
563static int init_preds(struct ftrace_event_call *call) 564static struct event_filter *__alloc_preds(void)
564{ 565{
565 struct event_filter *filter; 566 struct event_filter *filter;
566 struct filter_pred *pred; 567 struct filter_pred *pred;
567 int i; 568 int i;
568 569
569 if (call->filter) 570 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
570 return 0; 571 if (!filter)
571 572 return ERR_PTR(-ENOMEM);
572 filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
573 if (!call->filter)
574 return -ENOMEM;
575 573
576 filter->n_preds = 0; 574 filter->n_preds = 0;
577 575
@@ -587,12 +585,24 @@ static int init_preds(struct ftrace_event_call *call)
587 filter->preds[i] = pred; 585 filter->preds[i] = pred;
588 } 586 }
589 587
590 return 0; 588 return filter;
591 589
592oom: 590oom:
593 destroy_preds(call); 591 __free_preds(filter);
592 return ERR_PTR(-ENOMEM);
593}
594
595static int init_preds(struct ftrace_event_call *call)
596{
597 if (call->filter)
598 return 0;
594 599
595 return -ENOMEM; 600 call->filter_active = 0;
601 call->filter = __alloc_preds();
602 if (IS_ERR(call->filter))
603 return PTR_ERR(call->filter);
604
605 return 0;
596} 606}
597 607
598static int init_subsystem_preds(struct event_subsystem *system) 608static int init_subsystem_preds(struct event_subsystem *system)
@@ -615,14 +625,7 @@ static int init_subsystem_preds(struct event_subsystem *system)
615 return 0; 625 return 0;
616} 626}
617 627
618enum { 628static void filter_free_subsystem_preds(struct event_subsystem *system)
619 FILTER_DISABLE_ALL,
620 FILTER_INIT_NO_RESET,
621 FILTER_SKIP_NO_RESET,
622};
623
624static void filter_free_subsystem_preds(struct event_subsystem *system,
625 int flag)
626{ 629{
627 struct ftrace_event_call *call; 630 struct ftrace_event_call *call;
628 631
@@ -633,14 +636,6 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
633 if (strcmp(call->system, system->name) != 0) 636 if (strcmp(call->system, system->name) != 0)
634 continue; 637 continue;
635 638
636 if (flag == FILTER_INIT_NO_RESET) {
637 call->filter->no_reset = false;
638 continue;
639 }
640
641 if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset)
642 continue;
643
644 filter_disable_preds(call); 639 filter_disable_preds(call);
645 remove_filter_string(call->filter); 640 remove_filter_string(call->filter);
646 } 641 }
@@ -648,10 +643,10 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
648 643
649static int filter_add_pred_fn(struct filter_parse_state *ps, 644static int filter_add_pred_fn(struct filter_parse_state *ps,
650 struct ftrace_event_call *call, 645 struct ftrace_event_call *call,
646 struct event_filter *filter,
651 struct filter_pred *pred, 647 struct filter_pred *pred,
652 filter_pred_fn_t fn) 648 filter_pred_fn_t fn)
653{ 649{
654 struct event_filter *filter = call->filter;
655 int idx, err; 650 int idx, err;
656 651
657 if (filter->n_preds == MAX_FILTER_PRED) { 652 if (filter->n_preds == MAX_FILTER_PRED) {
@@ -666,7 +661,6 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
666 return err; 661 return err;
667 662
668 filter->n_preds++; 663 filter->n_preds++;
669 call->filter_active = 1;
670 664
671 return 0; 665 return 0;
672} 666}
@@ -691,7 +685,10 @@ static bool is_string_field(struct ftrace_event_field *field)
691 685
692static int is_legal_op(struct ftrace_event_field *field, int op) 686static int is_legal_op(struct ftrace_event_field *field, int op)
693{ 687{
694 if (is_string_field(field) && (op != OP_EQ && op != OP_NE)) 688 if (is_string_field(field) &&
689 (op != OP_EQ && op != OP_NE && op != OP_GLOB))
690 return 0;
691 if (!is_string_field(field) && op == OP_GLOB)
695 return 0; 692 return 0;
696 693
697 return 1; 694 return 1;
@@ -742,6 +739,7 @@ static filter_pred_fn_t select_comparison_fn(int op, int field_size,
742 739
743static int filter_add_pred(struct filter_parse_state *ps, 740static int filter_add_pred(struct filter_parse_state *ps,
744 struct ftrace_event_call *call, 741 struct ftrace_event_call *call,
742 struct event_filter *filter,
745 struct filter_pred *pred, 743 struct filter_pred *pred,
746 bool dry_run) 744 bool dry_run)
747{ 745{
@@ -776,15 +774,13 @@ static int filter_add_pred(struct filter_parse_state *ps,
776 } 774 }
777 775
778 if (is_string_field(field)) { 776 if (is_string_field(field)) {
779 ret = filter_build_regex(pred); 777 filter_build_regex(pred);
780 if (ret)
781 return ret;
782 778
783 if (field->filter_type == FILTER_STATIC_STRING) { 779 if (field->filter_type == FILTER_STATIC_STRING) {
784 fn = filter_pred_string; 780 fn = filter_pred_string;
785 pred->regex.field_len = field->size; 781 pred->regex.field_len = field->size;
786 } else if (field->filter_type == FILTER_DYN_STRING) 782 } else if (field->filter_type == FILTER_DYN_STRING)
787 fn = filter_pred_strloc; 783 fn = filter_pred_strloc;
788 else { 784 else {
789 fn = filter_pred_pchar; 785 fn = filter_pred_pchar;
790 pred->regex.field_len = strlen(pred->regex.pattern); 786 pred->regex.field_len = strlen(pred->regex.pattern);
@@ -813,45 +809,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
813 809
814add_pred_fn: 810add_pred_fn:
815 if (!dry_run) 811 if (!dry_run)
816 return filter_add_pred_fn(ps, call, pred, fn); 812 return filter_add_pred_fn(ps, call, filter, pred, fn);
817 return 0;
818}
819
820static int filter_add_subsystem_pred(struct filter_parse_state *ps,
821 struct event_subsystem *system,
822 struct filter_pred *pred,
823 char *filter_string,
824 bool dry_run)
825{
826 struct ftrace_event_call *call;
827 int err = 0;
828 bool fail = true;
829
830 list_for_each_entry(call, &ftrace_events, list) {
831
832 if (!call->define_fields)
833 continue;
834
835 if (strcmp(call->system, system->name))
836 continue;
837
838 if (call->filter->no_reset)
839 continue;
840
841 err = filter_add_pred(ps, call, pred, dry_run);
842 if (err)
843 call->filter->no_reset = true;
844 else
845 fail = false;
846
847 if (!dry_run)
848 replace_filter_string(call->filter, filter_string);
849 }
850
851 if (fail) {
852 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
853 return err;
854 }
855 return 0; 813 return 0;
856} 814}
857 815
@@ -1209,8 +1167,8 @@ static int check_preds(struct filter_parse_state *ps)
1209 return 0; 1167 return 0;
1210} 1168}
1211 1169
1212static int replace_preds(struct event_subsystem *system, 1170static int replace_preds(struct ftrace_event_call *call,
1213 struct ftrace_event_call *call, 1171 struct event_filter *filter,
1214 struct filter_parse_state *ps, 1172 struct filter_parse_state *ps,
1215 char *filter_string, 1173 char *filter_string,
1216 bool dry_run) 1174 bool dry_run)
@@ -1257,11 +1215,7 @@ static int replace_preds(struct event_subsystem *system,
1257add_pred: 1215add_pred:
1258 if (!pred) 1216 if (!pred)
1259 return -ENOMEM; 1217 return -ENOMEM;
1260 if (call) 1218 err = filter_add_pred(ps, call, filter, pred, dry_run);
1261 err = filter_add_pred(ps, call, pred, false);
1262 else
1263 err = filter_add_subsystem_pred(ps, system, pred,
1264 filter_string, dry_run);
1265 filter_free_pred(pred); 1219 filter_free_pred(pred);
1266 if (err) 1220 if (err)
1267 return err; 1221 return err;
@@ -1272,10 +1226,50 @@ add_pred:
1272 return 0; 1226 return 0;
1273} 1227}
1274 1228
1275int apply_event_filter(struct ftrace_event_call *call, char *filter_string) 1229static int replace_system_preds(struct event_subsystem *system,
1230 struct filter_parse_state *ps,
1231 char *filter_string)
1276{ 1232{
1233 struct ftrace_event_call *call;
1234 bool fail = true;
1277 int err; 1235 int err;
1278 1236
1237 list_for_each_entry(call, &ftrace_events, list) {
1238 struct event_filter *filter = call->filter;
1239
1240 if (!call->define_fields)
1241 continue;
1242
1243 if (strcmp(call->system, system->name) != 0)
1244 continue;
1245
1246 /* try to see if the filter can be applied */
1247 err = replace_preds(call, filter, ps, filter_string, true);
1248 if (err)
1249 continue;
1250
1251 /* really apply the filter */
1252 filter_disable_preds(call);
1253 err = replace_preds(call, filter, ps, filter_string, false);
1254 if (err)
1255 filter_disable_preds(call);
1256 else {
1257 call->filter_active = 1;
1258 replace_filter_string(filter, filter_string);
1259 }
1260 fail = false;
1261 }
1262
1263 if (fail) {
1264 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
1265 return -EINVAL;
1266 }
1267 return 0;
1268}
1269
1270int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1271{
1272 int err;
1279 struct filter_parse_state *ps; 1273 struct filter_parse_state *ps;
1280 1274
1281 mutex_lock(&event_mutex); 1275 mutex_lock(&event_mutex);
@@ -1287,8 +1281,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1287 if (!strcmp(strstrip(filter_string), "0")) { 1281 if (!strcmp(strstrip(filter_string), "0")) {
1288 filter_disable_preds(call); 1282 filter_disable_preds(call);
1289 remove_filter_string(call->filter); 1283 remove_filter_string(call->filter);
1290 mutex_unlock(&event_mutex); 1284 goto out_unlock;
1291 return 0;
1292 } 1285 }
1293 1286
1294 err = -ENOMEM; 1287 err = -ENOMEM;
@@ -1306,10 +1299,11 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1306 goto out; 1299 goto out;
1307 } 1300 }
1308 1301
1309 err = replace_preds(NULL, call, ps, filter_string, false); 1302 err = replace_preds(call, call->filter, ps, filter_string, false);
1310 if (err) 1303 if (err)
1311 append_filter_err(ps, call->filter); 1304 append_filter_err(ps, call->filter);
1312 1305 else
1306 call->filter_active = 1;
1313out: 1307out:
1314 filter_opstack_clear(ps); 1308 filter_opstack_clear(ps);
1315 postfix_clear(ps); 1309 postfix_clear(ps);
@@ -1324,7 +1318,6 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1324 char *filter_string) 1318 char *filter_string)
1325{ 1319{
1326 int err; 1320 int err;
1327
1328 struct filter_parse_state *ps; 1321 struct filter_parse_state *ps;
1329 1322
1330 mutex_lock(&event_mutex); 1323 mutex_lock(&event_mutex);
@@ -1334,10 +1327,9 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1334 goto out_unlock; 1327 goto out_unlock;
1335 1328
1336 if (!strcmp(strstrip(filter_string), "0")) { 1329 if (!strcmp(strstrip(filter_string), "0")) {
1337 filter_free_subsystem_preds(system, FILTER_DISABLE_ALL); 1330 filter_free_subsystem_preds(system);
1338 remove_filter_string(system->filter); 1331 remove_filter_string(system->filter);
1339 mutex_unlock(&event_mutex); 1332 goto out_unlock;
1340 return 0;
1341 } 1333 }
1342 1334
1343 err = -ENOMEM; 1335 err = -ENOMEM;
@@ -1354,31 +1346,87 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1354 goto out; 1346 goto out;
1355 } 1347 }
1356 1348
1357 filter_free_subsystem_preds(system, FILTER_INIT_NO_RESET); 1349 err = replace_system_preds(system, ps, filter_string);
1358 1350 if (err)
1359 /* try to see the filter can be applied to which events */
1360 err = replace_preds(system, NULL, ps, filter_string, true);
1361 if (err) {
1362 append_filter_err(ps, system->filter); 1351 append_filter_err(ps, system->filter);
1363 goto out; 1352
1353out:
1354 filter_opstack_clear(ps);
1355 postfix_clear(ps);
1356 kfree(ps);
1357out_unlock:
1358 mutex_unlock(&event_mutex);
1359
1360 return err;
1361}
1362
1363#ifdef CONFIG_EVENT_PROFILE
1364
1365void ftrace_profile_free_filter(struct perf_event *event)
1366{
1367 struct event_filter *filter = event->filter;
1368
1369 event->filter = NULL;
1370 __free_preds(filter);
1371}
1372
1373int ftrace_profile_set_filter(struct perf_event *event, int event_id,
1374 char *filter_str)
1375{
1376 int err;
1377 struct event_filter *filter;
1378 struct filter_parse_state *ps;
1379 struct ftrace_event_call *call = NULL;
1380
1381 mutex_lock(&event_mutex);
1382
1383 list_for_each_entry(call, &ftrace_events, list) {
1384 if (call->id == event_id)
1385 break;
1364 } 1386 }
1365 1387
1366 filter_free_subsystem_preds(system, FILTER_SKIP_NO_RESET); 1388 err = -EINVAL;
1389 if (!call)
1390 goto out_unlock;
1367 1391
1368 /* really apply the filter to the events */ 1392 err = -EEXIST;
1369 err = replace_preds(system, NULL, ps, filter_string, false); 1393 if (event->filter)
1370 if (err) { 1394 goto out_unlock;
1371 append_filter_err(ps, system->filter); 1395
1372 filter_free_subsystem_preds(system, 2); 1396 filter = __alloc_preds();
1397 if (IS_ERR(filter)) {
1398 err = PTR_ERR(filter);
1399 goto out_unlock;
1373 } 1400 }
1374 1401
1375out: 1402 err = -ENOMEM;
1403 ps = kzalloc(sizeof(*ps), GFP_KERNEL);
1404 if (!ps)
1405 goto free_preds;
1406
1407 parse_init(ps, filter_ops, filter_str);
1408 err = filter_parse(ps);
1409 if (err)
1410 goto free_ps;
1411
1412 err = replace_preds(call, filter, ps, filter_str, false);
1413 if (!err)
1414 event->filter = filter;
1415
1416free_ps:
1376 filter_opstack_clear(ps); 1417 filter_opstack_clear(ps);
1377 postfix_clear(ps); 1418 postfix_clear(ps);
1378 kfree(ps); 1419 kfree(ps);
1420
1421free_preds:
1422 if (err)
1423 __free_preds(filter);
1424
1379out_unlock: 1425out_unlock:
1380 mutex_unlock(&event_mutex); 1426 mutex_unlock(&event_mutex);
1381 1427
1382 return err; 1428 return err;
1383} 1429}
1384 1430
1431#endif /* CONFIG_EVENT_PROFILE */
1432
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index c74848ddb85a..dff8c84ddf17 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -66,44 +66,47 @@ static void __always_unused ____ftrace_check_##name(void) \
66#undef __field 66#undef __field
67#define __field(type, item) \ 67#define __field(type, item) \
68 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 68 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
69 "offset:%zu;\tsize:%zu;\n", \ 69 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
70 offsetof(typeof(field), item), \ 70 offsetof(typeof(field), item), \
71 sizeof(field.item)); \ 71 sizeof(field.item), is_signed_type(type)); \
72 if (!ret) \ 72 if (!ret) \
73 return 0; 73 return 0;
74 74
75#undef __field_desc 75#undef __field_desc
76#define __field_desc(type, container, item) \ 76#define __field_desc(type, container, item) \
77 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 77 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
78 "offset:%zu;\tsize:%zu;\n", \ 78 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
79 offsetof(typeof(field), container.item), \ 79 offsetof(typeof(field), container.item), \
80 sizeof(field.container.item)); \ 80 sizeof(field.container.item), \
81 is_signed_type(type)); \
81 if (!ret) \ 82 if (!ret) \
82 return 0; 83 return 0;
83 84
84#undef __array 85#undef __array
85#define __array(type, item, len) \ 86#define __array(type, item, len) \
86 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 87 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
87 "offset:%zu;\tsize:%zu;\n", \ 88 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
88 offsetof(typeof(field), item), \ 89 offsetof(typeof(field), item), \
89 sizeof(field.item)); \ 90 sizeof(field.item), is_signed_type(type)); \
90 if (!ret) \ 91 if (!ret) \
91 return 0; 92 return 0;
92 93
93#undef __array_desc 94#undef __array_desc
94#define __array_desc(type, container, item, len) \ 95#define __array_desc(type, container, item, len) \
95 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 96 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
96 "offset:%zu;\tsize:%zu;\n", \ 97 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
97 offsetof(typeof(field), container.item), \ 98 offsetof(typeof(field), container.item), \
98 sizeof(field.container.item)); \ 99 sizeof(field.container.item), \
100 is_signed_type(type)); \
99 if (!ret) \ 101 if (!ret) \
100 return 0; 102 return 0;
101 103
102#undef __dynamic_array 104#undef __dynamic_array
103#define __dynamic_array(type, item) \ 105#define __dynamic_array(type, item) \
104 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 106 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
105 "offset:%zu;\tsize:0;\n", \ 107 "offset:%zu;\tsize:0;\tsigned:%u;\n", \
106 offsetof(typeof(field), item)); \ 108 offsetof(typeof(field), item), \
109 is_signed_type(type)); \
107 if (!ret) \ 110 if (!ret) \
108 return 0; 111 return 0;
109 112
@@ -131,7 +134,6 @@ ftrace_format_##name(struct ftrace_event_call *unused, \
131 134
132#include "trace_entries.h" 135#include "trace_entries.h"
133 136
134
135#undef __field 137#undef __field
136#define __field(type, item) \ 138#define __field(type, item) \
137 ret = trace_define_field(event_call, #type, #item, \ 139 ret = trace_define_field(event_call, #type, #item, \
@@ -193,6 +195,11 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call) \
193 195
194#include "trace_entries.h" 196#include "trace_entries.h"
195 197
198static int ftrace_raw_init_event(struct ftrace_event_call *call)
199{
200 INIT_LIST_HEAD(&call->fields);
201 return 0;
202}
196 203
197#undef __field 204#undef __field
198#define __field(type, item) 205#define __field(type, item)
@@ -211,7 +218,6 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call) \
211 218
212#undef FTRACE_ENTRY 219#undef FTRACE_ENTRY
213#define FTRACE_ENTRY(call, struct_name, type, tstruct, print) \ 220#define FTRACE_ENTRY(call, struct_name, type, tstruct, print) \
214static int ftrace_raw_init_event_##call(void); \
215 \ 221 \
216struct ftrace_event_call __used \ 222struct ftrace_event_call __used \
217__attribute__((__aligned__(4))) \ 223__attribute__((__aligned__(4))) \
@@ -219,14 +225,9 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
219 .name = #call, \ 225 .name = #call, \
220 .id = type, \ 226 .id = type, \
221 .system = __stringify(TRACE_SYSTEM), \ 227 .system = __stringify(TRACE_SYSTEM), \
222 .raw_init = ftrace_raw_init_event_##call, \ 228 .raw_init = ftrace_raw_init_event, \
223 .show_format = ftrace_format_##call, \ 229 .show_format = ftrace_format_##call, \
224 .define_fields = ftrace_define_fields_##call, \ 230 .define_fields = ftrace_define_fields_##call, \
225}; \ 231}; \
226static int ftrace_raw_init_event_##call(void) \
227{ \
228 INIT_LIST_HEAD(&event_##call.fields); \
229 return 0; \
230} \
231 232
232#include "trace_entries.h" 233#include "trace_entries.h"
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
new file mode 100644
index 000000000000..aff5f80b59b8
--- /dev/null
+++ b/kernel/trace/trace_kprobe.c
@@ -0,0 +1,1523 @@
1/*
2 * Kprobes-based tracing events
3 *
4 * Created by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/uaccess.h>
22#include <linux/kprobes.h>
23#include <linux/seq_file.h>
24#include <linux/slab.h>
25#include <linux/smp.h>
26#include <linux/debugfs.h>
27#include <linux/types.h>
28#include <linux/string.h>
29#include <linux/ctype.h>
30#include <linux/ptrace.h>
31#include <linux/perf_event.h>
32
33#include "trace.h"
34#include "trace_output.h"
35
36#define MAX_TRACE_ARGS 128
37#define MAX_ARGSTR_LEN 63
38#define MAX_EVENT_NAME_LEN 64
39#define KPROBE_EVENT_SYSTEM "kprobes"
40
41/* Reserved field names */
42#define FIELD_STRING_IP "__probe_ip"
43#define FIELD_STRING_NARGS "__probe_nargs"
44#define FIELD_STRING_RETIP "__probe_ret_ip"
45#define FIELD_STRING_FUNC "__probe_func"
46
47const char *reserved_field_names[] = {
48 "common_type",
49 "common_flags",
50 "common_preempt_count",
51 "common_pid",
52 "common_tgid",
53 "common_lock_depth",
54 FIELD_STRING_IP,
55 FIELD_STRING_NARGS,
56 FIELD_STRING_RETIP,
57 FIELD_STRING_FUNC,
58};
59
60struct fetch_func {
61 unsigned long (*func)(struct pt_regs *, void *);
62 void *data;
63};
64
65static __kprobes unsigned long call_fetch(struct fetch_func *f,
66 struct pt_regs *regs)
67{
68 return f->func(regs, f->data);
69}
70
71/* fetch handlers */
72static __kprobes unsigned long fetch_register(struct pt_regs *regs,
73 void *offset)
74{
75 return regs_get_register(regs, (unsigned int)((unsigned long)offset));
76}
77
78static __kprobes unsigned long fetch_stack(struct pt_regs *regs,
79 void *num)
80{
81 return regs_get_kernel_stack_nth(regs,
82 (unsigned int)((unsigned long)num));
83}
84
85static __kprobes unsigned long fetch_memory(struct pt_regs *regs, void *addr)
86{
87 unsigned long retval;
88
89 if (probe_kernel_address(addr, retval))
90 return 0;
91 return retval;
92}
93
94static __kprobes unsigned long fetch_argument(struct pt_regs *regs, void *num)
95{
96 return regs_get_argument_nth(regs, (unsigned int)((unsigned long)num));
97}
98
99static __kprobes unsigned long fetch_retvalue(struct pt_regs *regs,
100 void *dummy)
101{
102 return regs_return_value(regs);
103}
104
105static __kprobes unsigned long fetch_stack_address(struct pt_regs *regs,
106 void *dummy)
107{
108 return kernel_stack_pointer(regs);
109}
110
111/* Memory fetching by symbol */
112struct symbol_cache {
113 char *symbol;
114 long offset;
115 unsigned long addr;
116};
117
118static unsigned long update_symbol_cache(struct symbol_cache *sc)
119{
120 sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol);
121 if (sc->addr)
122 sc->addr += sc->offset;
123 return sc->addr;
124}
125
126static void free_symbol_cache(struct symbol_cache *sc)
127{
128 kfree(sc->symbol);
129 kfree(sc);
130}
131
132static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset)
133{
134 struct symbol_cache *sc;
135
136 if (!sym || strlen(sym) == 0)
137 return NULL;
138 sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL);
139 if (!sc)
140 return NULL;
141
142 sc->symbol = kstrdup(sym, GFP_KERNEL);
143 if (!sc->symbol) {
144 kfree(sc);
145 return NULL;
146 }
147 sc->offset = offset;
148
149 update_symbol_cache(sc);
150 return sc;
151}
152
153static __kprobes unsigned long fetch_symbol(struct pt_regs *regs, void *data)
154{
155 struct symbol_cache *sc = data;
156
157 if (sc->addr)
158 return fetch_memory(regs, (void *)sc->addr);
159 else
160 return 0;
161}
162
163/* Special indirect memory access interface */
164struct indirect_fetch_data {
165 struct fetch_func orig;
166 long offset;
167};
168
169static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data)
170{
171 struct indirect_fetch_data *ind = data;
172 unsigned long addr;
173
174 addr = call_fetch(&ind->orig, regs);
175 if (addr) {
176 addr += ind->offset;
177 return fetch_memory(regs, (void *)addr);
178 } else
179 return 0;
180}
181
182static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data)
183{
184 if (data->orig.func == fetch_indirect)
185 free_indirect_fetch_data(data->orig.data);
186 else if (data->orig.func == fetch_symbol)
187 free_symbol_cache(data->orig.data);
188 kfree(data);
189}
190
191/**
192 * Kprobe event core functions
193 */
194
195struct probe_arg {
196 struct fetch_func fetch;
197 const char *name;
198};
199
200/* Flags for trace_probe */
201#define TP_FLAG_TRACE 1
202#define TP_FLAG_PROFILE 2
203
204struct trace_probe {
205 struct list_head list;
206 struct kretprobe rp; /* Use rp.kp for kprobe use */
207 unsigned long nhit;
208 unsigned int flags; /* For TP_FLAG_* */
209 const char *symbol; /* symbol name */
210 struct ftrace_event_call call;
211 struct trace_event event;
212 unsigned int nr_args;
213 struct probe_arg args[];
214};
215
216#define SIZEOF_TRACE_PROBE(n) \
217 (offsetof(struct trace_probe, args) + \
218 (sizeof(struct probe_arg) * (n)))
219
220static __kprobes int probe_is_return(struct trace_probe *tp)
221{
222 return tp->rp.handler != NULL;
223}
224
225static __kprobes const char *probe_symbol(struct trace_probe *tp)
226{
227 return tp->symbol ? tp->symbol : "unknown";
228}
229
230static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff)
231{
232 int ret = -EINVAL;
233
234 if (ff->func == fetch_argument)
235 ret = snprintf(buf, n, "$arg%lu", (unsigned long)ff->data);
236 else if (ff->func == fetch_register) {
237 const char *name;
238 name = regs_query_register_name((unsigned int)((long)ff->data));
239 ret = snprintf(buf, n, "%%%s", name);
240 } else if (ff->func == fetch_stack)
241 ret = snprintf(buf, n, "$stack%lu", (unsigned long)ff->data);
242 else if (ff->func == fetch_memory)
243 ret = snprintf(buf, n, "@0x%p", ff->data);
244 else if (ff->func == fetch_symbol) {
245 struct symbol_cache *sc = ff->data;
246 if (sc->offset)
247 ret = snprintf(buf, n, "@%s%+ld", sc->symbol,
248 sc->offset);
249 else
250 ret = snprintf(buf, n, "@%s", sc->symbol);
251 } else if (ff->func == fetch_retvalue)
252 ret = snprintf(buf, n, "$retval");
253 else if (ff->func == fetch_stack_address)
254 ret = snprintf(buf, n, "$stack");
255 else if (ff->func == fetch_indirect) {
256 struct indirect_fetch_data *id = ff->data;
257 size_t l = 0;
258 ret = snprintf(buf, n, "%+ld(", id->offset);
259 if (ret >= n)
260 goto end;
261 l += ret;
262 ret = probe_arg_string(buf + l, n - l, &id->orig);
263 if (ret < 0)
264 goto end;
265 l += ret;
266 ret = snprintf(buf + l, n - l, ")");
267 ret += l;
268 }
269end:
270 if (ret >= n)
271 return -ENOSPC;
272 return ret;
273}
274
275static int register_probe_event(struct trace_probe *tp);
276static void unregister_probe_event(struct trace_probe *tp);
277
278static DEFINE_MUTEX(probe_lock);
279static LIST_HEAD(probe_list);
280
281static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
282static int kretprobe_dispatcher(struct kretprobe_instance *ri,
283 struct pt_regs *regs);
284
285/*
286 * Allocate new trace_probe and initialize it (including kprobes).
287 */
288static struct trace_probe *alloc_trace_probe(const char *group,
289 const char *event,
290 void *addr,
291 const char *symbol,
292 unsigned long offs,
293 int nargs, int is_return)
294{
295 struct trace_probe *tp;
296
297 tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL);
298 if (!tp)
299 return ERR_PTR(-ENOMEM);
300
301 if (symbol) {
302 tp->symbol = kstrdup(symbol, GFP_KERNEL);
303 if (!tp->symbol)
304 goto error;
305 tp->rp.kp.symbol_name = tp->symbol;
306 tp->rp.kp.offset = offs;
307 } else
308 tp->rp.kp.addr = addr;
309
310 if (is_return)
311 tp->rp.handler = kretprobe_dispatcher;
312 else
313 tp->rp.kp.pre_handler = kprobe_dispatcher;
314
315 if (!event)
316 goto error;
317 tp->call.name = kstrdup(event, GFP_KERNEL);
318 if (!tp->call.name)
319 goto error;
320
321 if (!group)
322 goto error;
323 tp->call.system = kstrdup(group, GFP_KERNEL);
324 if (!tp->call.system)
325 goto error;
326
327 INIT_LIST_HEAD(&tp->list);
328 return tp;
329error:
330 kfree(tp->call.name);
331 kfree(tp->symbol);
332 kfree(tp);
333 return ERR_PTR(-ENOMEM);
334}
335
336static void free_probe_arg(struct probe_arg *arg)
337{
338 if (arg->fetch.func == fetch_symbol)
339 free_symbol_cache(arg->fetch.data);
340 else if (arg->fetch.func == fetch_indirect)
341 free_indirect_fetch_data(arg->fetch.data);
342 kfree(arg->name);
343}
344
345static void free_trace_probe(struct trace_probe *tp)
346{
347 int i;
348
349 for (i = 0; i < tp->nr_args; i++)
350 free_probe_arg(&tp->args[i]);
351
352 kfree(tp->call.system);
353 kfree(tp->call.name);
354 kfree(tp->symbol);
355 kfree(tp);
356}
357
358static struct trace_probe *find_probe_event(const char *event,
359 const char *group)
360{
361 struct trace_probe *tp;
362
363 list_for_each_entry(tp, &probe_list, list)
364 if (strcmp(tp->call.name, event) == 0 &&
365 strcmp(tp->call.system, group) == 0)
366 return tp;
367 return NULL;
368}
369
370/* Unregister a trace_probe and probe_event: call with locking probe_lock */
371static void unregister_trace_probe(struct trace_probe *tp)
372{
373 if (probe_is_return(tp))
374 unregister_kretprobe(&tp->rp);
375 else
376 unregister_kprobe(&tp->rp.kp);
377 list_del(&tp->list);
378 unregister_probe_event(tp);
379}
380
381/* Register a trace_probe and probe_event */
382static int register_trace_probe(struct trace_probe *tp)
383{
384 struct trace_probe *old_tp;
385 int ret;
386
387 mutex_lock(&probe_lock);
388
389 /* register as an event */
390 old_tp = find_probe_event(tp->call.name, tp->call.system);
391 if (old_tp) {
392 /* delete old event */
393 unregister_trace_probe(old_tp);
394 free_trace_probe(old_tp);
395 }
396 ret = register_probe_event(tp);
397 if (ret) {
398 pr_warning("Faild to register probe event(%d)\n", ret);
399 goto end;
400 }
401
402 tp->rp.kp.flags |= KPROBE_FLAG_DISABLED;
403 if (probe_is_return(tp))
404 ret = register_kretprobe(&tp->rp);
405 else
406 ret = register_kprobe(&tp->rp.kp);
407
408 if (ret) {
409 pr_warning("Could not insert probe(%d)\n", ret);
410 if (ret == -EILSEQ) {
411 pr_warning("Probing address(0x%p) is not an "
412 "instruction boundary.\n",
413 tp->rp.kp.addr);
414 ret = -EINVAL;
415 }
416 unregister_probe_event(tp);
417 } else
418 list_add_tail(&tp->list, &probe_list);
419end:
420 mutex_unlock(&probe_lock);
421 return ret;
422}
423
424/* Split symbol and offset. */
425static int split_symbol_offset(char *symbol, unsigned long *offset)
426{
427 char *tmp;
428 int ret;
429
430 if (!offset)
431 return -EINVAL;
432
433 tmp = strchr(symbol, '+');
434 if (tmp) {
435 /* skip sign because strict_strtol doesn't accept '+' */
436 ret = strict_strtoul(tmp + 1, 0, offset);
437 if (ret)
438 return ret;
439 *tmp = '\0';
440 } else
441 *offset = 0;
442 return 0;
443}
444
445#define PARAM_MAX_ARGS 16
446#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
447
448static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
449{
450 int ret = 0;
451 unsigned long param;
452
453 if (strcmp(arg, "retval") == 0) {
454 if (is_return) {
455 ff->func = fetch_retvalue;
456 ff->data = NULL;
457 } else
458 ret = -EINVAL;
459 } else if (strncmp(arg, "stack", 5) == 0) {
460 if (arg[5] == '\0') {
461 ff->func = fetch_stack_address;
462 ff->data = NULL;
463 } else if (isdigit(arg[5])) {
464 ret = strict_strtoul(arg + 5, 10, &param);
465 if (ret || param > PARAM_MAX_STACK)
466 ret = -EINVAL;
467 else {
468 ff->func = fetch_stack;
469 ff->data = (void *)param;
470 }
471 } else
472 ret = -EINVAL;
473 } else if (strncmp(arg, "arg", 3) == 0 && isdigit(arg[3])) {
474 ret = strict_strtoul(arg + 3, 10, &param);
475 if (ret || param > PARAM_MAX_ARGS)
476 ret = -EINVAL;
477 else {
478 ff->func = fetch_argument;
479 ff->data = (void *)param;
480 }
481 } else
482 ret = -EINVAL;
483 return ret;
484}
485
486/* Recursive argument parser */
487static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
488{
489 int ret = 0;
490 unsigned long param;
491 long offset;
492 char *tmp;
493
494 switch (arg[0]) {
495 case '$':
496 ret = parse_probe_vars(arg + 1, ff, is_return);
497 break;
498 case '%': /* named register */
499 ret = regs_query_register_offset(arg + 1);
500 if (ret >= 0) {
501 ff->func = fetch_register;
502 ff->data = (void *)(unsigned long)ret;
503 ret = 0;
504 }
505 break;
506 case '@': /* memory or symbol */
507 if (isdigit(arg[1])) {
508 ret = strict_strtoul(arg + 1, 0, &param);
509 if (ret)
510 break;
511 ff->func = fetch_memory;
512 ff->data = (void *)param;
513 } else {
514 ret = split_symbol_offset(arg + 1, &offset);
515 if (ret)
516 break;
517 ff->data = alloc_symbol_cache(arg + 1, offset);
518 if (ff->data)
519 ff->func = fetch_symbol;
520 else
521 ret = -EINVAL;
522 }
523 break;
524 case '+': /* indirect memory */
525 case '-':
526 tmp = strchr(arg, '(');
527 if (!tmp) {
528 ret = -EINVAL;
529 break;
530 }
531 *tmp = '\0';
532 ret = strict_strtol(arg + 1, 0, &offset);
533 if (ret)
534 break;
535 if (arg[0] == '-')
536 offset = -offset;
537 arg = tmp + 1;
538 tmp = strrchr(arg, ')');
539 if (tmp) {
540 struct indirect_fetch_data *id;
541 *tmp = '\0';
542 id = kzalloc(sizeof(struct indirect_fetch_data),
543 GFP_KERNEL);
544 if (!id)
545 return -ENOMEM;
546 id->offset = offset;
547 ret = __parse_probe_arg(arg, &id->orig, is_return);
548 if (ret)
549 kfree(id);
550 else {
551 ff->func = fetch_indirect;
552 ff->data = (void *)id;
553 }
554 } else
555 ret = -EINVAL;
556 break;
557 default:
558 /* TODO: support custom handler */
559 ret = -EINVAL;
560 }
561 return ret;
562}
563
564/* String length checking wrapper */
565static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
566{
567 if (strlen(arg) > MAX_ARGSTR_LEN) {
568 pr_info("Argument is too long.: %s\n", arg);
569 return -ENOSPC;
570 }
571 return __parse_probe_arg(arg, ff, is_return);
572}
573
574/* Return 1 if name is reserved or already used by another argument */
575static int conflict_field_name(const char *name,
576 struct probe_arg *args, int narg)
577{
578 int i;
579 for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
580 if (strcmp(reserved_field_names[i], name) == 0)
581 return 1;
582 for (i = 0; i < narg; i++)
583 if (strcmp(args[i].name, name) == 0)
584 return 1;
585 return 0;
586}
587
588static int create_trace_probe(int argc, char **argv)
589{
590 /*
591 * Argument syntax:
592 * - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS]
593 * - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS]
594 * Fetch args:
595 * $argN : fetch Nth of function argument. (N:0-)
596 * $retval : fetch return value
597 * $stack : fetch stack address
598 * $stackN : fetch Nth of stack (N:0-)
599 * @ADDR : fetch memory at ADDR (ADDR should be in kernel)
600 * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol)
601 * %REG : fetch register REG
602 * Indirect memory fetch:
603 * +|-offs(ARG) : fetch memory at ARG +|- offs address.
604 * Alias name of args:
605 * NAME=FETCHARG : set NAME as alias of FETCHARG.
606 */
607 struct trace_probe *tp;
608 int i, ret = 0;
609 int is_return = 0;
610 char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL;
611 unsigned long offset = 0;
612 void *addr = NULL;
613 char buf[MAX_EVENT_NAME_LEN];
614
615 if (argc < 2) {
616 pr_info("Probe point is not specified.\n");
617 return -EINVAL;
618 }
619
620 if (argv[0][0] == 'p')
621 is_return = 0;
622 else if (argv[0][0] == 'r')
623 is_return = 1;
624 else {
625 pr_info("Probe definition must be started with 'p' or 'r'.\n");
626 return -EINVAL;
627 }
628
629 if (argv[0][1] == ':') {
630 event = &argv[0][2];
631 if (strchr(event, '/')) {
632 group = event;
633 event = strchr(group, '/') + 1;
634 event[-1] = '\0';
635 if (strlen(group) == 0) {
636 pr_info("Group name is not specifiled\n");
637 return -EINVAL;
638 }
639 }
640 if (strlen(event) == 0) {
641 pr_info("Event name is not specifiled\n");
642 return -EINVAL;
643 }
644 }
645
646 if (isdigit(argv[1][0])) {
647 if (is_return) {
648 pr_info("Return probe point must be a symbol.\n");
649 return -EINVAL;
650 }
651 /* an address specified */
652 ret = strict_strtoul(&argv[0][2], 0, (unsigned long *)&addr);
653 if (ret) {
654 pr_info("Failed to parse address.\n");
655 return ret;
656 }
657 } else {
658 /* a symbol specified */
659 symbol = argv[1];
660 /* TODO: support .init module functions */
661 ret = split_symbol_offset(symbol, &offset);
662 if (ret) {
663 pr_info("Failed to parse symbol.\n");
664 return ret;
665 }
666 if (offset && is_return) {
667 pr_info("Return probe must be used without offset.\n");
668 return -EINVAL;
669 }
670 }
671 argc -= 2; argv += 2;
672
673 /* setup a probe */
674 if (!group)
675 group = KPROBE_EVENT_SYSTEM;
676 if (!event) {
677 /* Make a new event name */
678 if (symbol)
679 snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld",
680 is_return ? 'r' : 'p', symbol, offset);
681 else
682 snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p",
683 is_return ? 'r' : 'p', addr);
684 event = buf;
685 }
686 tp = alloc_trace_probe(group, event, addr, symbol, offset, argc,
687 is_return);
688 if (IS_ERR(tp)) {
689 pr_info("Failed to allocate trace_probe.(%d)\n",
690 (int)PTR_ERR(tp));
691 return PTR_ERR(tp);
692 }
693
694 /* parse arguments */
695 ret = 0;
696 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
697 /* Parse argument name */
698 arg = strchr(argv[i], '=');
699 if (arg)
700 *arg++ = '\0';
701 else
702 arg = argv[i];
703
704 if (conflict_field_name(argv[i], tp->args, i)) {
705 pr_info("Argument%d name '%s' conflicts with "
706 "another field.\n", i, argv[i]);
707 ret = -EINVAL;
708 goto error;
709 }
710
711 tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
712 if (!tp->args[i].name) {
713 pr_info("Failed to allocate argument%d name '%s'.\n",
714 i, argv[i]);
715 ret = -ENOMEM;
716 goto error;
717 }
718
719 /* Parse fetch argument */
720 ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return);
721 if (ret) {
722 pr_info("Parse error at argument%d. (%d)\n", i, ret);
723 kfree(tp->args[i].name);
724 goto error;
725 }
726
727 tp->nr_args++;
728 }
729
730 ret = register_trace_probe(tp);
731 if (ret)
732 goto error;
733 return 0;
734
735error:
736 free_trace_probe(tp);
737 return ret;
738}
739
740static void cleanup_all_probes(void)
741{
742 struct trace_probe *tp;
743
744 mutex_lock(&probe_lock);
745 /* TODO: Use batch unregistration */
746 while (!list_empty(&probe_list)) {
747 tp = list_entry(probe_list.next, struct trace_probe, list);
748 unregister_trace_probe(tp);
749 free_trace_probe(tp);
750 }
751 mutex_unlock(&probe_lock);
752}
753
754
755/* Probes listing interfaces */
756static void *probes_seq_start(struct seq_file *m, loff_t *pos)
757{
758 mutex_lock(&probe_lock);
759 return seq_list_start(&probe_list, *pos);
760}
761
762static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos)
763{
764 return seq_list_next(v, &probe_list, pos);
765}
766
767static void probes_seq_stop(struct seq_file *m, void *v)
768{
769 mutex_unlock(&probe_lock);
770}
771
772static int probes_seq_show(struct seq_file *m, void *v)
773{
774 struct trace_probe *tp = v;
775 int i, ret;
776 char buf[MAX_ARGSTR_LEN + 1];
777
778 seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p');
779 seq_printf(m, ":%s/%s", tp->call.system, tp->call.name);
780
781 if (!tp->symbol)
782 seq_printf(m, " 0x%p", tp->rp.kp.addr);
783 else if (tp->rp.kp.offset)
784 seq_printf(m, " %s+%u", probe_symbol(tp), tp->rp.kp.offset);
785 else
786 seq_printf(m, " %s", probe_symbol(tp));
787
788 for (i = 0; i < tp->nr_args; i++) {
789 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch);
790 if (ret < 0) {
791 pr_warning("Argument%d decoding error(%d).\n", i, ret);
792 return ret;
793 }
794 seq_printf(m, " %s=%s", tp->args[i].name, buf);
795 }
796 seq_printf(m, "\n");
797 return 0;
798}
799
800static const struct seq_operations probes_seq_op = {
801 .start = probes_seq_start,
802 .next = probes_seq_next,
803 .stop = probes_seq_stop,
804 .show = probes_seq_show
805};
806
807static int probes_open(struct inode *inode, struct file *file)
808{
809 if ((file->f_mode & FMODE_WRITE) &&
810 (file->f_flags & O_TRUNC))
811 cleanup_all_probes();
812
813 return seq_open(file, &probes_seq_op);
814}
815
816static int command_trace_probe(const char *buf)
817{
818 char **argv;
819 int argc = 0, ret = 0;
820
821 argv = argv_split(GFP_KERNEL, buf, &argc);
822 if (!argv)
823 return -ENOMEM;
824
825 if (argc)
826 ret = create_trace_probe(argc, argv);
827
828 argv_free(argv);
829 return ret;
830}
831
832#define WRITE_BUFSIZE 128
833
834static ssize_t probes_write(struct file *file, const char __user *buffer,
835 size_t count, loff_t *ppos)
836{
837 char *kbuf, *tmp;
838 int ret;
839 size_t done;
840 size_t size;
841
842 kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
843 if (!kbuf)
844 return -ENOMEM;
845
846 ret = done = 0;
847 while (done < count) {
848 size = count - done;
849 if (size >= WRITE_BUFSIZE)
850 size = WRITE_BUFSIZE - 1;
851 if (copy_from_user(kbuf, buffer + done, size)) {
852 ret = -EFAULT;
853 goto out;
854 }
855 kbuf[size] = '\0';
856 tmp = strchr(kbuf, '\n');
857 if (tmp) {
858 *tmp = '\0';
859 size = tmp - kbuf + 1;
860 } else if (done + size < count) {
861 pr_warning("Line length is too long: "
862 "Should be less than %d.", WRITE_BUFSIZE);
863 ret = -EINVAL;
864 goto out;
865 }
866 done += size;
867 /* Remove comments */
868 tmp = strchr(kbuf, '#');
869 if (tmp)
870 *tmp = '\0';
871
872 ret = command_trace_probe(kbuf);
873 if (ret)
874 goto out;
875 }
876 ret = done;
877out:
878 kfree(kbuf);
879 return ret;
880}
881
882static const struct file_operations kprobe_events_ops = {
883 .owner = THIS_MODULE,
884 .open = probes_open,
885 .read = seq_read,
886 .llseek = seq_lseek,
887 .release = seq_release,
888 .write = probes_write,
889};
890
891/* Probes profiling interfaces */
892static int probes_profile_seq_show(struct seq_file *m, void *v)
893{
894 struct trace_probe *tp = v;
895
896 seq_printf(m, " %-44s %15lu %15lu\n", tp->call.name, tp->nhit,
897 tp->rp.kp.nmissed);
898
899 return 0;
900}
901
902static const struct seq_operations profile_seq_op = {
903 .start = probes_seq_start,
904 .next = probes_seq_next,
905 .stop = probes_seq_stop,
906 .show = probes_profile_seq_show
907};
908
909static int profile_open(struct inode *inode, struct file *file)
910{
911 return seq_open(file, &profile_seq_op);
912}
913
914static const struct file_operations kprobe_profile_ops = {
915 .owner = THIS_MODULE,
916 .open = profile_open,
917 .read = seq_read,
918 .llseek = seq_lseek,
919 .release = seq_release,
920};
921
922/* Kprobe handler */
923static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
924{
925 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
926 struct kprobe_trace_entry *entry;
927 struct ring_buffer_event *event;
928 struct ring_buffer *buffer;
929 int size, i, pc;
930 unsigned long irq_flags;
931 struct ftrace_event_call *call = &tp->call;
932
933 tp->nhit++;
934
935 local_save_flags(irq_flags);
936 pc = preempt_count();
937
938 size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
939
940 event = trace_current_buffer_lock_reserve(&buffer, call->id, size,
941 irq_flags, pc);
942 if (!event)
943 return 0;
944
945 entry = ring_buffer_event_data(event);
946 entry->nargs = tp->nr_args;
947 entry->ip = (unsigned long)kp->addr;
948 for (i = 0; i < tp->nr_args; i++)
949 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
950
951 if (!filter_current_check_discard(buffer, call, entry, event))
952 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
953 return 0;
954}
955
956/* Kretprobe handler */
957static __kprobes int kretprobe_trace_func(struct kretprobe_instance *ri,
958 struct pt_regs *regs)
959{
960 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
961 struct kretprobe_trace_entry *entry;
962 struct ring_buffer_event *event;
963 struct ring_buffer *buffer;
964 int size, i, pc;
965 unsigned long irq_flags;
966 struct ftrace_event_call *call = &tp->call;
967
968 local_save_flags(irq_flags);
969 pc = preempt_count();
970
971 size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
972
973 event = trace_current_buffer_lock_reserve(&buffer, call->id, size,
974 irq_flags, pc);
975 if (!event)
976 return 0;
977
978 entry = ring_buffer_event_data(event);
979 entry->nargs = tp->nr_args;
980 entry->func = (unsigned long)tp->rp.kp.addr;
981 entry->ret_ip = (unsigned long)ri->ret_addr;
982 for (i = 0; i < tp->nr_args; i++)
983 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
984
985 if (!filter_current_check_discard(buffer, call, entry, event))
986 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
987
988 return 0;
989}
990
991/* Event entry printers */
992enum print_line_t
993print_kprobe_event(struct trace_iterator *iter, int flags)
994{
995 struct kprobe_trace_entry *field;
996 struct trace_seq *s = &iter->seq;
997 struct trace_event *event;
998 struct trace_probe *tp;
999 int i;
1000
1001 field = (struct kprobe_trace_entry *)iter->ent;
1002 event = ftrace_find_event(field->ent.type);
1003 tp = container_of(event, struct trace_probe, event);
1004
1005 if (!trace_seq_printf(s, "%s: (", tp->call.name))
1006 goto partial;
1007
1008 if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
1009 goto partial;
1010
1011 if (!trace_seq_puts(s, ")"))
1012 goto partial;
1013
1014 for (i = 0; i < field->nargs; i++)
1015 if (!trace_seq_printf(s, " %s=%lx",
1016 tp->args[i].name, field->args[i]))
1017 goto partial;
1018
1019 if (!trace_seq_puts(s, "\n"))
1020 goto partial;
1021
1022 return TRACE_TYPE_HANDLED;
1023partial:
1024 return TRACE_TYPE_PARTIAL_LINE;
1025}
1026
1027enum print_line_t
1028print_kretprobe_event(struct trace_iterator *iter, int flags)
1029{
1030 struct kretprobe_trace_entry *field;
1031 struct trace_seq *s = &iter->seq;
1032 struct trace_event *event;
1033 struct trace_probe *tp;
1034 int i;
1035
1036 field = (struct kretprobe_trace_entry *)iter->ent;
1037 event = ftrace_find_event(field->ent.type);
1038 tp = container_of(event, struct trace_probe, event);
1039
1040 if (!trace_seq_printf(s, "%s: (", tp->call.name))
1041 goto partial;
1042
1043 if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
1044 goto partial;
1045
1046 if (!trace_seq_puts(s, " <- "))
1047 goto partial;
1048
1049 if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET))
1050 goto partial;
1051
1052 if (!trace_seq_puts(s, ")"))
1053 goto partial;
1054
1055 for (i = 0; i < field->nargs; i++)
1056 if (!trace_seq_printf(s, " %s=%lx",
1057 tp->args[i].name, field->args[i]))
1058 goto partial;
1059
1060 if (!trace_seq_puts(s, "\n"))
1061 goto partial;
1062
1063 return TRACE_TYPE_HANDLED;
1064partial:
1065 return TRACE_TYPE_PARTIAL_LINE;
1066}
1067
1068static int probe_event_enable(struct ftrace_event_call *call)
1069{
1070 struct trace_probe *tp = (struct trace_probe *)call->data;
1071
1072 tp->flags |= TP_FLAG_TRACE;
1073 if (probe_is_return(tp))
1074 return enable_kretprobe(&tp->rp);
1075 else
1076 return enable_kprobe(&tp->rp.kp);
1077}
1078
1079static void probe_event_disable(struct ftrace_event_call *call)
1080{
1081 struct trace_probe *tp = (struct trace_probe *)call->data;
1082
1083 tp->flags &= ~TP_FLAG_TRACE;
1084 if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
1085 if (probe_is_return(tp))
1086 disable_kretprobe(&tp->rp);
1087 else
1088 disable_kprobe(&tp->rp.kp);
1089 }
1090}
1091
1092static int probe_event_raw_init(struct ftrace_event_call *event_call)
1093{
1094 INIT_LIST_HEAD(&event_call->fields);
1095
1096 return 0;
1097}
1098
1099#undef DEFINE_FIELD
1100#define DEFINE_FIELD(type, item, name, is_signed) \
1101 do { \
1102 ret = trace_define_field(event_call, #type, name, \
1103 offsetof(typeof(field), item), \
1104 sizeof(field.item), is_signed, \
1105 FILTER_OTHER); \
1106 if (ret) \
1107 return ret; \
1108 } while (0)
1109
1110static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
1111{
1112 int ret, i;
1113 struct kprobe_trace_entry field;
1114 struct trace_probe *tp = (struct trace_probe *)event_call->data;
1115
1116 ret = trace_define_common_fields(event_call);
1117 if (!ret)
1118 return ret;
1119
1120 DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
1121 DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
1122 /* Set argument names as fields */
1123 for (i = 0; i < tp->nr_args; i++)
1124 DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
1125 return 0;
1126}
1127
1128static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
1129{
1130 int ret, i;
1131 struct kretprobe_trace_entry field;
1132 struct trace_probe *tp = (struct trace_probe *)event_call->data;
1133
1134 ret = trace_define_common_fields(event_call);
1135 if (!ret)
1136 return ret;
1137
1138 DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
1139 DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
1140 DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
1141 /* Set argument names as fields */
1142 for (i = 0; i < tp->nr_args; i++)
1143 DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
1144 return 0;
1145}
1146
1147static int __probe_event_show_format(struct trace_seq *s,
1148 struct trace_probe *tp, const char *fmt,
1149 const char *arg)
1150{
1151 int i;
1152
1153 /* Show format */
1154 if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt))
1155 return 0;
1156
1157 for (i = 0; i < tp->nr_args; i++)
1158 if (!trace_seq_printf(s, " %s=%%lx", tp->args[i].name))
1159 return 0;
1160
1161 if (!trace_seq_printf(s, "\", %s", arg))
1162 return 0;
1163
1164 for (i = 0; i < tp->nr_args; i++)
1165 if (!trace_seq_printf(s, ", REC->%s", tp->args[i].name))
1166 return 0;
1167
1168 return trace_seq_puts(s, "\n");
1169}
1170
1171#undef SHOW_FIELD
1172#define SHOW_FIELD(type, item, name) \
1173 do { \
1174 ret = trace_seq_printf(s, "\tfield: " #type " %s;\t" \
1175 "offset:%u;\tsize:%u;\n", name, \
1176 (unsigned int)offsetof(typeof(field), item),\
1177 (unsigned int)sizeof(type)); \
1178 if (!ret) \
1179 return 0; \
1180 } while (0)
1181
1182static int kprobe_event_show_format(struct ftrace_event_call *call,
1183 struct trace_seq *s)
1184{
1185 struct kprobe_trace_entry field __attribute__((unused));
1186 int ret, i;
1187 struct trace_probe *tp = (struct trace_probe *)call->data;
1188
1189 SHOW_FIELD(unsigned long, ip, FIELD_STRING_IP);
1190 SHOW_FIELD(int, nargs, FIELD_STRING_NARGS);
1191
1192 /* Show fields */
1193 for (i = 0; i < tp->nr_args; i++)
1194 SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
1195 trace_seq_puts(s, "\n");
1196
1197 return __probe_event_show_format(s, tp, "(%lx)",
1198 "REC->" FIELD_STRING_IP);
1199}
1200
1201static int kretprobe_event_show_format(struct ftrace_event_call *call,
1202 struct trace_seq *s)
1203{
1204 struct kretprobe_trace_entry field __attribute__((unused));
1205 int ret, i;
1206 struct trace_probe *tp = (struct trace_probe *)call->data;
1207
1208 SHOW_FIELD(unsigned long, func, FIELD_STRING_FUNC);
1209 SHOW_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP);
1210 SHOW_FIELD(int, nargs, FIELD_STRING_NARGS);
1211
1212 /* Show fields */
1213 for (i = 0; i < tp->nr_args; i++)
1214 SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
1215 trace_seq_puts(s, "\n");
1216
1217 return __probe_event_show_format(s, tp, "(%lx <- %lx)",
1218 "REC->" FIELD_STRING_FUNC
1219 ", REC->" FIELD_STRING_RETIP);
1220}
1221
1222#ifdef CONFIG_EVENT_PROFILE
1223
1224/* Kprobe profile handler */
1225static __kprobes int kprobe_profile_func(struct kprobe *kp,
1226 struct pt_regs *regs)
1227{
1228 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
1229 struct ftrace_event_call *call = &tp->call;
1230 struct kprobe_trace_entry *entry;
1231 struct trace_entry *ent;
1232 int size, __size, i, pc, __cpu;
1233 unsigned long irq_flags;
1234 char *trace_buf;
1235 char *raw_data;
1236 int rctx;
1237
1238 pc = preempt_count();
1239 __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
1240 size = ALIGN(__size + sizeof(u32), sizeof(u64));
1241 size -= sizeof(u32);
1242 if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE,
1243 "profile buffer not large enough"))
1244 return 0;
1245
1246 /*
1247 * Protect the non nmi buffer
1248 * This also protects the rcu read side
1249 */
1250 local_irq_save(irq_flags);
1251
1252 rctx = perf_swevent_get_recursion_context();
1253 if (rctx < 0)
1254 goto end_recursion;
1255
1256 __cpu = smp_processor_id();
1257
1258 if (in_nmi())
1259 trace_buf = rcu_dereference(perf_trace_buf_nmi);
1260 else
1261 trace_buf = rcu_dereference(perf_trace_buf);
1262
1263 if (!trace_buf)
1264 goto end;
1265
1266 raw_data = per_cpu_ptr(trace_buf, __cpu);
1267
1268 /* Zero dead bytes from alignment to avoid buffer leak to userspace */
1269 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
1270 entry = (struct kprobe_trace_entry *)raw_data;
1271 ent = &entry->ent;
1272
1273 tracing_generic_entry_update(ent, irq_flags, pc);
1274 ent->type = call->id;
1275 entry->nargs = tp->nr_args;
1276 entry->ip = (unsigned long)kp->addr;
1277 for (i = 0; i < tp->nr_args; i++)
1278 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
1279 perf_tp_event(call->id, entry->ip, 1, entry, size);
1280
1281end:
1282 perf_swevent_put_recursion_context(rctx);
1283end_recursion:
1284 local_irq_restore(irq_flags);
1285
1286 return 0;
1287}
1288
1289/* Kretprobe profile handler */
1290static __kprobes int kretprobe_profile_func(struct kretprobe_instance *ri,
1291 struct pt_regs *regs)
1292{
1293 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
1294 struct ftrace_event_call *call = &tp->call;
1295 struct kretprobe_trace_entry *entry;
1296 struct trace_entry *ent;
1297 int size, __size, i, pc, __cpu;
1298 unsigned long irq_flags;
1299 char *trace_buf;
1300 char *raw_data;
1301 int rctx;
1302
1303 pc = preempt_count();
1304 __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
1305 size = ALIGN(__size + sizeof(u32), sizeof(u64));
1306 size -= sizeof(u32);
1307 if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE,
1308 "profile buffer not large enough"))
1309 return 0;
1310
1311 /*
1312 * Protect the non nmi buffer
1313 * This also protects the rcu read side
1314 */
1315 local_irq_save(irq_flags);
1316
1317 rctx = perf_swevent_get_recursion_context();
1318 if (rctx < 0)
1319 goto end_recursion;
1320
1321 __cpu = smp_processor_id();
1322
1323 if (in_nmi())
1324 trace_buf = rcu_dereference(perf_trace_buf_nmi);
1325 else
1326 trace_buf = rcu_dereference(perf_trace_buf);
1327
1328 if (!trace_buf)
1329 goto end;
1330
1331 raw_data = per_cpu_ptr(trace_buf, __cpu);
1332
1333 /* Zero dead bytes from alignment to avoid buffer leak to userspace */
1334 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
1335 entry = (struct kretprobe_trace_entry *)raw_data;
1336 ent = &entry->ent;
1337
1338 tracing_generic_entry_update(ent, irq_flags, pc);
1339 ent->type = call->id;
1340 entry->nargs = tp->nr_args;
1341 entry->func = (unsigned long)tp->rp.kp.addr;
1342 entry->ret_ip = (unsigned long)ri->ret_addr;
1343 for (i = 0; i < tp->nr_args; i++)
1344 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
1345 perf_tp_event(call->id, entry->ret_ip, 1, entry, size);
1346
1347end:
1348 perf_swevent_put_recursion_context(rctx);
1349end_recursion:
1350 local_irq_restore(irq_flags);
1351
1352 return 0;
1353}
1354
1355static int probe_profile_enable(struct ftrace_event_call *call)
1356{
1357 struct trace_probe *tp = (struct trace_probe *)call->data;
1358
1359 tp->flags |= TP_FLAG_PROFILE;
1360
1361 if (probe_is_return(tp))
1362 return enable_kretprobe(&tp->rp);
1363 else
1364 return enable_kprobe(&tp->rp.kp);
1365}
1366
1367static void probe_profile_disable(struct ftrace_event_call *call)
1368{
1369 struct trace_probe *tp = (struct trace_probe *)call->data;
1370
1371 tp->flags &= ~TP_FLAG_PROFILE;
1372
1373 if (!(tp->flags & TP_FLAG_TRACE)) {
1374 if (probe_is_return(tp))
1375 disable_kretprobe(&tp->rp);
1376 else
1377 disable_kprobe(&tp->rp.kp);
1378 }
1379}
1380#endif /* CONFIG_EVENT_PROFILE */
1381
1382
1383static __kprobes
1384int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
1385{
1386 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
1387
1388 if (tp->flags & TP_FLAG_TRACE)
1389 kprobe_trace_func(kp, regs);
1390#ifdef CONFIG_EVENT_PROFILE
1391 if (tp->flags & TP_FLAG_PROFILE)
1392 kprobe_profile_func(kp, regs);
1393#endif /* CONFIG_EVENT_PROFILE */
1394 return 0; /* We don't tweek kernel, so just return 0 */
1395}
1396
1397static __kprobes
1398int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
1399{
1400 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
1401
1402 if (tp->flags & TP_FLAG_TRACE)
1403 kretprobe_trace_func(ri, regs);
1404#ifdef CONFIG_EVENT_PROFILE
1405 if (tp->flags & TP_FLAG_PROFILE)
1406 kretprobe_profile_func(ri, regs);
1407#endif /* CONFIG_EVENT_PROFILE */
1408 return 0; /* We don't tweek kernel, so just return 0 */
1409}
1410
1411static int register_probe_event(struct trace_probe *tp)
1412{
1413 struct ftrace_event_call *call = &tp->call;
1414 int ret;
1415
1416 /* Initialize ftrace_event_call */
1417 if (probe_is_return(tp)) {
1418 tp->event.trace = print_kretprobe_event;
1419 call->raw_init = probe_event_raw_init;
1420 call->show_format = kretprobe_event_show_format;
1421 call->define_fields = kretprobe_event_define_fields;
1422 } else {
1423 tp->event.trace = print_kprobe_event;
1424 call->raw_init = probe_event_raw_init;
1425 call->show_format = kprobe_event_show_format;
1426 call->define_fields = kprobe_event_define_fields;
1427 }
1428 call->event = &tp->event;
1429 call->id = register_ftrace_event(&tp->event);
1430 if (!call->id)
1431 return -ENODEV;
1432 call->enabled = 0;
1433 call->regfunc = probe_event_enable;
1434 call->unregfunc = probe_event_disable;
1435
1436#ifdef CONFIG_EVENT_PROFILE
1437 atomic_set(&call->profile_count, -1);
1438 call->profile_enable = probe_profile_enable;
1439 call->profile_disable = probe_profile_disable;
1440#endif
1441 call->data = tp;
1442 ret = trace_add_event_call(call);
1443 if (ret) {
1444 pr_info("Failed to register kprobe event: %s\n", call->name);
1445 unregister_ftrace_event(&tp->event);
1446 }
1447 return ret;
1448}
1449
1450static void unregister_probe_event(struct trace_probe *tp)
1451{
1452 /* tp->event is unregistered in trace_remove_event_call() */
1453 trace_remove_event_call(&tp->call);
1454}
1455
1456/* Make a debugfs interface for controling probe points */
1457static __init int init_kprobe_trace(void)
1458{
1459 struct dentry *d_tracer;
1460 struct dentry *entry;
1461
1462 d_tracer = tracing_init_dentry();
1463 if (!d_tracer)
1464 return 0;
1465
1466 entry = debugfs_create_file("kprobe_events", 0644, d_tracer,
1467 NULL, &kprobe_events_ops);
1468
1469 /* Event list interface */
1470 if (!entry)
1471 pr_warning("Could not create debugfs "
1472 "'kprobe_events' entry\n");
1473
1474 /* Profile interface */
1475 entry = debugfs_create_file("kprobe_profile", 0444, d_tracer,
1476 NULL, &kprobe_profile_ops);
1477
1478 if (!entry)
1479 pr_warning("Could not create debugfs "
1480 "'kprobe_profile' entry\n");
1481 return 0;
1482}
1483fs_initcall(init_kprobe_trace);
1484
1485
1486#ifdef CONFIG_FTRACE_STARTUP_TEST
1487
1488static int kprobe_trace_selftest_target(int a1, int a2, int a3,
1489 int a4, int a5, int a6)
1490{
1491 return a1 + a2 + a3 + a4 + a5 + a6;
1492}
1493
1494static __init int kprobe_trace_self_tests_init(void)
1495{
1496 int ret;
1497 int (*target)(int, int, int, int, int, int);
1498
1499 target = kprobe_trace_selftest_target;
1500
1501 pr_info("Testing kprobe tracing: ");
1502
1503 ret = command_trace_probe("p:testprobe kprobe_trace_selftest_target "
1504 "$arg1 $arg2 $arg3 $arg4 $stack $stack0");
1505 if (WARN_ON_ONCE(ret))
1506 pr_warning("error enabling function entry\n");
1507
1508 ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
1509 "$retval");
1510 if (WARN_ON_ONCE(ret))
1511 pr_warning("error enabling function return\n");
1512
1513 ret = target(1, 2, 3, 4, 5, 6);
1514
1515 cleanup_all_probes();
1516
1517 pr_cont("OK\n");
1518 return 0;
1519}
1520
1521late_initcall(kprobe_trace_self_tests_init);
1522
1523#endif
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
new file mode 100644
index 000000000000..ddfa0fd43bc0
--- /dev/null
+++ b/kernel/trace/trace_ksym.c
@@ -0,0 +1,550 @@
1/*
2 * trace_ksym.c - Kernel Symbol Tracer
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright (C) IBM Corporation, 2009
19 */
20
21#include <linux/kallsyms.h>
22#include <linux/uaccess.h>
23#include <linux/debugfs.h>
24#include <linux/ftrace.h>
25#include <linux/module.h>
26#include <linux/fs.h>
27
28#include "trace_output.h"
29#include "trace_stat.h"
30#include "trace.h"
31
32#include <linux/hw_breakpoint.h>
33#include <asm/hw_breakpoint.h>
34
35/*
36 * For now, let us restrict the no. of symbols traced simultaneously to number
37 * of available hardware breakpoint registers.
38 */
39#define KSYM_TRACER_MAX HBP_NUM
40
41#define KSYM_TRACER_OP_LEN 3 /* rw- */
42
43struct trace_ksym {
44 struct perf_event **ksym_hbp;
45 struct perf_event_attr attr;
46#ifdef CONFIG_PROFILE_KSYM_TRACER
47 unsigned long counter;
48#endif
49 struct hlist_node ksym_hlist;
50};
51
52static struct trace_array *ksym_trace_array;
53
54static unsigned int ksym_filter_entry_count;
55static unsigned int ksym_tracing_enabled;
56
57static HLIST_HEAD(ksym_filter_head);
58
59static DEFINE_MUTEX(ksym_tracer_mutex);
60
61#ifdef CONFIG_PROFILE_KSYM_TRACER
62
63#define MAX_UL_INT 0xffffffff
64
65void ksym_collect_stats(unsigned long hbp_hit_addr)
66{
67 struct hlist_node *node;
68 struct trace_ksym *entry;
69
70 rcu_read_lock();
71 hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
72 if ((entry->attr.bp_addr == hbp_hit_addr) &&
73 (entry->counter <= MAX_UL_INT)) {
74 entry->counter++;
75 break;
76 }
77 }
78 rcu_read_unlock();
79}
80#endif /* CONFIG_PROFILE_KSYM_TRACER */
81
82void ksym_hbp_handler(struct perf_event *hbp, void *data)
83{
84 struct ring_buffer_event *event;
85 struct ksym_trace_entry *entry;
86 struct pt_regs *regs = data;
87 struct ring_buffer *buffer;
88 int pc;
89
90 if (!ksym_tracing_enabled)
91 return;
92
93 buffer = ksym_trace_array->buffer;
94
95 pc = preempt_count();
96
97 event = trace_buffer_lock_reserve(buffer, TRACE_KSYM,
98 sizeof(*entry), 0, pc);
99 if (!event)
100 return;
101
102 entry = ring_buffer_event_data(event);
103 entry->ip = instruction_pointer(regs);
104 entry->type = hw_breakpoint_type(hbp);
105 entry->addr = hw_breakpoint_addr(hbp);
106 strlcpy(entry->cmd, current->comm, TASK_COMM_LEN);
107
108#ifdef CONFIG_PROFILE_KSYM_TRACER
109 ksym_collect_stats(hw_breakpoint_addr(hbp));
110#endif /* CONFIG_PROFILE_KSYM_TRACER */
111
112 trace_buffer_unlock_commit(buffer, event, 0, pc);
113}
114
115/* Valid access types are represented as
116 *
117 * rw- : Set Read/Write Access Breakpoint
118 * -w- : Set Write Access Breakpoint
119 * --- : Clear Breakpoints
120 * --x : Set Execution Break points (Not available yet)
121 *
122 */
123static int ksym_trace_get_access_type(char *str)
124{
125 int access = 0;
126
127 if (str[0] == 'r')
128 access |= HW_BREAKPOINT_R;
129
130 if (str[1] == 'w')
131 access |= HW_BREAKPOINT_W;
132
133 if (str[2] == 'x')
134 access |= HW_BREAKPOINT_X;
135
136 switch (access) {
137 case HW_BREAKPOINT_R:
138 case HW_BREAKPOINT_W:
139 case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
140 return access;
141 default:
142 return -EINVAL;
143 }
144}
145
146/*
147 * There can be several possible malformed requests and we attempt to capture
148 * all of them. We enumerate some of the rules
149 * 1. We will not allow kernel symbols with ':' since it is used as a delimiter.
150 * i.e. multiple ':' symbols disallowed. Possible uses are of the form
151 * <module>:<ksym_name>:<op>.
152 * 2. No delimiter symbol ':' in the input string
153 * 3. Spurious operator symbols or symbols not in their respective positions
154 * 4. <ksym_name>:--- i.e. clear breakpoint request when ksym_name not in file
155 * 5. Kernel symbol not a part of /proc/kallsyms
156 * 6. Duplicate requests
157 */
158static int parse_ksym_trace_str(char *input_string, char **ksymname,
159 unsigned long *addr)
160{
161 int ret;
162
163 *ksymname = strsep(&input_string, ":");
164 *addr = kallsyms_lookup_name(*ksymname);
165
166 /* Check for malformed request: (2), (1) and (5) */
167 if ((!input_string) ||
168 (strlen(input_string) != KSYM_TRACER_OP_LEN) ||
169 (*addr == 0))
170 return -EINVAL;;
171
172 ret = ksym_trace_get_access_type(input_string);
173
174 return ret;
175}
176
177int process_new_ksym_entry(char *ksymname, int op, unsigned long addr)
178{
179 struct trace_ksym *entry;
180 int ret = -ENOMEM;
181
182 if (ksym_filter_entry_count >= KSYM_TRACER_MAX) {
183 printk(KERN_ERR "ksym_tracer: Maximum limit:(%d) reached. No"
184 " new requests for tracing can be accepted now.\n",
185 KSYM_TRACER_MAX);
186 return -ENOSPC;
187 }
188
189 entry = kzalloc(sizeof(struct trace_ksym), GFP_KERNEL);
190 if (!entry)
191 return -ENOMEM;
192
193 hw_breakpoint_init(&entry->attr);
194
195 entry->attr.bp_type = op;
196 entry->attr.bp_addr = addr;
197 entry->attr.bp_len = HW_BREAKPOINT_LEN_4;
198
199 ret = -EAGAIN;
200 entry->ksym_hbp = register_wide_hw_breakpoint(&entry->attr,
201 ksym_hbp_handler);
202
203 if (IS_ERR(entry->ksym_hbp)) {
204 ret = PTR_ERR(entry->ksym_hbp);
205 printk(KERN_INFO "ksym_tracer request failed. Try again"
206 " later!!\n");
207 goto err;
208 }
209
210 hlist_add_head_rcu(&(entry->ksym_hlist), &ksym_filter_head);
211 ksym_filter_entry_count++;
212
213 return 0;
214
215err:
216 kfree(entry);
217
218 return ret;
219}
220
221static ssize_t ksym_trace_filter_read(struct file *filp, char __user *ubuf,
222 size_t count, loff_t *ppos)
223{
224 struct trace_ksym *entry;
225 struct hlist_node *node;
226 struct trace_seq *s;
227 ssize_t cnt = 0;
228 int ret;
229
230 s = kmalloc(sizeof(*s), GFP_KERNEL);
231 if (!s)
232 return -ENOMEM;
233 trace_seq_init(s);
234
235 mutex_lock(&ksym_tracer_mutex);
236
237 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
238 ret = trace_seq_printf(s, "%pS:", (void *)entry->attr.bp_addr);
239 if (entry->attr.bp_type == HW_BREAKPOINT_R)
240 ret = trace_seq_puts(s, "r--\n");
241 else if (entry->attr.bp_type == HW_BREAKPOINT_W)
242 ret = trace_seq_puts(s, "-w-\n");
243 else if (entry->attr.bp_type == (HW_BREAKPOINT_W | HW_BREAKPOINT_R))
244 ret = trace_seq_puts(s, "rw-\n");
245 WARN_ON_ONCE(!ret);
246 }
247
248 cnt = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
249
250 mutex_unlock(&ksym_tracer_mutex);
251
252 kfree(s);
253
254 return cnt;
255}
256
257static void __ksym_trace_reset(void)
258{
259 struct trace_ksym *entry;
260 struct hlist_node *node, *node1;
261
262 mutex_lock(&ksym_tracer_mutex);
263 hlist_for_each_entry_safe(entry, node, node1, &ksym_filter_head,
264 ksym_hlist) {
265 unregister_wide_hw_breakpoint(entry->ksym_hbp);
266 ksym_filter_entry_count--;
267 hlist_del_rcu(&(entry->ksym_hlist));
268 synchronize_rcu();
269 kfree(entry);
270 }
271 mutex_unlock(&ksym_tracer_mutex);
272}
273
274static ssize_t ksym_trace_filter_write(struct file *file,
275 const char __user *buffer,
276 size_t count, loff_t *ppos)
277{
278 struct trace_ksym *entry;
279 struct hlist_node *node;
280 char *input_string, *ksymname = NULL;
281 unsigned long ksym_addr = 0;
282 int ret, op, changed = 0;
283
284 input_string = kzalloc(count + 1, GFP_KERNEL);
285 if (!input_string)
286 return -ENOMEM;
287
288 if (copy_from_user(input_string, buffer, count)) {
289 kfree(input_string);
290 return -EFAULT;
291 }
292 input_string[count] = '\0';
293
294 strstrip(input_string);
295
296 /*
297 * Clear all breakpoints if:
298 * 1: echo > ksym_trace_filter
299 * 2: echo 0 > ksym_trace_filter
300 * 3: echo "*:---" > ksym_trace_filter
301 */
302 if (!input_string[0] || !strcmp(input_string, "0") ||
303 !strcmp(input_string, "*:---")) {
304 __ksym_trace_reset();
305 kfree(input_string);
306 return count;
307 }
308
309 ret = op = parse_ksym_trace_str(input_string, &ksymname, &ksym_addr);
310 if (ret < 0) {
311 kfree(input_string);
312 return ret;
313 }
314
315 mutex_lock(&ksym_tracer_mutex);
316
317 ret = -EINVAL;
318 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
319 if (entry->attr.bp_addr == ksym_addr) {
320 /* Check for malformed request: (6) */
321 if (entry->attr.bp_type != op)
322 changed = 1;
323 else
324 goto out;
325 break;
326 }
327 }
328 if (changed) {
329 unregister_wide_hw_breakpoint(entry->ksym_hbp);
330 entry->attr.bp_type = op;
331 ret = 0;
332 if (op > 0) {
333 entry->ksym_hbp =
334 register_wide_hw_breakpoint(&entry->attr,
335 ksym_hbp_handler);
336 if (IS_ERR(entry->ksym_hbp))
337 ret = PTR_ERR(entry->ksym_hbp);
338 else
339 goto out;
340 }
341 /* Error or "symbol:---" case: drop it */
342 ksym_filter_entry_count--;
343 hlist_del_rcu(&(entry->ksym_hlist));
344 synchronize_rcu();
345 kfree(entry);
346 goto out;
347 } else {
348 /* Check for malformed request: (4) */
349 if (op == 0)
350 goto out;
351 ret = process_new_ksym_entry(ksymname, op, ksym_addr);
352 }
353out:
354 mutex_unlock(&ksym_tracer_mutex);
355
356 kfree(input_string);
357
358 if (!ret)
359 ret = count;
360 return ret;
361}
362
363static const struct file_operations ksym_tracing_fops = {
364 .open = tracing_open_generic,
365 .read = ksym_trace_filter_read,
366 .write = ksym_trace_filter_write,
367};
368
369static void ksym_trace_reset(struct trace_array *tr)
370{
371 ksym_tracing_enabled = 0;
372 __ksym_trace_reset();
373}
374
375static int ksym_trace_init(struct trace_array *tr)
376{
377 int cpu, ret = 0;
378
379 for_each_online_cpu(cpu)
380 tracing_reset(tr, cpu);
381 ksym_tracing_enabled = 1;
382 ksym_trace_array = tr;
383
384 return ret;
385}
386
387static void ksym_trace_print_header(struct seq_file *m)
388{
389 seq_puts(m,
390 "# TASK-PID CPU# Symbol "
391 "Type Function\n");
392 seq_puts(m,
393 "# | | | "
394 " | |\n");
395}
396
397static enum print_line_t ksym_trace_output(struct trace_iterator *iter)
398{
399 struct trace_entry *entry = iter->ent;
400 struct trace_seq *s = &iter->seq;
401 struct ksym_trace_entry *field;
402 char str[KSYM_SYMBOL_LEN];
403 int ret;
404
405 if (entry->type != TRACE_KSYM)
406 return TRACE_TYPE_UNHANDLED;
407
408 trace_assign_type(field, entry);
409
410 ret = trace_seq_printf(s, "%11s-%-5d [%03d] %pS", field->cmd,
411 entry->pid, iter->cpu, (char *)field->addr);
412 if (!ret)
413 return TRACE_TYPE_PARTIAL_LINE;
414
415 switch (field->type) {
416 case HW_BREAKPOINT_R:
417 ret = trace_seq_printf(s, " R ");
418 break;
419 case HW_BREAKPOINT_W:
420 ret = trace_seq_printf(s, " W ");
421 break;
422 case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
423 ret = trace_seq_printf(s, " RW ");
424 break;
425 default:
426 return TRACE_TYPE_PARTIAL_LINE;
427 }
428
429 if (!ret)
430 return TRACE_TYPE_PARTIAL_LINE;
431
432 sprint_symbol(str, field->ip);
433 ret = trace_seq_printf(s, "%s\n", str);
434 if (!ret)
435 return TRACE_TYPE_PARTIAL_LINE;
436
437 return TRACE_TYPE_HANDLED;
438}
439
440struct tracer ksym_tracer __read_mostly =
441{
442 .name = "ksym_tracer",
443 .init = ksym_trace_init,
444 .reset = ksym_trace_reset,
445#ifdef CONFIG_FTRACE_SELFTEST
446 .selftest = trace_selftest_startup_ksym,
447#endif
448 .print_header = ksym_trace_print_header,
449 .print_line = ksym_trace_output
450};
451
452__init static int init_ksym_trace(void)
453{
454 struct dentry *d_tracer;
455 struct dentry *entry;
456
457 d_tracer = tracing_init_dentry();
458 ksym_filter_entry_count = 0;
459
460 entry = debugfs_create_file("ksym_trace_filter", 0644, d_tracer,
461 NULL, &ksym_tracing_fops);
462 if (!entry)
463 pr_warning("Could not create debugfs "
464 "'ksym_trace_filter' file\n");
465
466 return register_tracer(&ksym_tracer);
467}
468device_initcall(init_ksym_trace);
469
470
471#ifdef CONFIG_PROFILE_KSYM_TRACER
472static int ksym_tracer_stat_headers(struct seq_file *m)
473{
474 seq_puts(m, " Access Type ");
475 seq_puts(m, " Symbol Counter\n");
476 seq_puts(m, " ----------- ");
477 seq_puts(m, " ------ -------\n");
478 return 0;
479}
480
481static int ksym_tracer_stat_show(struct seq_file *m, void *v)
482{
483 struct hlist_node *stat = v;
484 struct trace_ksym *entry;
485 int access_type = 0;
486 char fn_name[KSYM_NAME_LEN];
487
488 entry = hlist_entry(stat, struct trace_ksym, ksym_hlist);
489
490 access_type = entry->attr.bp_type;
491
492 switch (access_type) {
493 case HW_BREAKPOINT_R:
494 seq_puts(m, " R ");
495 break;
496 case HW_BREAKPOINT_W:
497 seq_puts(m, " W ");
498 break;
499 case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
500 seq_puts(m, " RW ");
501 break;
502 default:
503 seq_puts(m, " NA ");
504 }
505
506 if (lookup_symbol_name(entry->attr.bp_addr, fn_name) >= 0)
507 seq_printf(m, " %-36s", fn_name);
508 else
509 seq_printf(m, " %-36s", "<NA>");
510 seq_printf(m, " %15lu\n", entry->counter);
511
512 return 0;
513}
514
515static void *ksym_tracer_stat_start(struct tracer_stat *trace)
516{
517 return ksym_filter_head.first;
518}
519
520static void *
521ksym_tracer_stat_next(void *v, int idx)
522{
523 struct hlist_node *stat = v;
524
525 return stat->next;
526}
527
528static struct tracer_stat ksym_tracer_stats = {
529 .name = "ksym_tracer",
530 .stat_start = ksym_tracer_stat_start,
531 .stat_next = ksym_tracer_stat_next,
532 .stat_headers = ksym_tracer_stat_headers,
533 .stat_show = ksym_tracer_stat_show
534};
535
536__init static int ksym_tracer_stat_init(void)
537{
538 int ret;
539
540 ret = register_stat_tracer(&ksym_tracer_stats);
541 if (ret) {
542 printk(KERN_WARNING "Warning: could not register "
543 "ksym tracer stats\n");
544 return 1;
545 }
546
547 return 0;
548}
549fs_initcall(ksym_tracer_stat_init);
550#endif /* CONFIG_PROFILE_KSYM_TRACER */
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index d2cdbabb4ead..dc98309e839a 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -17,6 +17,7 @@ static inline int trace_valid_entry(struct trace_entry *entry)
17 case TRACE_GRAPH_ENT: 17 case TRACE_GRAPH_ENT:
18 case TRACE_GRAPH_RET: 18 case TRACE_GRAPH_RET:
19 case TRACE_HW_BRANCHES: 19 case TRACE_HW_BRANCHES:
20 case TRACE_KSYM:
20 return 1; 21 return 1;
21 } 22 }
22 return 0; 23 return 0;
@@ -808,3 +809,57 @@ trace_selftest_startup_hw_branches(struct tracer *trace,
808 return ret; 809 return ret;
809} 810}
810#endif /* CONFIG_HW_BRANCH_TRACER */ 811#endif /* CONFIG_HW_BRANCH_TRACER */
812
813#ifdef CONFIG_KSYM_TRACER
814static int ksym_selftest_dummy;
815
816int
817trace_selftest_startup_ksym(struct tracer *trace, struct trace_array *tr)
818{
819 unsigned long count;
820 int ret;
821
822 /* start the tracing */
823 ret = tracer_init(trace, tr);
824 if (ret) {
825 warn_failed_init_tracer(trace, ret);
826 return ret;
827 }
828
829 ksym_selftest_dummy = 0;
830 /* Register the read-write tracing request */
831
832 ret = process_new_ksym_entry("ksym_selftest_dummy",
833 HW_BREAKPOINT_R | HW_BREAKPOINT_W,
834 (unsigned long)(&ksym_selftest_dummy));
835
836 if (ret < 0) {
837 printk(KERN_CONT "ksym_trace read-write startup test failed\n");
838 goto ret_path;
839 }
840 /* Perform a read and a write operation over the dummy variable to
841 * trigger the tracer
842 */
843 if (ksym_selftest_dummy == 0)
844 ksym_selftest_dummy++;
845
846 /* stop the tracing. */
847 tracing_stop();
848 /* check the trace buffer */
849 ret = trace_test_buffer(tr, &count);
850 trace->reset(tr);
851 tracing_start();
852
853 /* read & write operations - one each is performed on the dummy variable
854 * triggering two entries in the trace buffer
855 */
856 if (!ret && count != 2) {
857 printk(KERN_CONT "Ksym tracer startup test failed");
858 ret = -1;
859 }
860
861ret_path:
862 return ret;
863}
864#endif /* CONFIG_KSYM_TRACER */
865
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index ddee9c593732..57501d90096a 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -51,32 +51,6 @@ static struct syscall_metadata *syscall_nr_to_meta(int nr)
51 return syscalls_metadata[nr]; 51 return syscalls_metadata[nr];
52} 52}
53 53
54int syscall_name_to_nr(char *name)
55{
56 int i;
57
58 if (!syscalls_metadata)
59 return -1;
60
61 for (i = 0; i < NR_syscalls; i++) {
62 if (syscalls_metadata[i]) {
63 if (!strcmp(syscalls_metadata[i]->name, name))
64 return i;
65 }
66 }
67 return -1;
68}
69
70void set_syscall_enter_id(int num, int id)
71{
72 syscalls_metadata[num]->enter_id = id;
73}
74
75void set_syscall_exit_id(int num, int id)
76{
77 syscalls_metadata[num]->exit_id = id;
78}
79
80enum print_line_t 54enum print_line_t
81print_syscall_enter(struct trace_iterator *iter, int flags) 55print_syscall_enter(struct trace_iterator *iter, int flags)
82{ 56{
@@ -93,7 +67,7 @@ print_syscall_enter(struct trace_iterator *iter, int flags)
93 if (!entry) 67 if (!entry)
94 goto end; 68 goto end;
95 69
96 if (entry->enter_id != ent->type) { 70 if (entry->enter_event->id != ent->type) {
97 WARN_ON_ONCE(1); 71 WARN_ON_ONCE(1);
98 goto end; 72 goto end;
99 } 73 }
@@ -148,7 +122,7 @@ print_syscall_exit(struct trace_iterator *iter, int flags)
148 return TRACE_TYPE_HANDLED; 122 return TRACE_TYPE_HANDLED;
149 } 123 }
150 124
151 if (entry->exit_id != ent->type) { 125 if (entry->exit_event->id != ent->type) {
152 WARN_ON_ONCE(1); 126 WARN_ON_ONCE(1);
153 return TRACE_TYPE_UNHANDLED; 127 return TRACE_TYPE_UNHANDLED;
154 } 128 }
@@ -166,24 +140,19 @@ extern char *__bad_type_size(void);
166#define SYSCALL_FIELD(type, name) \ 140#define SYSCALL_FIELD(type, name) \
167 sizeof(type) != sizeof(trace.name) ? \ 141 sizeof(type) != sizeof(trace.name) ? \
168 __bad_type_size() : \ 142 __bad_type_size() : \
169 #type, #name, offsetof(typeof(trace), name), sizeof(trace.name) 143 #type, #name, offsetof(typeof(trace), name), \
144 sizeof(trace.name), is_signed_type(type)
170 145
171int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) 146int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s)
172{ 147{
173 int i; 148 int i;
174 int nr;
175 int ret; 149 int ret;
176 struct syscall_metadata *entry; 150 struct syscall_metadata *entry = call->data;
177 struct syscall_trace_enter trace; 151 struct syscall_trace_enter trace;
178 int offset = offsetof(struct syscall_trace_enter, args); 152 int offset = offsetof(struct syscall_trace_enter, args);
179 153
180 nr = syscall_name_to_nr(call->data); 154 ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
181 entry = syscall_nr_to_meta(nr); 155 "\tsigned:%u;\n",
182
183 if (!entry)
184 return 0;
185
186 ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n",
187 SYSCALL_FIELD(int, nr)); 156 SYSCALL_FIELD(int, nr));
188 if (!ret) 157 if (!ret)
189 return 0; 158 return 0;
@@ -193,8 +162,10 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s)
193 entry->args[i]); 162 entry->args[i]);
194 if (!ret) 163 if (!ret)
195 return 0; 164 return 0;
196 ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;\n", offset, 165 ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;"
197 sizeof(unsigned long)); 166 "\tsigned:%u;\n", offset,
167 sizeof(unsigned long),
168 is_signed_type(unsigned long));
198 if (!ret) 169 if (!ret)
199 return 0; 170 return 0;
200 offset += sizeof(unsigned long); 171 offset += sizeof(unsigned long);
@@ -226,8 +197,10 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s)
226 struct syscall_trace_exit trace; 197 struct syscall_trace_exit trace;
227 198
228 ret = trace_seq_printf(s, 199 ret = trace_seq_printf(s,
229 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 200 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
230 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", 201 "\tsigned:%u;\n"
202 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
203 "\tsigned:%u;\n",
231 SYSCALL_FIELD(int, nr), 204 SYSCALL_FIELD(int, nr),
232 SYSCALL_FIELD(long, ret)); 205 SYSCALL_FIELD(long, ret));
233 if (!ret) 206 if (!ret)
@@ -239,22 +212,19 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s)
239int syscall_enter_define_fields(struct ftrace_event_call *call) 212int syscall_enter_define_fields(struct ftrace_event_call *call)
240{ 213{
241 struct syscall_trace_enter trace; 214 struct syscall_trace_enter trace;
242 struct syscall_metadata *meta; 215 struct syscall_metadata *meta = call->data;
243 int ret; 216 int ret;
244 int nr;
245 int i; 217 int i;
246 int offset = offsetof(typeof(trace), args); 218 int offset = offsetof(typeof(trace), args);
247 219
248 nr = syscall_name_to_nr(call->data);
249 meta = syscall_nr_to_meta(nr);
250
251 if (!meta)
252 return 0;
253
254 ret = trace_define_common_fields(call); 220 ret = trace_define_common_fields(call);
255 if (ret) 221 if (ret)
256 return ret; 222 return ret;
257 223
224 ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
225 if (ret)
226 return ret;
227
258 for (i = 0; i < meta->nb_args; i++) { 228 for (i = 0; i < meta->nb_args; i++) {
259 ret = trace_define_field(call, meta->types[i], 229 ret = trace_define_field(call, meta->types[i],
260 meta->args[i], offset, 230 meta->args[i], offset,
@@ -275,7 +245,11 @@ int syscall_exit_define_fields(struct ftrace_event_call *call)
275 if (ret) 245 if (ret)
276 return ret; 246 return ret;
277 247
278 ret = trace_define_field(call, SYSCALL_FIELD(long, ret), 0, 248 ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
249 if (ret)
250 return ret;
251
252 ret = trace_define_field(call, SYSCALL_FIELD(long, ret),
279 FILTER_OTHER); 253 FILTER_OTHER);
280 254
281 return ret; 255 return ret;
@@ -302,8 +276,8 @@ void ftrace_syscall_enter(struct pt_regs *regs, long id)
302 276
303 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; 277 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
304 278
305 event = trace_current_buffer_lock_reserve(&buffer, sys_data->enter_id, 279 event = trace_current_buffer_lock_reserve(&buffer,
306 size, 0, 0); 280 sys_data->enter_event->id, size, 0, 0);
307 if (!event) 281 if (!event)
308 return; 282 return;
309 283
@@ -334,8 +308,8 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret)
334 if (!sys_data) 308 if (!sys_data)
335 return; 309 return;
336 310
337 event = trace_current_buffer_lock_reserve(&buffer, sys_data->exit_id, 311 event = trace_current_buffer_lock_reserve(&buffer,
338 sizeof(*entry), 0, 0); 312 sys_data->exit_event->id, sizeof(*entry), 0, 0);
339 if (!event) 313 if (!event)
340 return; 314 return;
341 315
@@ -348,14 +322,12 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret)
348 trace_current_buffer_unlock_commit(buffer, event, 0, 0); 322 trace_current_buffer_unlock_commit(buffer, event, 0, 0);
349} 323}
350 324
351int reg_event_syscall_enter(void *ptr) 325int reg_event_syscall_enter(struct ftrace_event_call *call)
352{ 326{
353 int ret = 0; 327 int ret = 0;
354 int num; 328 int num;
355 char *name;
356 329
357 name = (char *)ptr; 330 num = ((struct syscall_metadata *)call->data)->syscall_nr;
358 num = syscall_name_to_nr(name);
359 if (num < 0 || num >= NR_syscalls) 331 if (num < 0 || num >= NR_syscalls)
360 return -ENOSYS; 332 return -ENOSYS;
361 mutex_lock(&syscall_trace_lock); 333 mutex_lock(&syscall_trace_lock);
@@ -372,13 +344,11 @@ int reg_event_syscall_enter(void *ptr)
372 return ret; 344 return ret;
373} 345}
374 346
375void unreg_event_syscall_enter(void *ptr) 347void unreg_event_syscall_enter(struct ftrace_event_call *call)
376{ 348{
377 int num; 349 int num;
378 char *name;
379 350
380 name = (char *)ptr; 351 num = ((struct syscall_metadata *)call->data)->syscall_nr;
381 num = syscall_name_to_nr(name);
382 if (num < 0 || num >= NR_syscalls) 352 if (num < 0 || num >= NR_syscalls)
383 return; 353 return;
384 mutex_lock(&syscall_trace_lock); 354 mutex_lock(&syscall_trace_lock);
@@ -389,14 +359,12 @@ void unreg_event_syscall_enter(void *ptr)
389 mutex_unlock(&syscall_trace_lock); 359 mutex_unlock(&syscall_trace_lock);
390} 360}
391 361
392int reg_event_syscall_exit(void *ptr) 362int reg_event_syscall_exit(struct ftrace_event_call *call)
393{ 363{
394 int ret = 0; 364 int ret = 0;
395 int num; 365 int num;
396 char *name;
397 366
398 name = (char *)ptr; 367 num = ((struct syscall_metadata *)call->data)->syscall_nr;
399 num = syscall_name_to_nr(name);
400 if (num < 0 || num >= NR_syscalls) 368 if (num < 0 || num >= NR_syscalls)
401 return -ENOSYS; 369 return -ENOSYS;
402 mutex_lock(&syscall_trace_lock); 370 mutex_lock(&syscall_trace_lock);
@@ -413,13 +381,11 @@ int reg_event_syscall_exit(void *ptr)
413 return ret; 381 return ret;
414} 382}
415 383
416void unreg_event_syscall_exit(void *ptr) 384void unreg_event_syscall_exit(struct ftrace_event_call *call)
417{ 385{
418 int num; 386 int num;
419 char *name;
420 387
421 name = (char *)ptr; 388 num = ((struct syscall_metadata *)call->data)->syscall_nr;
422 num = syscall_name_to_nr(name);
423 if (num < 0 || num >= NR_syscalls) 389 if (num < 0 || num >= NR_syscalls)
424 return; 390 return;
425 mutex_lock(&syscall_trace_lock); 391 mutex_lock(&syscall_trace_lock);
@@ -430,13 +396,17 @@ void unreg_event_syscall_exit(void *ptr)
430 mutex_unlock(&syscall_trace_lock); 396 mutex_unlock(&syscall_trace_lock);
431} 397}
432 398
433struct trace_event event_syscall_enter = { 399int init_syscall_trace(struct ftrace_event_call *call)
434 .trace = print_syscall_enter, 400{
435}; 401 int id;
436 402
437struct trace_event event_syscall_exit = { 403 id = register_ftrace_event(call->event);
438 .trace = print_syscall_exit, 404 if (!id)
439}; 405 return -ENODEV;
406 call->id = id;
407 INIT_LIST_HEAD(&call->fields);
408 return 0;
409}
440 410
441int __init init_ftrace_syscalls(void) 411int __init init_ftrace_syscalls(void)
442{ 412{
@@ -454,6 +424,10 @@ int __init init_ftrace_syscalls(void)
454 for (i = 0; i < NR_syscalls; i++) { 424 for (i = 0; i < NR_syscalls; i++) {
455 addr = arch_syscall_addr(i); 425 addr = arch_syscall_addr(i);
456 meta = find_syscall_meta(addr); 426 meta = find_syscall_meta(addr);
427 if (!meta)
428 continue;
429
430 meta->syscall_nr = i;
457 syscalls_metadata[i] = meta; 431 syscalls_metadata[i] = meta;
458 } 432 }
459 433
@@ -473,8 +447,10 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)
473 struct syscall_metadata *sys_data; 447 struct syscall_metadata *sys_data;
474 struct syscall_trace_enter *rec; 448 struct syscall_trace_enter *rec;
475 unsigned long flags; 449 unsigned long flags;
450 char *trace_buf;
476 char *raw_data; 451 char *raw_data;
477 int syscall_nr; 452 int syscall_nr;
453 int rctx;
478 int size; 454 int size;
479 int cpu; 455 int cpu;
480 456
@@ -498,41 +474,42 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)
498 /* Protect the per cpu buffer, begin the rcu read side */ 474 /* Protect the per cpu buffer, begin the rcu read side */
499 local_irq_save(flags); 475 local_irq_save(flags);
500 476
477 rctx = perf_swevent_get_recursion_context();
478 if (rctx < 0)
479 goto end_recursion;
480
501 cpu = smp_processor_id(); 481 cpu = smp_processor_id();
502 482
503 if (in_nmi()) 483 trace_buf = rcu_dereference(perf_trace_buf);
504 raw_data = rcu_dereference(trace_profile_buf_nmi);
505 else
506 raw_data = rcu_dereference(trace_profile_buf);
507 484
508 if (!raw_data) 485 if (!trace_buf)
509 goto end; 486 goto end;
510 487
511 raw_data = per_cpu_ptr(raw_data, cpu); 488 raw_data = per_cpu_ptr(trace_buf, cpu);
512 489
513 /* zero the dead bytes from align to not leak stack to user */ 490 /* zero the dead bytes from align to not leak stack to user */
514 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; 491 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
515 492
516 rec = (struct syscall_trace_enter *) raw_data; 493 rec = (struct syscall_trace_enter *) raw_data;
517 tracing_generic_entry_update(&rec->ent, 0, 0); 494 tracing_generic_entry_update(&rec->ent, 0, 0);
518 rec->ent.type = sys_data->enter_id; 495 rec->ent.type = sys_data->enter_event->id;
519 rec->nr = syscall_nr; 496 rec->nr = syscall_nr;
520 syscall_get_arguments(current, regs, 0, sys_data->nb_args, 497 syscall_get_arguments(current, regs, 0, sys_data->nb_args,
521 (unsigned long *)&rec->args); 498 (unsigned long *)&rec->args);
522 perf_tp_event(sys_data->enter_id, 0, 1, rec, size); 499 perf_tp_event(sys_data->enter_event->id, 0, 1, rec, size);
523 500
524end: 501end:
502 perf_swevent_put_recursion_context(rctx);
503end_recursion:
525 local_irq_restore(flags); 504 local_irq_restore(flags);
526} 505}
527 506
528int reg_prof_syscall_enter(char *name) 507int prof_sysenter_enable(struct ftrace_event_call *call)
529{ 508{
530 int ret = 0; 509 int ret = 0;
531 int num; 510 int num;
532 511
533 num = syscall_name_to_nr(name); 512 num = ((struct syscall_metadata *)call->data)->syscall_nr;
534 if (num < 0 || num >= NR_syscalls)
535 return -ENOSYS;
536 513
537 mutex_lock(&syscall_trace_lock); 514 mutex_lock(&syscall_trace_lock);
538 if (!sys_prof_refcount_enter) 515 if (!sys_prof_refcount_enter)
@@ -548,13 +525,11 @@ int reg_prof_syscall_enter(char *name)
548 return ret; 525 return ret;
549} 526}
550 527
551void unreg_prof_syscall_enter(char *name) 528void prof_sysenter_disable(struct ftrace_event_call *call)
552{ 529{
553 int num; 530 int num;
554 531
555 num = syscall_name_to_nr(name); 532 num = ((struct syscall_metadata *)call->data)->syscall_nr;
556 if (num < 0 || num >= NR_syscalls)
557 return;
558 533
559 mutex_lock(&syscall_trace_lock); 534 mutex_lock(&syscall_trace_lock);
560 sys_prof_refcount_enter--; 535 sys_prof_refcount_enter--;
@@ -570,7 +545,9 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)
570 struct syscall_trace_exit *rec; 545 struct syscall_trace_exit *rec;
571 unsigned long flags; 546 unsigned long flags;
572 int syscall_nr; 547 int syscall_nr;
548 char *trace_buf;
573 char *raw_data; 549 char *raw_data;
550 int rctx;
574 int size; 551 int size;
575 int cpu; 552 int cpu;
576 553
@@ -596,17 +573,19 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)
596 573
597 /* Protect the per cpu buffer, begin the rcu read side */ 574 /* Protect the per cpu buffer, begin the rcu read side */
598 local_irq_save(flags); 575 local_irq_save(flags);
576
577 rctx = perf_swevent_get_recursion_context();
578 if (rctx < 0)
579 goto end_recursion;
580
599 cpu = smp_processor_id(); 581 cpu = smp_processor_id();
600 582
601 if (in_nmi()) 583 trace_buf = rcu_dereference(perf_trace_buf);
602 raw_data = rcu_dereference(trace_profile_buf_nmi);
603 else
604 raw_data = rcu_dereference(trace_profile_buf);
605 584
606 if (!raw_data) 585 if (!trace_buf)
607 goto end; 586 goto end;
608 587
609 raw_data = per_cpu_ptr(raw_data, cpu); 588 raw_data = per_cpu_ptr(trace_buf, cpu);
610 589
611 /* zero the dead bytes from align to not leak stack to user */ 590 /* zero the dead bytes from align to not leak stack to user */
612 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; 591 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
@@ -614,24 +593,24 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)
614 rec = (struct syscall_trace_exit *)raw_data; 593 rec = (struct syscall_trace_exit *)raw_data;
615 594
616 tracing_generic_entry_update(&rec->ent, 0, 0); 595 tracing_generic_entry_update(&rec->ent, 0, 0);
617 rec->ent.type = sys_data->exit_id; 596 rec->ent.type = sys_data->exit_event->id;
618 rec->nr = syscall_nr; 597 rec->nr = syscall_nr;
619 rec->ret = syscall_get_return_value(current, regs); 598 rec->ret = syscall_get_return_value(current, regs);
620 599
621 perf_tp_event(sys_data->exit_id, 0, 1, rec, size); 600 perf_tp_event(sys_data->exit_event->id, 0, 1, rec, size);
622 601
623end: 602end:
603 perf_swevent_put_recursion_context(rctx);
604end_recursion:
624 local_irq_restore(flags); 605 local_irq_restore(flags);
625} 606}
626 607
627int reg_prof_syscall_exit(char *name) 608int prof_sysexit_enable(struct ftrace_event_call *call)
628{ 609{
629 int ret = 0; 610 int ret = 0;
630 int num; 611 int num;
631 612
632 num = syscall_name_to_nr(name); 613 num = ((struct syscall_metadata *)call->data)->syscall_nr;
633 if (num < 0 || num >= NR_syscalls)
634 return -ENOSYS;
635 614
636 mutex_lock(&syscall_trace_lock); 615 mutex_lock(&syscall_trace_lock);
637 if (!sys_prof_refcount_exit) 616 if (!sys_prof_refcount_exit)
@@ -647,13 +626,11 @@ int reg_prof_syscall_exit(char *name)
647 return ret; 626 return ret;
648} 627}
649 628
650void unreg_prof_syscall_exit(char *name) 629void prof_sysexit_disable(struct ftrace_event_call *call)
651{ 630{
652 int num; 631 int num;
653 632
654 num = syscall_name_to_nr(name); 633 num = ((struct syscall_metadata *)call->data)->syscall_nr;
655 if (num < 0 || num >= NR_syscalls)
656 return;
657 634
658 mutex_lock(&syscall_trace_lock); 635 mutex_lock(&syscall_trace_lock);
659 sys_prof_refcount_exit--; 636 sys_prof_refcount_exit--;
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index 69eae358a726..a2cd77e70d4d 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -57,78 +57,47 @@ static int proc_do_uts_string(ctl_table *table, int write,
57#define proc_do_uts_string NULL 57#define proc_do_uts_string NULL
58#endif 58#endif
59 59
60
61#ifdef CONFIG_SYSCTL_SYSCALL
62/* The generic string strategy routine: */
63static int sysctl_uts_string(ctl_table *table,
64 void __user *oldval, size_t __user *oldlenp,
65 void __user *newval, size_t newlen)
66{
67 struct ctl_table uts_table;
68 int r, write;
69 write = newval && newlen;
70 memcpy(&uts_table, table, sizeof(uts_table));
71 uts_table.data = get_uts(table, write);
72 r = sysctl_string(&uts_table, oldval, oldlenp, newval, newlen);
73 put_uts(table, write, uts_table.data);
74 return r;
75}
76#else
77#define sysctl_uts_string NULL
78#endif
79
80static struct ctl_table uts_kern_table[] = { 60static struct ctl_table uts_kern_table[] = {
81 { 61 {
82 .ctl_name = KERN_OSTYPE,
83 .procname = "ostype", 62 .procname = "ostype",
84 .data = init_uts_ns.name.sysname, 63 .data = init_uts_ns.name.sysname,
85 .maxlen = sizeof(init_uts_ns.name.sysname), 64 .maxlen = sizeof(init_uts_ns.name.sysname),
86 .mode = 0444, 65 .mode = 0444,
87 .proc_handler = proc_do_uts_string, 66 .proc_handler = proc_do_uts_string,
88 .strategy = sysctl_uts_string,
89 }, 67 },
90 { 68 {
91 .ctl_name = KERN_OSRELEASE,
92 .procname = "osrelease", 69 .procname = "osrelease",
93 .data = init_uts_ns.name.release, 70 .data = init_uts_ns.name.release,
94 .maxlen = sizeof(init_uts_ns.name.release), 71 .maxlen = sizeof(init_uts_ns.name.release),
95 .mode = 0444, 72 .mode = 0444,
96 .proc_handler = proc_do_uts_string, 73 .proc_handler = proc_do_uts_string,
97 .strategy = sysctl_uts_string,
98 }, 74 },
99 { 75 {
100 .ctl_name = KERN_VERSION,
101 .procname = "version", 76 .procname = "version",
102 .data = init_uts_ns.name.version, 77 .data = init_uts_ns.name.version,
103 .maxlen = sizeof(init_uts_ns.name.version), 78 .maxlen = sizeof(init_uts_ns.name.version),
104 .mode = 0444, 79 .mode = 0444,
105 .proc_handler = proc_do_uts_string, 80 .proc_handler = proc_do_uts_string,
106 .strategy = sysctl_uts_string,
107 }, 81 },
108 { 82 {
109 .ctl_name = KERN_NODENAME,
110 .procname = "hostname", 83 .procname = "hostname",
111 .data = init_uts_ns.name.nodename, 84 .data = init_uts_ns.name.nodename,
112 .maxlen = sizeof(init_uts_ns.name.nodename), 85 .maxlen = sizeof(init_uts_ns.name.nodename),
113 .mode = 0644, 86 .mode = 0644,
114 .proc_handler = proc_do_uts_string, 87 .proc_handler = proc_do_uts_string,
115 .strategy = sysctl_uts_string,
116 }, 88 },
117 { 89 {
118 .ctl_name = KERN_DOMAINNAME,
119 .procname = "domainname", 90 .procname = "domainname",
120 .data = init_uts_ns.name.domainname, 91 .data = init_uts_ns.name.domainname,
121 .maxlen = sizeof(init_uts_ns.name.domainname), 92 .maxlen = sizeof(init_uts_ns.name.domainname),
122 .mode = 0644, 93 .mode = 0644,
123 .proc_handler = proc_do_uts_string, 94 .proc_handler = proc_do_uts_string,
124 .strategy = sysctl_uts_string,
125 }, 95 },
126 {} 96 {}
127}; 97};
128 98
129static struct ctl_table uts_root_table[] = { 99static struct ctl_table uts_root_table[] = {
130 { 100 {
131 .ctl_name = CTL_KERN,
132 .procname = "kernel", 101 .procname = "kernel",
133 .mode = 0555, 102 .mode = 0555,
134 .child = uts_kern_table, 103 .child = uts_kern_table,
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a79c4d0407ab..0b8f35918a36 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -912,7 +912,7 @@ config LATENCYTOP
912 912
913config SYSCTL_SYSCALL_CHECK 913config SYSCTL_SYSCALL_CHECK
914 bool "Sysctl checks" 914 bool "Sysctl checks"
915 depends on SYSCTL_SYSCALL 915 depends on SYSCTL
916 ---help--- 916 ---help---
917 sys_sysctl uses binary paths that have been found challenging 917 sys_sysctl uses binary paths that have been found challenging
918 to properly maintain and use. This enables checks that help 918 to properly maintain and use. This enables checks that help
diff --git a/net/802/tr.c b/net/802/tr.c
index e874447ad144..44acce47fcdc 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -635,19 +635,18 @@ struct net_device *alloc_trdev(int sizeof_priv)
635#ifdef CONFIG_SYSCTL 635#ifdef CONFIG_SYSCTL
636static struct ctl_table tr_table[] = { 636static struct ctl_table tr_table[] = {
637 { 637 {
638 .ctl_name = NET_TR_RIF_TIMEOUT,
639 .procname = "rif_timeout", 638 .procname = "rif_timeout",
640 .data = &sysctl_tr_rif_timeout, 639 .data = &sysctl_tr_rif_timeout,
641 .maxlen = sizeof(int), 640 .maxlen = sizeof(int),
642 .mode = 0644, 641 .mode = 0644,
643 .proc_handler = proc_dointvec 642 .proc_handler = proc_dointvec
644 }, 643 },
645 { 0 }, 644 { },
646}; 645};
647 646
648static __initdata struct ctl_path tr_path[] = { 647static __initdata struct ctl_path tr_path[] = {
649 { .procname = "net", .ctl_name = CTL_NET, }, 648 { .procname = "net", },
650 { .procname = "token-ring", .ctl_name = NET_TR, }, 649 { .procname = "token-ring", },
651 { } 650 { }
652}; 651};
653#endif 652#endif
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index 8d237b15183b..04e9c0da7aa9 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -12,25 +12,20 @@
12 12
13static struct ctl_table atalk_table[] = { 13static struct ctl_table atalk_table[] = {
14 { 14 {
15 .ctl_name = NET_ATALK_AARP_EXPIRY_TIME,
16 .procname = "aarp-expiry-time", 15 .procname = "aarp-expiry-time",
17 .data = &sysctl_aarp_expiry_time, 16 .data = &sysctl_aarp_expiry_time,
18 .maxlen = sizeof(int), 17 .maxlen = sizeof(int),
19 .mode = 0644, 18 .mode = 0644,
20 .proc_handler = proc_dointvec_jiffies, 19 .proc_handler = proc_dointvec_jiffies,
21 .strategy = sysctl_jiffies,
22 }, 20 },
23 { 21 {
24 .ctl_name = NET_ATALK_AARP_TICK_TIME,
25 .procname = "aarp-tick-time", 22 .procname = "aarp-tick-time",
26 .data = &sysctl_aarp_tick_time, 23 .data = &sysctl_aarp_tick_time,
27 .maxlen = sizeof(int), 24 .maxlen = sizeof(int),
28 .mode = 0644, 25 .mode = 0644,
29 .proc_handler = proc_dointvec_jiffies, 26 .proc_handler = proc_dointvec_jiffies,
30 .strategy = sysctl_jiffies,
31 }, 27 },
32 { 28 {
33 .ctl_name = NET_ATALK_AARP_RETRANSMIT_LIMIT,
34 .procname = "aarp-retransmit-limit", 29 .procname = "aarp-retransmit-limit",
35 .data = &sysctl_aarp_retransmit_limit, 30 .data = &sysctl_aarp_retransmit_limit,
36 .maxlen = sizeof(int), 31 .maxlen = sizeof(int),
@@ -38,20 +33,18 @@ static struct ctl_table atalk_table[] = {
38 .proc_handler = proc_dointvec, 33 .proc_handler = proc_dointvec,
39 }, 34 },
40 { 35 {
41 .ctl_name = NET_ATALK_AARP_RESOLVE_TIME,
42 .procname = "aarp-resolve-time", 36 .procname = "aarp-resolve-time",
43 .data = &sysctl_aarp_resolve_time, 37 .data = &sysctl_aarp_resolve_time,
44 .maxlen = sizeof(int), 38 .maxlen = sizeof(int),
45 .mode = 0644, 39 .mode = 0644,
46 .proc_handler = proc_dointvec_jiffies, 40 .proc_handler = proc_dointvec_jiffies,
47 .strategy = sysctl_jiffies,
48 }, 41 },
49 { 0 }, 42 { },
50}; 43};
51 44
52static struct ctl_path atalk_path[] = { 45static struct ctl_path atalk_path[] = {
53 { .procname = "net", .ctl_name = CTL_NET, }, 46 { .procname = "net", },
54 { .procname = "appletalk", .ctl_name = NET_ATALK, }, 47 { .procname = "appletalk", },
55 { } 48 { }
56}; 49};
57 50
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 62ee3fb34732..5159be6b2625 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -34,156 +34,128 @@ static ctl_table *ax25_table;
34static int ax25_table_size; 34static int ax25_table_size;
35 35
36static struct ctl_path ax25_path[] = { 36static struct ctl_path ax25_path[] = {
37 { .procname = "net", .ctl_name = CTL_NET, }, 37 { .procname = "net", },
38 { .procname = "ax25", .ctl_name = NET_AX25, }, 38 { .procname = "ax25", },
39 { } 39 { }
40}; 40};
41 41
42static const ctl_table ax25_param_table[] = { 42static const ctl_table ax25_param_table[] = {
43 { 43 {
44 .ctl_name = NET_AX25_IP_DEFAULT_MODE,
45 .procname = "ip_default_mode", 44 .procname = "ip_default_mode",
46 .maxlen = sizeof(int), 45 .maxlen = sizeof(int),
47 .mode = 0644, 46 .mode = 0644,
48 .proc_handler = proc_dointvec_minmax, 47 .proc_handler = proc_dointvec_minmax,
49 .strategy = sysctl_intvec,
50 .extra1 = &min_ipdefmode, 48 .extra1 = &min_ipdefmode,
51 .extra2 = &max_ipdefmode 49 .extra2 = &max_ipdefmode
52 }, 50 },
53 { 51 {
54 .ctl_name = NET_AX25_DEFAULT_MODE,
55 .procname = "ax25_default_mode", 52 .procname = "ax25_default_mode",
56 .maxlen = sizeof(int), 53 .maxlen = sizeof(int),
57 .mode = 0644, 54 .mode = 0644,
58 .proc_handler = proc_dointvec_minmax, 55 .proc_handler = proc_dointvec_minmax,
59 .strategy = sysctl_intvec,
60 .extra1 = &min_axdefmode, 56 .extra1 = &min_axdefmode,
61 .extra2 = &max_axdefmode 57 .extra2 = &max_axdefmode
62 }, 58 },
63 { 59 {
64 .ctl_name = NET_AX25_BACKOFF_TYPE,
65 .procname = "backoff_type", 60 .procname = "backoff_type",
66 .maxlen = sizeof(int), 61 .maxlen = sizeof(int),
67 .mode = 0644, 62 .mode = 0644,
68 .proc_handler = proc_dointvec_minmax, 63 .proc_handler = proc_dointvec_minmax,
69 .strategy = sysctl_intvec,
70 .extra1 = &min_backoff, 64 .extra1 = &min_backoff,
71 .extra2 = &max_backoff 65 .extra2 = &max_backoff
72 }, 66 },
73 { 67 {
74 .ctl_name = NET_AX25_CONNECT_MODE,
75 .procname = "connect_mode", 68 .procname = "connect_mode",
76 .maxlen = sizeof(int), 69 .maxlen = sizeof(int),
77 .mode = 0644, 70 .mode = 0644,
78 .proc_handler = proc_dointvec_minmax, 71 .proc_handler = proc_dointvec_minmax,
79 .strategy = sysctl_intvec,
80 .extra1 = &min_conmode, 72 .extra1 = &min_conmode,
81 .extra2 = &max_conmode 73 .extra2 = &max_conmode
82 }, 74 },
83 { 75 {
84 .ctl_name = NET_AX25_STANDARD_WINDOW,
85 .procname = "standard_window_size", 76 .procname = "standard_window_size",
86 .maxlen = sizeof(int), 77 .maxlen = sizeof(int),
87 .mode = 0644, 78 .mode = 0644,
88 .proc_handler = proc_dointvec_minmax, 79 .proc_handler = proc_dointvec_minmax,
89 .strategy = sysctl_intvec,
90 .extra1 = &min_window, 80 .extra1 = &min_window,
91 .extra2 = &max_window 81 .extra2 = &max_window
92 }, 82 },
93 { 83 {
94 .ctl_name = NET_AX25_EXTENDED_WINDOW,
95 .procname = "extended_window_size", 84 .procname = "extended_window_size",
96 .maxlen = sizeof(int), 85 .maxlen = sizeof(int),
97 .mode = 0644, 86 .mode = 0644,
98 .proc_handler = proc_dointvec_minmax, 87 .proc_handler = proc_dointvec_minmax,
99 .strategy = sysctl_intvec,
100 .extra1 = &min_ewindow, 88 .extra1 = &min_ewindow,
101 .extra2 = &max_ewindow 89 .extra2 = &max_ewindow
102 }, 90 },
103 { 91 {
104 .ctl_name = NET_AX25_T1_TIMEOUT,
105 .procname = "t1_timeout", 92 .procname = "t1_timeout",
106 .maxlen = sizeof(int), 93 .maxlen = sizeof(int),
107 .mode = 0644, 94 .mode = 0644,
108 .proc_handler = proc_dointvec_minmax, 95 .proc_handler = proc_dointvec_minmax,
109 .strategy = sysctl_intvec,
110 .extra1 = &min_t1, 96 .extra1 = &min_t1,
111 .extra2 = &max_t1 97 .extra2 = &max_t1
112 }, 98 },
113 { 99 {
114 .ctl_name = NET_AX25_T2_TIMEOUT,
115 .procname = "t2_timeout", 100 .procname = "t2_timeout",
116 .maxlen = sizeof(int), 101 .maxlen = sizeof(int),
117 .mode = 0644, 102 .mode = 0644,
118 .proc_handler = proc_dointvec_minmax, 103 .proc_handler = proc_dointvec_minmax,
119 .strategy = sysctl_intvec,
120 .extra1 = &min_t2, 104 .extra1 = &min_t2,
121 .extra2 = &max_t2 105 .extra2 = &max_t2
122 }, 106 },
123 { 107 {
124 .ctl_name = NET_AX25_T3_TIMEOUT,
125 .procname = "t3_timeout", 108 .procname = "t3_timeout",
126 .maxlen = sizeof(int), 109 .maxlen = sizeof(int),
127 .mode = 0644, 110 .mode = 0644,
128 .proc_handler = proc_dointvec_minmax, 111 .proc_handler = proc_dointvec_minmax,
129 .strategy = sysctl_intvec,
130 .extra1 = &min_t3, 112 .extra1 = &min_t3,
131 .extra2 = &max_t3 113 .extra2 = &max_t3
132 }, 114 },
133 { 115 {
134 .ctl_name = NET_AX25_IDLE_TIMEOUT,
135 .procname = "idle_timeout", 116 .procname = "idle_timeout",
136 .maxlen = sizeof(int), 117 .maxlen = sizeof(int),
137 .mode = 0644, 118 .mode = 0644,
138 .proc_handler = proc_dointvec_minmax, 119 .proc_handler = proc_dointvec_minmax,
139 .strategy = sysctl_intvec,
140 .extra1 = &min_idle, 120 .extra1 = &min_idle,
141 .extra2 = &max_idle 121 .extra2 = &max_idle
142 }, 122 },
143 { 123 {
144 .ctl_name = NET_AX25_N2,
145 .procname = "maximum_retry_count", 124 .procname = "maximum_retry_count",
146 .maxlen = sizeof(int), 125 .maxlen = sizeof(int),
147 .mode = 0644, 126 .mode = 0644,
148 .proc_handler = proc_dointvec_minmax, 127 .proc_handler = proc_dointvec_minmax,
149 .strategy = sysctl_intvec,
150 .extra1 = &min_n2, 128 .extra1 = &min_n2,
151 .extra2 = &max_n2 129 .extra2 = &max_n2
152 }, 130 },
153 { 131 {
154 .ctl_name = NET_AX25_PACLEN,
155 .procname = "maximum_packet_length", 132 .procname = "maximum_packet_length",
156 .maxlen = sizeof(int), 133 .maxlen = sizeof(int),
157 .mode = 0644, 134 .mode = 0644,
158 .proc_handler = proc_dointvec_minmax, 135 .proc_handler = proc_dointvec_minmax,
159 .strategy = sysctl_intvec,
160 .extra1 = &min_paclen, 136 .extra1 = &min_paclen,
161 .extra2 = &max_paclen 137 .extra2 = &max_paclen
162 }, 138 },
163 { 139 {
164 .ctl_name = NET_AX25_PROTOCOL,
165 .procname = "protocol", 140 .procname = "protocol",
166 .maxlen = sizeof(int), 141 .maxlen = sizeof(int),
167 .mode = 0644, 142 .mode = 0644,
168 .proc_handler = proc_dointvec_minmax, 143 .proc_handler = proc_dointvec_minmax,
169 .strategy = sysctl_intvec,
170 .extra1 = &min_proto, 144 .extra1 = &min_proto,
171 .extra2 = &max_proto 145 .extra2 = &max_proto
172 }, 146 },
173#ifdef CONFIG_AX25_DAMA_SLAVE 147#ifdef CONFIG_AX25_DAMA_SLAVE
174 { 148 {
175 .ctl_name = NET_AX25_DAMA_SLAVE_TIMEOUT,
176 .procname = "dama_slave_timeout", 149 .procname = "dama_slave_timeout",
177 .maxlen = sizeof(int), 150 .maxlen = sizeof(int),
178 .mode = 0644, 151 .mode = 0644,
179 .proc_handler = proc_dointvec_minmax, 152 .proc_handler = proc_dointvec_minmax,
180 .strategy = sysctl_intvec,
181 .extra1 = &min_ds_timeout, 153 .extra1 = &min_ds_timeout,
182 .extra2 = &max_ds_timeout 154 .extra2 = &max_ds_timeout
183 }, 155 },
184#endif 156#endif
185 157
186 { .ctl_name = 0 } /* that's all, folks! */ 158 { } /* that's all, folks! */
187}; 159};
188 160
189void ax25_register_sysctl(void) 161void ax25_register_sysctl(void)
@@ -212,11 +184,9 @@ void ax25_register_sysctl(void)
212 return; 184 return;
213 } 185 }
214 ax25_table[n].child = ax25_dev->systable = child; 186 ax25_table[n].child = ax25_dev->systable = child;
215 ax25_table[n].ctl_name = n + 1;
216 ax25_table[n].procname = ax25_dev->dev->name; 187 ax25_table[n].procname = ax25_dev->dev->name;
217 ax25_table[n].mode = 0555; 188 ax25_table[n].mode = 0555;
218 189
219 child[AX25_MAX_VALUES].ctl_name = 0; /* just in case... */
220 190
221 for (k = 0; k < AX25_MAX_VALUES; k++) 191 for (k = 0; k < AX25_MAX_VALUES; k++)
222 child[k].data = &ax25_dev->values[k]; 192 child[k].data = &ax25_dev->values[k];
@@ -233,7 +203,7 @@ void ax25_unregister_sysctl(void)
233 ctl_table *p; 203 ctl_table *p;
234 unregister_sysctl_table(ax25_table_header); 204 unregister_sysctl_table(ax25_table_header);
235 205
236 for (p = ax25_table; p->ctl_name; p++) 206 for (p = ax25_table; p->procname; p++)
237 kfree(p->child); 207 kfree(p->child);
238 kfree(ax25_table); 208 kfree(ax25_table);
239} 209}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index a16a2342f6bf..268e2e725888 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -1013,12 +1013,12 @@ static ctl_table brnf_table[] = {
1013 .mode = 0644, 1013 .mode = 0644,
1014 .proc_handler = brnf_sysctl_call_tables, 1014 .proc_handler = brnf_sysctl_call_tables,
1015 }, 1015 },
1016 { .ctl_name = 0 } 1016 { }
1017}; 1017};
1018 1018
1019static struct ctl_path brnf_path[] = { 1019static struct ctl_path brnf_path[] = {
1020 { .procname = "net", .ctl_name = CTL_NET, }, 1020 { .procname = "net", },
1021 { .procname = "bridge", .ctl_name = NET_BRIDGE, }, 1021 { .procname = "bridge", },
1022 { } 1022 { }
1023}; 1023};
1024#endif 1024#endif
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index a08a35bf0a7b..f35377b643e4 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2566,21 +2566,18 @@ static struct neigh_sysctl_table {
2566} neigh_sysctl_template __read_mostly = { 2566} neigh_sysctl_template __read_mostly = {
2567 .neigh_vars = { 2567 .neigh_vars = {
2568 { 2568 {
2569 .ctl_name = NET_NEIGH_MCAST_SOLICIT,
2570 .procname = "mcast_solicit", 2569 .procname = "mcast_solicit",
2571 .maxlen = sizeof(int), 2570 .maxlen = sizeof(int),
2572 .mode = 0644, 2571 .mode = 0644,
2573 .proc_handler = proc_dointvec, 2572 .proc_handler = proc_dointvec,
2574 }, 2573 },
2575 { 2574 {
2576 .ctl_name = NET_NEIGH_UCAST_SOLICIT,
2577 .procname = "ucast_solicit", 2575 .procname = "ucast_solicit",
2578 .maxlen = sizeof(int), 2576 .maxlen = sizeof(int),
2579 .mode = 0644, 2577 .mode = 0644,
2580 .proc_handler = proc_dointvec, 2578 .proc_handler = proc_dointvec,
2581 }, 2579 },
2582 { 2580 {
2583 .ctl_name = NET_NEIGH_APP_SOLICIT,
2584 .procname = "app_solicit", 2581 .procname = "app_solicit",
2585 .maxlen = sizeof(int), 2582 .maxlen = sizeof(int),
2586 .mode = 0644, 2583 .mode = 0644,
@@ -2593,38 +2590,30 @@ static struct neigh_sysctl_table {
2593 .proc_handler = proc_dointvec_userhz_jiffies, 2590 .proc_handler = proc_dointvec_userhz_jiffies,
2594 }, 2591 },
2595 { 2592 {
2596 .ctl_name = NET_NEIGH_REACHABLE_TIME,
2597 .procname = "base_reachable_time", 2593 .procname = "base_reachable_time",
2598 .maxlen = sizeof(int), 2594 .maxlen = sizeof(int),
2599 .mode = 0644, 2595 .mode = 0644,
2600 .proc_handler = proc_dointvec_jiffies, 2596 .proc_handler = proc_dointvec_jiffies,
2601 .strategy = sysctl_jiffies,
2602 }, 2597 },
2603 { 2598 {
2604 .ctl_name = NET_NEIGH_DELAY_PROBE_TIME,
2605 .procname = "delay_first_probe_time", 2599 .procname = "delay_first_probe_time",
2606 .maxlen = sizeof(int), 2600 .maxlen = sizeof(int),
2607 .mode = 0644, 2601 .mode = 0644,
2608 .proc_handler = proc_dointvec_jiffies, 2602 .proc_handler = proc_dointvec_jiffies,
2609 .strategy = sysctl_jiffies,
2610 }, 2603 },
2611 { 2604 {
2612 .ctl_name = NET_NEIGH_GC_STALE_TIME,
2613 .procname = "gc_stale_time", 2605 .procname = "gc_stale_time",
2614 .maxlen = sizeof(int), 2606 .maxlen = sizeof(int),
2615 .mode = 0644, 2607 .mode = 0644,
2616 .proc_handler = proc_dointvec_jiffies, 2608 .proc_handler = proc_dointvec_jiffies,
2617 .strategy = sysctl_jiffies,
2618 }, 2609 },
2619 { 2610 {
2620 .ctl_name = NET_NEIGH_UNRES_QLEN,
2621 .procname = "unres_qlen", 2611 .procname = "unres_qlen",
2622 .maxlen = sizeof(int), 2612 .maxlen = sizeof(int),
2623 .mode = 0644, 2613 .mode = 0644,
2624 .proc_handler = proc_dointvec, 2614 .proc_handler = proc_dointvec,
2625 }, 2615 },
2626 { 2616 {
2627 .ctl_name = NET_NEIGH_PROXY_QLEN,
2628 .procname = "proxy_qlen", 2617 .procname = "proxy_qlen",
2629 .maxlen = sizeof(int), 2618 .maxlen = sizeof(int),
2630 .mode = 0644, 2619 .mode = 0644,
@@ -2649,45 +2638,36 @@ static struct neigh_sysctl_table {
2649 .proc_handler = proc_dointvec_userhz_jiffies, 2638 .proc_handler = proc_dointvec_userhz_jiffies,
2650 }, 2639 },
2651 { 2640 {
2652 .ctl_name = NET_NEIGH_RETRANS_TIME_MS,
2653 .procname = "retrans_time_ms", 2641 .procname = "retrans_time_ms",
2654 .maxlen = sizeof(int), 2642 .maxlen = sizeof(int),
2655 .mode = 0644, 2643 .mode = 0644,
2656 .proc_handler = proc_dointvec_ms_jiffies, 2644 .proc_handler = proc_dointvec_ms_jiffies,
2657 .strategy = sysctl_ms_jiffies,
2658 }, 2645 },
2659 { 2646 {
2660 .ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
2661 .procname = "base_reachable_time_ms", 2647 .procname = "base_reachable_time_ms",
2662 .maxlen = sizeof(int), 2648 .maxlen = sizeof(int),
2663 .mode = 0644, 2649 .mode = 0644,
2664 .proc_handler = proc_dointvec_ms_jiffies, 2650 .proc_handler = proc_dointvec_ms_jiffies,
2665 .strategy = sysctl_ms_jiffies,
2666 }, 2651 },
2667 { 2652 {
2668 .ctl_name = NET_NEIGH_GC_INTERVAL,
2669 .procname = "gc_interval", 2653 .procname = "gc_interval",
2670 .maxlen = sizeof(int), 2654 .maxlen = sizeof(int),
2671 .mode = 0644, 2655 .mode = 0644,
2672 .proc_handler = proc_dointvec_jiffies, 2656 .proc_handler = proc_dointvec_jiffies,
2673 .strategy = sysctl_jiffies,
2674 }, 2657 },
2675 { 2658 {
2676 .ctl_name = NET_NEIGH_GC_THRESH1,
2677 .procname = "gc_thresh1", 2659 .procname = "gc_thresh1",
2678 .maxlen = sizeof(int), 2660 .maxlen = sizeof(int),
2679 .mode = 0644, 2661 .mode = 0644,
2680 .proc_handler = proc_dointvec, 2662 .proc_handler = proc_dointvec,
2681 }, 2663 },
2682 { 2664 {
2683 .ctl_name = NET_NEIGH_GC_THRESH2,
2684 .procname = "gc_thresh2", 2665 .procname = "gc_thresh2",
2685 .maxlen = sizeof(int), 2666 .maxlen = sizeof(int),
2686 .mode = 0644, 2667 .mode = 0644,
2687 .proc_handler = proc_dointvec, 2668 .proc_handler = proc_dointvec,
2688 }, 2669 },
2689 { 2670 {
2690 .ctl_name = NET_NEIGH_GC_THRESH3,
2691 .procname = "gc_thresh3", 2671 .procname = "gc_thresh3",
2692 .maxlen = sizeof(int), 2672 .maxlen = sizeof(int),
2693 .mode = 0644, 2673 .mode = 0644,
@@ -2699,7 +2679,7 @@ static struct neigh_sysctl_table {
2699 2679
2700int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, 2680int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
2701 int p_id, int pdev_id, char *p_name, 2681 int p_id, int pdev_id, char *p_name,
2702 proc_handler *handler, ctl_handler *strategy) 2682 proc_handler *handler)
2703{ 2683{
2704 struct neigh_sysctl_table *t; 2684 struct neigh_sysctl_table *t;
2705 const char *dev_name_source = NULL; 2685 const char *dev_name_source = NULL;
@@ -2710,10 +2690,10 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
2710#define NEIGH_CTL_PATH_DEV 3 2690#define NEIGH_CTL_PATH_DEV 3
2711 2691
2712 struct ctl_path neigh_path[] = { 2692 struct ctl_path neigh_path[] = {
2713 { .procname = "net", .ctl_name = CTL_NET, }, 2693 { .procname = "net", },
2714 { .procname = "proto", .ctl_name = 0, }, 2694 { .procname = "proto", },
2715 { .procname = "neigh", .ctl_name = 0, }, 2695 { .procname = "neigh", },
2716 { .procname = "default", .ctl_name = NET_PROTO_CONF_DEFAULT, }, 2696 { .procname = "default", },
2717 { }, 2697 { },
2718 }; 2698 };
2719 2699
@@ -2738,7 +2718,6 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
2738 2718
2739 if (dev) { 2719 if (dev) {
2740 dev_name_source = dev->name; 2720 dev_name_source = dev->name;
2741 neigh_path[NEIGH_CTL_PATH_DEV].ctl_name = dev->ifindex;
2742 /* Terminate the table early */ 2721 /* Terminate the table early */
2743 memset(&t->neigh_vars[14], 0, sizeof(t->neigh_vars[14])); 2722 memset(&t->neigh_vars[14], 0, sizeof(t->neigh_vars[14]));
2744 } else { 2723 } else {
@@ -2750,31 +2729,19 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
2750 } 2729 }
2751 2730
2752 2731
2753 if (handler || strategy) { 2732 if (handler) {
2754 /* RetransTime */ 2733 /* RetransTime */
2755 t->neigh_vars[3].proc_handler = handler; 2734 t->neigh_vars[3].proc_handler = handler;
2756 t->neigh_vars[3].strategy = strategy;
2757 t->neigh_vars[3].extra1 = dev; 2735 t->neigh_vars[3].extra1 = dev;
2758 if (!strategy)
2759 t->neigh_vars[3].ctl_name = CTL_UNNUMBERED;
2760 /* ReachableTime */ 2736 /* ReachableTime */
2761 t->neigh_vars[4].proc_handler = handler; 2737 t->neigh_vars[4].proc_handler = handler;
2762 t->neigh_vars[4].strategy = strategy;
2763 t->neigh_vars[4].extra1 = dev; 2738 t->neigh_vars[4].extra1 = dev;
2764 if (!strategy)
2765 t->neigh_vars[4].ctl_name = CTL_UNNUMBERED;
2766 /* RetransTime (in milliseconds)*/ 2739 /* RetransTime (in milliseconds)*/
2767 t->neigh_vars[12].proc_handler = handler; 2740 t->neigh_vars[12].proc_handler = handler;
2768 t->neigh_vars[12].strategy = strategy;
2769 t->neigh_vars[12].extra1 = dev; 2741 t->neigh_vars[12].extra1 = dev;
2770 if (!strategy)
2771 t->neigh_vars[12].ctl_name = CTL_UNNUMBERED;
2772 /* ReachableTime (in milliseconds) */ 2742 /* ReachableTime (in milliseconds) */
2773 t->neigh_vars[13].proc_handler = handler; 2743 t->neigh_vars[13].proc_handler = handler;
2774 t->neigh_vars[13].strategy = strategy;
2775 t->neigh_vars[13].extra1 = dev; 2744 t->neigh_vars[13].extra1 = dev;
2776 if (!strategy)
2777 t->neigh_vars[13].ctl_name = CTL_UNNUMBERED;
2778 } 2745 }
2779 2746
2780 t->dev_name = kstrdup(dev_name_source, GFP_KERNEL); 2747 t->dev_name = kstrdup(dev_name_source, GFP_KERNEL);
@@ -2782,9 +2749,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
2782 goto free; 2749 goto free;
2783 2750
2784 neigh_path[NEIGH_CTL_PATH_DEV].procname = t->dev_name; 2751 neigh_path[NEIGH_CTL_PATH_DEV].procname = t->dev_name;
2785 neigh_path[NEIGH_CTL_PATH_NEIGH].ctl_name = pdev_id;
2786 neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name; 2752 neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
2787 neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id;
2788 2753
2789 t->sysctl_header = 2754 t->sysctl_header =
2790 register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars); 2755 register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars);
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 8938fa79124d..06124872af5b 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -19,7 +19,6 @@
19static struct ctl_table net_core_table[] = { 19static struct ctl_table net_core_table[] = {
20#ifdef CONFIG_NET 20#ifdef CONFIG_NET
21 { 21 {
22 .ctl_name = NET_CORE_WMEM_MAX,
23 .procname = "wmem_max", 22 .procname = "wmem_max",
24 .data = &sysctl_wmem_max, 23 .data = &sysctl_wmem_max,
25 .maxlen = sizeof(int), 24 .maxlen = sizeof(int),
@@ -27,7 +26,6 @@ static struct ctl_table net_core_table[] = {
27 .proc_handler = proc_dointvec 26 .proc_handler = proc_dointvec
28 }, 27 },
29 { 28 {
30 .ctl_name = NET_CORE_RMEM_MAX,
31 .procname = "rmem_max", 29 .procname = "rmem_max",
32 .data = &sysctl_rmem_max, 30 .data = &sysctl_rmem_max,
33 .maxlen = sizeof(int), 31 .maxlen = sizeof(int),
@@ -35,7 +33,6 @@ static struct ctl_table net_core_table[] = {
35 .proc_handler = proc_dointvec 33 .proc_handler = proc_dointvec
36 }, 34 },
37 { 35 {
38 .ctl_name = NET_CORE_WMEM_DEFAULT,
39 .procname = "wmem_default", 36 .procname = "wmem_default",
40 .data = &sysctl_wmem_default, 37 .data = &sysctl_wmem_default,
41 .maxlen = sizeof(int), 38 .maxlen = sizeof(int),
@@ -43,7 +40,6 @@ static struct ctl_table net_core_table[] = {
43 .proc_handler = proc_dointvec 40 .proc_handler = proc_dointvec
44 }, 41 },
45 { 42 {
46 .ctl_name = NET_CORE_RMEM_DEFAULT,
47 .procname = "rmem_default", 43 .procname = "rmem_default",
48 .data = &sysctl_rmem_default, 44 .data = &sysctl_rmem_default,
49 .maxlen = sizeof(int), 45 .maxlen = sizeof(int),
@@ -51,7 +47,6 @@ static struct ctl_table net_core_table[] = {
51 .proc_handler = proc_dointvec 47 .proc_handler = proc_dointvec
52 }, 48 },
53 { 49 {
54 .ctl_name = NET_CORE_DEV_WEIGHT,
55 .procname = "dev_weight", 50 .procname = "dev_weight",
56 .data = &weight_p, 51 .data = &weight_p,
57 .maxlen = sizeof(int), 52 .maxlen = sizeof(int),
@@ -59,7 +54,6 @@ static struct ctl_table net_core_table[] = {
59 .proc_handler = proc_dointvec 54 .proc_handler = proc_dointvec
60 }, 55 },
61 { 56 {
62 .ctl_name = NET_CORE_MAX_BACKLOG,
63 .procname = "netdev_max_backlog", 57 .procname = "netdev_max_backlog",
64 .data = &netdev_max_backlog, 58 .data = &netdev_max_backlog,
65 .maxlen = sizeof(int), 59 .maxlen = sizeof(int),
@@ -67,16 +61,13 @@ static struct ctl_table net_core_table[] = {
67 .proc_handler = proc_dointvec 61 .proc_handler = proc_dointvec
68 }, 62 },
69 { 63 {
70 .ctl_name = NET_CORE_MSG_COST,
71 .procname = "message_cost", 64 .procname = "message_cost",
72 .data = &net_ratelimit_state.interval, 65 .data = &net_ratelimit_state.interval,
73 .maxlen = sizeof(int), 66 .maxlen = sizeof(int),
74 .mode = 0644, 67 .mode = 0644,
75 .proc_handler = proc_dointvec_jiffies, 68 .proc_handler = proc_dointvec_jiffies,
76 .strategy = sysctl_jiffies,
77 }, 69 },
78 { 70 {
79 .ctl_name = NET_CORE_MSG_BURST,
80 .procname = "message_burst", 71 .procname = "message_burst",
81 .data = &net_ratelimit_state.burst, 72 .data = &net_ratelimit_state.burst,
82 .maxlen = sizeof(int), 73 .maxlen = sizeof(int),
@@ -84,7 +75,6 @@ static struct ctl_table net_core_table[] = {
84 .proc_handler = proc_dointvec, 75 .proc_handler = proc_dointvec,
85 }, 76 },
86 { 77 {
87 .ctl_name = NET_CORE_OPTMEM_MAX,
88 .procname = "optmem_max", 78 .procname = "optmem_max",
89 .data = &sysctl_optmem_max, 79 .data = &sysctl_optmem_max,
90 .maxlen = sizeof(int), 80 .maxlen = sizeof(int),
@@ -93,7 +83,6 @@ static struct ctl_table net_core_table[] = {
93 }, 83 },
94#endif /* CONFIG_NET */ 84#endif /* CONFIG_NET */
95 { 85 {
96 .ctl_name = NET_CORE_BUDGET,
97 .procname = "netdev_budget", 86 .procname = "netdev_budget",
98 .data = &netdev_budget, 87 .data = &netdev_budget,
99 .maxlen = sizeof(int), 88 .maxlen = sizeof(int),
@@ -101,31 +90,29 @@ static struct ctl_table net_core_table[] = {
101 .proc_handler = proc_dointvec 90 .proc_handler = proc_dointvec
102 }, 91 },
103 { 92 {
104 .ctl_name = NET_CORE_WARNINGS,
105 .procname = "warnings", 93 .procname = "warnings",
106 .data = &net_msg_warn, 94 .data = &net_msg_warn,
107 .maxlen = sizeof(int), 95 .maxlen = sizeof(int),
108 .mode = 0644, 96 .mode = 0644,
109 .proc_handler = proc_dointvec 97 .proc_handler = proc_dointvec
110 }, 98 },
111 { .ctl_name = 0 } 99 { }
112}; 100};
113 101
114static struct ctl_table netns_core_table[] = { 102static struct ctl_table netns_core_table[] = {
115 { 103 {
116 .ctl_name = NET_CORE_SOMAXCONN,
117 .procname = "somaxconn", 104 .procname = "somaxconn",
118 .data = &init_net.core.sysctl_somaxconn, 105 .data = &init_net.core.sysctl_somaxconn,
119 .maxlen = sizeof(int), 106 .maxlen = sizeof(int),
120 .mode = 0644, 107 .mode = 0644,
121 .proc_handler = proc_dointvec 108 .proc_handler = proc_dointvec
122 }, 109 },
123 { .ctl_name = 0 } 110 { }
124}; 111};
125 112
126__net_initdata struct ctl_path net_core_path[] = { 113__net_initdata struct ctl_path net_core_path[] = {
127 { .procname = "net", .ctl_name = CTL_NET, }, 114 { .procname = "net", },
128 { .procname = "core", .ctl_name = NET_CORE, }, 115 { .procname = "core", },
129 { }, 116 { },
130}; 117};
131 118
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
index a5a1856234e7..563943822e58 100644
--- a/net/dccp/sysctl.c
+++ b/net/dccp/sysctl.c
@@ -93,13 +93,13 @@ static struct ctl_table dccp_default_table[] = {
93 .proc_handler = proc_dointvec_ms_jiffies, 93 .proc_handler = proc_dointvec_ms_jiffies,
94 }, 94 },
95 95
96 { .ctl_name = 0, } 96 { }
97}; 97};
98 98
99static struct ctl_path dccp_path[] = { 99static struct ctl_path dccp_path[] = {
100 { .procname = "net", .ctl_name = CTL_NET, }, 100 { .procname = "net", },
101 { .procname = "dccp", .ctl_name = NET_DCCP, }, 101 { .procname = "dccp", },
102 { .procname = "default", .ctl_name = NET_DCCP_DEFAULT, }, 102 { .procname = "default", },
103 { } 103 { }
104}; 104};
105 105
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index f20dec9cfa06..238af093495b 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -89,7 +89,6 @@ static struct dn_dev_parms dn_dev_list[] = {
89 .t2 = 1, 89 .t2 = 1,
90 .t3 = 10, 90 .t3 = 10,
91 .name = "ethernet", 91 .name = "ethernet",
92 .ctl_name = NET_DECNET_CONF_ETHER,
93 .up = dn_eth_up, 92 .up = dn_eth_up,
94 .down = dn_eth_down, 93 .down = dn_eth_down,
95 .timer3 = dn_send_brd_hello, 94 .timer3 = dn_send_brd_hello,
@@ -101,7 +100,6 @@ static struct dn_dev_parms dn_dev_list[] = {
101 .t2 = 1, 100 .t2 = 1,
102 .t3 = 10, 101 .t3 = 10,
103 .name = "ipgre", 102 .name = "ipgre",
104 .ctl_name = NET_DECNET_CONF_GRE,
105 .timer3 = dn_send_brd_hello, 103 .timer3 = dn_send_brd_hello,
106}, 104},
107#if 0 105#if 0
@@ -112,7 +110,6 @@ static struct dn_dev_parms dn_dev_list[] = {
112 .t2 = 1, 110 .t2 = 1,
113 .t3 = 120, 111 .t3 = 120,
114 .name = "x25", 112 .name = "x25",
115 .ctl_name = NET_DECNET_CONF_X25,
116 .timer3 = dn_send_ptp_hello, 113 .timer3 = dn_send_ptp_hello,
117}, 114},
118#endif 115#endif
@@ -124,7 +121,6 @@ static struct dn_dev_parms dn_dev_list[] = {
124 .t2 = 1, 121 .t2 = 1,
125 .t3 = 10, 122 .t3 = 10,
126 .name = "ppp", 123 .name = "ppp",
127 .ctl_name = NET_DECNET_CONF_PPP,
128 .timer3 = dn_send_brd_hello, 124 .timer3 = dn_send_brd_hello,
129}, 125},
130#endif 126#endif
@@ -135,7 +131,6 @@ static struct dn_dev_parms dn_dev_list[] = {
135 .t2 = 1, 131 .t2 = 1,
136 .t3 = 120, 132 .t3 = 120,
137 .name = "ddcmp", 133 .name = "ddcmp",
138 .ctl_name = NET_DECNET_CONF_DDCMP,
139 .timer3 = dn_send_ptp_hello, 134 .timer3 = dn_send_ptp_hello,
140}, 135},
141{ 136{
@@ -145,7 +140,6 @@ static struct dn_dev_parms dn_dev_list[] = {
145 .t2 = 1, 140 .t2 = 1,
146 .t3 = 10, 141 .t3 = 10,
147 .name = "loopback", 142 .name = "loopback",
148 .ctl_name = NET_DECNET_CONF_LOOPBACK,
149 .timer3 = dn_send_brd_hello, 143 .timer3 = dn_send_brd_hello,
150} 144}
151}; 145};
@@ -166,10 +160,6 @@ static int max_priority[] = { 127 }; /* From DECnet spec */
166 160
167static int dn_forwarding_proc(ctl_table *, int, 161static int dn_forwarding_proc(ctl_table *, int,
168 void __user *, size_t *, loff_t *); 162 void __user *, size_t *, loff_t *);
169static int dn_forwarding_sysctl(ctl_table *table,
170 void __user *oldval, size_t __user *oldlenp,
171 void __user *newval, size_t newlen);
172
173static struct dn_dev_sysctl_table { 163static struct dn_dev_sysctl_table {
174 struct ctl_table_header *sysctl_header; 164 struct ctl_table_header *sysctl_header;
175 ctl_table dn_dev_vars[5]; 165 ctl_table dn_dev_vars[5];
@@ -177,44 +167,36 @@ static struct dn_dev_sysctl_table {
177 NULL, 167 NULL,
178 { 168 {
179 { 169 {
180 .ctl_name = NET_DECNET_CONF_DEV_FORWARDING,
181 .procname = "forwarding", 170 .procname = "forwarding",
182 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding), 171 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
183 .maxlen = sizeof(int), 172 .maxlen = sizeof(int),
184 .mode = 0644, 173 .mode = 0644,
185 .proc_handler = dn_forwarding_proc, 174 .proc_handler = dn_forwarding_proc,
186 .strategy = dn_forwarding_sysctl,
187 }, 175 },
188 { 176 {
189 .ctl_name = NET_DECNET_CONF_DEV_PRIORITY,
190 .procname = "priority", 177 .procname = "priority",
191 .data = (void *)DN_DEV_PARMS_OFFSET(priority), 178 .data = (void *)DN_DEV_PARMS_OFFSET(priority),
192 .maxlen = sizeof(int), 179 .maxlen = sizeof(int),
193 .mode = 0644, 180 .mode = 0644,
194 .proc_handler = proc_dointvec_minmax, 181 .proc_handler = proc_dointvec_minmax,
195 .strategy = sysctl_intvec,
196 .extra1 = &min_priority, 182 .extra1 = &min_priority,
197 .extra2 = &max_priority 183 .extra2 = &max_priority
198 }, 184 },
199 { 185 {
200 .ctl_name = NET_DECNET_CONF_DEV_T2,
201 .procname = "t2", 186 .procname = "t2",
202 .data = (void *)DN_DEV_PARMS_OFFSET(t2), 187 .data = (void *)DN_DEV_PARMS_OFFSET(t2),
203 .maxlen = sizeof(int), 188 .maxlen = sizeof(int),
204 .mode = 0644, 189 .mode = 0644,
205 .proc_handler = proc_dointvec_minmax, 190 .proc_handler = proc_dointvec_minmax,
206 .strategy = sysctl_intvec,
207 .extra1 = &min_t2, 191 .extra1 = &min_t2,
208 .extra2 = &max_t2 192 .extra2 = &max_t2
209 }, 193 },
210 { 194 {
211 .ctl_name = NET_DECNET_CONF_DEV_T3,
212 .procname = "t3", 195 .procname = "t3",
213 .data = (void *)DN_DEV_PARMS_OFFSET(t3), 196 .data = (void *)DN_DEV_PARMS_OFFSET(t3),
214 .maxlen = sizeof(int), 197 .maxlen = sizeof(int),
215 .mode = 0644, 198 .mode = 0644,
216 .proc_handler = proc_dointvec_minmax, 199 .proc_handler = proc_dointvec_minmax,
217 .strategy = sysctl_intvec,
218 .extra1 = &min_t3, 200 .extra1 = &min_t3,
219 .extra2 = &max_t3 201 .extra2 = &max_t3
220 }, 202 },
@@ -230,9 +212,9 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
230#define DN_CTL_PATH_DEV 3 212#define DN_CTL_PATH_DEV 3
231 213
232 struct ctl_path dn_ctl_path[] = { 214 struct ctl_path dn_ctl_path[] = {
233 { .procname = "net", .ctl_name = CTL_NET, }, 215 { .procname = "net", },
234 { .procname = "decnet", .ctl_name = NET_DECNET, }, 216 { .procname = "decnet", },
235 { .procname = "conf", .ctl_name = NET_DECNET_CONF, }, 217 { .procname = "conf", },
236 { /* to be set */ }, 218 { /* to be set */ },
237 { }, 219 { },
238 }; 220 };
@@ -248,10 +230,8 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
248 230
249 if (dev) { 231 if (dev) {
250 dn_ctl_path[DN_CTL_PATH_DEV].procname = dev->name; 232 dn_ctl_path[DN_CTL_PATH_DEV].procname = dev->name;
251 dn_ctl_path[DN_CTL_PATH_DEV].ctl_name = dev->ifindex;
252 } else { 233 } else {
253 dn_ctl_path[DN_CTL_PATH_DEV].procname = parms->name; 234 dn_ctl_path[DN_CTL_PATH_DEV].procname = parms->name;
254 dn_ctl_path[DN_CTL_PATH_DEV].ctl_name = parms->ctl_name;
255 } 235 }
256 236
257 t->dn_dev_vars[0].extra1 = (void *)dev; 237 t->dn_dev_vars[0].extra1 = (void *)dev;
@@ -317,44 +297,6 @@ static int dn_forwarding_proc(ctl_table *table, int write,
317#endif 297#endif
318} 298}
319 299
320static int dn_forwarding_sysctl(ctl_table *table,
321 void __user *oldval, size_t __user *oldlenp,
322 void __user *newval, size_t newlen)
323{
324#ifdef CONFIG_DECNET_ROUTER
325 struct net_device *dev = table->extra1;
326 struct dn_dev *dn_db;
327 int value;
328
329 if (table->extra1 == NULL)
330 return -EINVAL;
331
332 dn_db = dev->dn_ptr;
333
334 if (newval && newlen) {
335 if (newlen != sizeof(int))
336 return -EINVAL;
337
338 if (get_user(value, (int __user *)newval))
339 return -EFAULT;
340 if (value < 0)
341 return -EINVAL;
342 if (value > 2)
343 return -EINVAL;
344
345 if (dn_db->parms.down)
346 dn_db->parms.down(dev);
347 dn_db->parms.forwarding = value;
348 if (dn_db->parms.up)
349 dn_db->parms.up(dev);
350 }
351
352 return 0;
353#else
354 return -EINVAL;
355#endif
356}
357
358#else /* CONFIG_SYSCTL */ 300#else /* CONFIG_SYSCTL */
359static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) 301static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
360{ 302{
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 2036568beea9..be3eb8e23288 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -131,39 +131,6 @@ static int parse_addr(__le16 *addr, char *str)
131 return 0; 131 return 0;
132} 132}
133 133
134
135static int dn_node_address_strategy(ctl_table *table,
136 void __user *oldval, size_t __user *oldlenp,
137 void __user *newval, size_t newlen)
138{
139 size_t len;
140 __le16 addr;
141
142 if (oldval && oldlenp) {
143 if (get_user(len, oldlenp))
144 return -EFAULT;
145 if (len) {
146 if (len != sizeof(unsigned short))
147 return -EINVAL;
148 if (put_user(decnet_address, (__le16 __user *)oldval))
149 return -EFAULT;
150 }
151 }
152 if (newval && newlen) {
153 if (newlen != sizeof(unsigned short))
154 return -EINVAL;
155 if (get_user(addr, (__le16 __user *)newval))
156 return -EFAULT;
157
158 dn_dev_devices_off();
159
160 decnet_address = addr;
161
162 dn_dev_devices_on();
163 }
164 return 0;
165}
166
167static int dn_node_address_handler(ctl_table *table, int write, 134static int dn_node_address_handler(ctl_table *table, int write,
168 void __user *buffer, 135 void __user *buffer,
169 size_t *lenp, loff_t *ppos) 136 size_t *lenp, loff_t *ppos)
@@ -215,64 +182,6 @@ static int dn_node_address_handler(ctl_table *table, int write,
215 return 0; 182 return 0;
216} 183}
217 184
218
219static int dn_def_dev_strategy(ctl_table *table,
220 void __user *oldval, size_t __user *oldlenp,
221 void __user *newval, size_t newlen)
222{
223 size_t len;
224 struct net_device *dev;
225 char devname[17];
226 size_t namel;
227 int rv = 0;
228
229 devname[0] = 0;
230
231 if (oldval && oldlenp) {
232 if (get_user(len, oldlenp))
233 return -EFAULT;
234 if (len) {
235 dev = dn_dev_get_default();
236 if (dev) {
237 strcpy(devname, dev->name);
238 dev_put(dev);
239 }
240
241 namel = strlen(devname) + 1;
242 if (len > namel) len = namel;
243
244 if (copy_to_user(oldval, devname, len))
245 return -EFAULT;
246
247 if (put_user(len, oldlenp))
248 return -EFAULT;
249 }
250 }
251
252 if (newval && newlen) {
253 if (newlen > 16)
254 return -E2BIG;
255
256 if (copy_from_user(devname, newval, newlen))
257 return -EFAULT;
258
259 devname[newlen] = 0;
260
261 dev = dev_get_by_name(&init_net, devname);
262 if (dev == NULL)
263 return -ENODEV;
264
265 rv = -ENODEV;
266 if (dev->dn_ptr != NULL)
267 rv = dn_dev_set_default(dev, 1);
268 if (rv)
269 dev_put(dev);
270 }
271
272 return rv;
273}
274
275
276static int dn_def_dev_handler(ctl_table *table, int write, 185static int dn_def_dev_handler(ctl_table *table, int write,
277 void __user *buffer, 186 void __user *buffer,
278 size_t *lenp, loff_t *ppos) 187 size_t *lenp, loff_t *ppos)
@@ -338,138 +247,112 @@ static int dn_def_dev_handler(ctl_table *table, int write,
338 247
339static ctl_table dn_table[] = { 248static ctl_table dn_table[] = {
340 { 249 {
341 .ctl_name = NET_DECNET_NODE_ADDRESS,
342 .procname = "node_address", 250 .procname = "node_address",
343 .maxlen = 7, 251 .maxlen = 7,
344 .mode = 0644, 252 .mode = 0644,
345 .proc_handler = dn_node_address_handler, 253 .proc_handler = dn_node_address_handler,
346 .strategy = dn_node_address_strategy,
347 }, 254 },
348 { 255 {
349 .ctl_name = NET_DECNET_NODE_NAME,
350 .procname = "node_name", 256 .procname = "node_name",
351 .data = node_name, 257 .data = node_name,
352 .maxlen = 7, 258 .maxlen = 7,
353 .mode = 0644, 259 .mode = 0644,
354 .proc_handler = proc_dostring, 260 .proc_handler = proc_dostring,
355 .strategy = sysctl_string,
356 }, 261 },
357 { 262 {
358 .ctl_name = NET_DECNET_DEFAULT_DEVICE,
359 .procname = "default_device", 263 .procname = "default_device",
360 .maxlen = 16, 264 .maxlen = 16,
361 .mode = 0644, 265 .mode = 0644,
362 .proc_handler = dn_def_dev_handler, 266 .proc_handler = dn_def_dev_handler,
363 .strategy = dn_def_dev_strategy,
364 }, 267 },
365 { 268 {
366 .ctl_name = NET_DECNET_TIME_WAIT,
367 .procname = "time_wait", 269 .procname = "time_wait",
368 .data = &decnet_time_wait, 270 .data = &decnet_time_wait,
369 .maxlen = sizeof(int), 271 .maxlen = sizeof(int),
370 .mode = 0644, 272 .mode = 0644,
371 .proc_handler = proc_dointvec_minmax, 273 .proc_handler = proc_dointvec_minmax,
372 .strategy = sysctl_intvec,
373 .extra1 = &min_decnet_time_wait, 274 .extra1 = &min_decnet_time_wait,
374 .extra2 = &max_decnet_time_wait 275 .extra2 = &max_decnet_time_wait
375 }, 276 },
376 { 277 {
377 .ctl_name = NET_DECNET_DN_COUNT,
378 .procname = "dn_count", 278 .procname = "dn_count",
379 .data = &decnet_dn_count, 279 .data = &decnet_dn_count,
380 .maxlen = sizeof(int), 280 .maxlen = sizeof(int),
381 .mode = 0644, 281 .mode = 0644,
382 .proc_handler = proc_dointvec_minmax, 282 .proc_handler = proc_dointvec_minmax,
383 .strategy = sysctl_intvec,
384 .extra1 = &min_state_count, 283 .extra1 = &min_state_count,
385 .extra2 = &max_state_count 284 .extra2 = &max_state_count
386 }, 285 },
387 { 286 {
388 .ctl_name = NET_DECNET_DI_COUNT,
389 .procname = "di_count", 287 .procname = "di_count",
390 .data = &decnet_di_count, 288 .data = &decnet_di_count,
391 .maxlen = sizeof(int), 289 .maxlen = sizeof(int),
392 .mode = 0644, 290 .mode = 0644,
393 .proc_handler = proc_dointvec_minmax, 291 .proc_handler = proc_dointvec_minmax,
394 .strategy = sysctl_intvec,
395 .extra1 = &min_state_count, 292 .extra1 = &min_state_count,
396 .extra2 = &max_state_count 293 .extra2 = &max_state_count
397 }, 294 },
398 { 295 {
399 .ctl_name = NET_DECNET_DR_COUNT,
400 .procname = "dr_count", 296 .procname = "dr_count",
401 .data = &decnet_dr_count, 297 .data = &decnet_dr_count,
402 .maxlen = sizeof(int), 298 .maxlen = sizeof(int),
403 .mode = 0644, 299 .mode = 0644,
404 .proc_handler = proc_dointvec_minmax, 300 .proc_handler = proc_dointvec_minmax,
405 .strategy = sysctl_intvec,
406 .extra1 = &min_state_count, 301 .extra1 = &min_state_count,
407 .extra2 = &max_state_count 302 .extra2 = &max_state_count
408 }, 303 },
409 { 304 {
410 .ctl_name = NET_DECNET_DST_GC_INTERVAL,
411 .procname = "dst_gc_interval", 305 .procname = "dst_gc_interval",
412 .data = &decnet_dst_gc_interval, 306 .data = &decnet_dst_gc_interval,
413 .maxlen = sizeof(int), 307 .maxlen = sizeof(int),
414 .mode = 0644, 308 .mode = 0644,
415 .proc_handler = proc_dointvec_minmax, 309 .proc_handler = proc_dointvec_minmax,
416 .strategy = sysctl_intvec,
417 .extra1 = &min_decnet_dst_gc_interval, 310 .extra1 = &min_decnet_dst_gc_interval,
418 .extra2 = &max_decnet_dst_gc_interval 311 .extra2 = &max_decnet_dst_gc_interval
419 }, 312 },
420 { 313 {
421 .ctl_name = NET_DECNET_NO_FC_MAX_CWND,
422 .procname = "no_fc_max_cwnd", 314 .procname = "no_fc_max_cwnd",
423 .data = &decnet_no_fc_max_cwnd, 315 .data = &decnet_no_fc_max_cwnd,
424 .maxlen = sizeof(int), 316 .maxlen = sizeof(int),
425 .mode = 0644, 317 .mode = 0644,
426 .proc_handler = proc_dointvec_minmax, 318 .proc_handler = proc_dointvec_minmax,
427 .strategy = sysctl_intvec,
428 .extra1 = &min_decnet_no_fc_max_cwnd, 319 .extra1 = &min_decnet_no_fc_max_cwnd,
429 .extra2 = &max_decnet_no_fc_max_cwnd 320 .extra2 = &max_decnet_no_fc_max_cwnd
430 }, 321 },
431 { 322 {
432 .ctl_name = NET_DECNET_MEM,
433 .procname = "decnet_mem", 323 .procname = "decnet_mem",
434 .data = &sysctl_decnet_mem, 324 .data = &sysctl_decnet_mem,
435 .maxlen = sizeof(sysctl_decnet_mem), 325 .maxlen = sizeof(sysctl_decnet_mem),
436 .mode = 0644, 326 .mode = 0644,
437 .proc_handler = proc_dointvec, 327 .proc_handler = proc_dointvec,
438 .strategy = sysctl_intvec,
439 }, 328 },
440 { 329 {
441 .ctl_name = NET_DECNET_RMEM,
442 .procname = "decnet_rmem", 330 .procname = "decnet_rmem",
443 .data = &sysctl_decnet_rmem, 331 .data = &sysctl_decnet_rmem,
444 .maxlen = sizeof(sysctl_decnet_rmem), 332 .maxlen = sizeof(sysctl_decnet_rmem),
445 .mode = 0644, 333 .mode = 0644,
446 .proc_handler = proc_dointvec, 334 .proc_handler = proc_dointvec,
447 .strategy = sysctl_intvec,
448 }, 335 },
449 { 336 {
450 .ctl_name = NET_DECNET_WMEM,
451 .procname = "decnet_wmem", 337 .procname = "decnet_wmem",
452 .data = &sysctl_decnet_wmem, 338 .data = &sysctl_decnet_wmem,
453 .maxlen = sizeof(sysctl_decnet_wmem), 339 .maxlen = sizeof(sysctl_decnet_wmem),
454 .mode = 0644, 340 .mode = 0644,
455 .proc_handler = proc_dointvec, 341 .proc_handler = proc_dointvec,
456 .strategy = sysctl_intvec,
457 }, 342 },
458 { 343 {
459 .ctl_name = NET_DECNET_DEBUG_LEVEL,
460 .procname = "debug", 344 .procname = "debug",
461 .data = &decnet_debug_level, 345 .data = &decnet_debug_level,
462 .maxlen = sizeof(int), 346 .maxlen = sizeof(int),
463 .mode = 0644, 347 .mode = 0644,
464 .proc_handler = proc_dointvec, 348 .proc_handler = proc_dointvec,
465 .strategy = sysctl_intvec,
466 }, 349 },
467 {0} 350 { }
468}; 351};
469 352
470static struct ctl_path dn_path[] = { 353static struct ctl_path dn_path[] = {
471 { .procname = "net", .ctl_name = CTL_NET, }, 354 { .procname = "net", },
472 { .procname = "decnet", .ctl_name = NET_DECNET, }, 355 { .procname = "decnet", },
473 { } 356 { }
474}; 357};
475 358
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 4e80f336c0cf..c95cd93acf29 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1240,7 +1240,7 @@ void __init arp_init(void)
1240 arp_proc_init(); 1240 arp_proc_init();
1241#ifdef CONFIG_SYSCTL 1241#ifdef CONFIG_SYSCTL
1242 neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, 1242 neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
1243 NET_IPV4_NEIGH, "ipv4", NULL, NULL); 1243 NET_IPV4_NEIGH, "ipv4", NULL);
1244#endif 1244#endif
1245 register_netdevice_notifier(&arp_netdev_notifier); 1245 register_netdevice_notifier(&arp_netdev_notifier);
1246} 1246}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index e3126612fcbb..5cdbc102a418 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1311,58 +1311,6 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
1311 return ret; 1311 return ret;
1312} 1312}
1313 1313
1314static int devinet_conf_sysctl(ctl_table *table,
1315 void __user *oldval, size_t __user *oldlenp,
1316 void __user *newval, size_t newlen)
1317{
1318 struct ipv4_devconf *cnf;
1319 struct net *net;
1320 int *valp = table->data;
1321 int new;
1322 int i;
1323
1324 if (!newval || !newlen)
1325 return 0;
1326
1327 if (newlen != sizeof(int))
1328 return -EINVAL;
1329
1330 if (get_user(new, (int __user *)newval))
1331 return -EFAULT;
1332
1333 if (new == *valp)
1334 return 0;
1335
1336 if (oldval && oldlenp) {
1337 size_t len;
1338
1339 if (get_user(len, oldlenp))
1340 return -EFAULT;
1341
1342 if (len) {
1343 if (len > table->maxlen)
1344 len = table->maxlen;
1345 if (copy_to_user(oldval, valp, len))
1346 return -EFAULT;
1347 if (put_user(len, oldlenp))
1348 return -EFAULT;
1349 }
1350 }
1351
1352 *valp = new;
1353
1354 cnf = table->extra1;
1355 net = table->extra2;
1356 i = (int *)table->data - cnf->data;
1357
1358 set_bit(i, cnf->state);
1359
1360 if (cnf == net->ipv4.devconf_dflt)
1361 devinet_copy_dflt_conf(net, i);
1362
1363 return 1;
1364}
1365
1366static int devinet_sysctl_forward(ctl_table *ctl, int write, 1314static int devinet_sysctl_forward(ctl_table *ctl, int write,
1367 void __user *buffer, 1315 void __user *buffer,
1368 size_t *lenp, loff_t *ppos) 1316 size_t *lenp, loff_t *ppos)
@@ -1408,47 +1356,28 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
1408 return ret; 1356 return ret;
1409} 1357}
1410 1358
1411int ipv4_doint_and_flush_strategy(ctl_table *table, 1359#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc) \
1412 void __user *oldval, size_t __user *oldlenp,
1413 void __user *newval, size_t newlen)
1414{
1415 int ret = devinet_conf_sysctl(table, oldval, oldlenp, newval, newlen);
1416 struct net *net = table->extra2;
1417
1418 if (ret == 1)
1419 rt_cache_flush(net, 0);
1420
1421 return ret;
1422}
1423
1424
1425#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
1426 { \ 1360 { \
1427 .ctl_name = NET_IPV4_CONF_ ## attr, \
1428 .procname = name, \ 1361 .procname = name, \
1429 .data = ipv4_devconf.data + \ 1362 .data = ipv4_devconf.data + \
1430 NET_IPV4_CONF_ ## attr - 1, \ 1363 NET_IPV4_CONF_ ## attr - 1, \
1431 .maxlen = sizeof(int), \ 1364 .maxlen = sizeof(int), \
1432 .mode = mval, \ 1365 .mode = mval, \
1433 .proc_handler = proc, \ 1366 .proc_handler = proc, \
1434 .strategy = sysctl, \
1435 .extra1 = &ipv4_devconf, \ 1367 .extra1 = &ipv4_devconf, \
1436 } 1368 }
1437 1369
1438#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \ 1370#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
1439 DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \ 1371 DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc)
1440 devinet_conf_sysctl)
1441 1372
1442#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \ 1373#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
1443 DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \ 1374 DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc)
1444 devinet_conf_sysctl)
1445 1375
1446#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \ 1376#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc) \
1447 DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl) 1377 DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc)
1448 1378
1449#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \ 1379#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
1450 DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \ 1380 DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush)
1451 ipv4_doint_and_flush_strategy)
1452 1381
1453static struct devinet_sysctl_table { 1382static struct devinet_sysctl_table {
1454 struct ctl_table_header *sysctl_header; 1383 struct ctl_table_header *sysctl_header;
@@ -1457,8 +1386,7 @@ static struct devinet_sysctl_table {
1457} devinet_sysctl = { 1386} devinet_sysctl = {
1458 .devinet_vars = { 1387 .devinet_vars = {
1459 DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding", 1388 DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
1460 devinet_sysctl_forward, 1389 devinet_sysctl_forward),
1461 devinet_conf_sysctl),
1462 DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"), 1390 DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
1463 1391
1464 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"), 1392 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
@@ -1490,7 +1418,7 @@ static struct devinet_sysctl_table {
1490}; 1418};
1491 1419
1492static int __devinet_sysctl_register(struct net *net, char *dev_name, 1420static int __devinet_sysctl_register(struct net *net, char *dev_name,
1493 int ctl_name, struct ipv4_devconf *p) 1421 struct ipv4_devconf *p)
1494{ 1422{
1495 int i; 1423 int i;
1496 struct devinet_sysctl_table *t; 1424 struct devinet_sysctl_table *t;
@@ -1498,9 +1426,9 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
1498#define DEVINET_CTL_PATH_DEV 3 1426#define DEVINET_CTL_PATH_DEV 3
1499 1427
1500 struct ctl_path devinet_ctl_path[] = { 1428 struct ctl_path devinet_ctl_path[] = {
1501 { .procname = "net", .ctl_name = CTL_NET, }, 1429 { .procname = "net", },
1502 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 1430 { .procname = "ipv4", },
1503 { .procname = "conf", .ctl_name = NET_IPV4_CONF, }, 1431 { .procname = "conf", },
1504 { /* to be set */ }, 1432 { /* to be set */ },
1505 { }, 1433 { },
1506 }; 1434 };
@@ -1525,7 +1453,6 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
1525 goto free; 1453 goto free;
1526 1454
1527 devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name; 1455 devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name;
1528 devinet_ctl_path[DEVINET_CTL_PATH_DEV].ctl_name = ctl_name;
1529 1456
1530 t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path, 1457 t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path,
1531 t->devinet_vars); 1458 t->devinet_vars);
@@ -1559,9 +1486,9 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
1559static void devinet_sysctl_register(struct in_device *idev) 1486static void devinet_sysctl_register(struct in_device *idev)
1560{ 1487{
1561 neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4, 1488 neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4,
1562 NET_IPV4_NEIGH, "ipv4", NULL, NULL); 1489 NET_IPV4_NEIGH, "ipv4", NULL);
1563 __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, 1490 __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
1564 idev->dev->ifindex, &idev->cnf); 1491 &idev->cnf);
1565} 1492}
1566 1493
1567static void devinet_sysctl_unregister(struct in_device *idev) 1494static void devinet_sysctl_unregister(struct in_device *idev)
@@ -1572,14 +1499,12 @@ static void devinet_sysctl_unregister(struct in_device *idev)
1572 1499
1573static struct ctl_table ctl_forward_entry[] = { 1500static struct ctl_table ctl_forward_entry[] = {
1574 { 1501 {
1575 .ctl_name = NET_IPV4_FORWARD,
1576 .procname = "ip_forward", 1502 .procname = "ip_forward",
1577 .data = &ipv4_devconf.data[ 1503 .data = &ipv4_devconf.data[
1578 NET_IPV4_CONF_FORWARDING - 1], 1504 NET_IPV4_CONF_FORWARDING - 1],
1579 .maxlen = sizeof(int), 1505 .maxlen = sizeof(int),
1580 .mode = 0644, 1506 .mode = 0644,
1581 .proc_handler = devinet_sysctl_forward, 1507 .proc_handler = devinet_sysctl_forward,
1582 .strategy = devinet_conf_sysctl,
1583 .extra1 = &ipv4_devconf, 1508 .extra1 = &ipv4_devconf,
1584 .extra2 = &init_net, 1509 .extra2 = &init_net,
1585 }, 1510 },
@@ -1587,8 +1512,8 @@ static struct ctl_table ctl_forward_entry[] = {
1587}; 1512};
1588 1513
1589static __net_initdata struct ctl_path net_ipv4_path[] = { 1514static __net_initdata struct ctl_path net_ipv4_path[] = {
1590 { .procname = "net", .ctl_name = CTL_NET, }, 1515 { .procname = "net", },
1591 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 1516 { .procname = "ipv4", },
1592 { }, 1517 { },
1593}; 1518};
1594#endif 1519#endif
@@ -1627,13 +1552,11 @@ static __net_init int devinet_init_net(struct net *net)
1627 } 1552 }
1628 1553
1629#ifdef CONFIG_SYSCTL 1554#ifdef CONFIG_SYSCTL
1630 err = __devinet_sysctl_register(net, "all", 1555 err = __devinet_sysctl_register(net, "all", all);
1631 NET_PROTO_CONF_ALL, all);
1632 if (err < 0) 1556 if (err < 0)
1633 goto err_reg_all; 1557 goto err_reg_all;
1634 1558
1635 err = __devinet_sysctl_register(net, "default", 1559 err = __devinet_sysctl_register(net, "default", dflt);
1636 NET_PROTO_CONF_DEFAULT, dflt);
1637 if (err < 0) 1560 if (err < 0)
1638 goto err_reg_dflt; 1561 goto err_reg_dflt;
1639 1562
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index c4735310a923..86964b353c31 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -604,7 +604,6 @@ static int zero;
604 604
605static struct ctl_table ip4_frags_ns_ctl_table[] = { 605static struct ctl_table ip4_frags_ns_ctl_table[] = {
606 { 606 {
607 .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH,
608 .procname = "ipfrag_high_thresh", 607 .procname = "ipfrag_high_thresh",
609 .data = &init_net.ipv4.frags.high_thresh, 608 .data = &init_net.ipv4.frags.high_thresh,
610 .maxlen = sizeof(int), 609 .maxlen = sizeof(int),
@@ -612,7 +611,6 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
612 .proc_handler = proc_dointvec 611 .proc_handler = proc_dointvec
613 }, 612 },
614 { 613 {
615 .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH,
616 .procname = "ipfrag_low_thresh", 614 .procname = "ipfrag_low_thresh",
617 .data = &init_net.ipv4.frags.low_thresh, 615 .data = &init_net.ipv4.frags.low_thresh,
618 .maxlen = sizeof(int), 616 .maxlen = sizeof(int),
@@ -620,26 +618,22 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
620 .proc_handler = proc_dointvec 618 .proc_handler = proc_dointvec
621 }, 619 },
622 { 620 {
623 .ctl_name = NET_IPV4_IPFRAG_TIME,
624 .procname = "ipfrag_time", 621 .procname = "ipfrag_time",
625 .data = &init_net.ipv4.frags.timeout, 622 .data = &init_net.ipv4.frags.timeout,
626 .maxlen = sizeof(int), 623 .maxlen = sizeof(int),
627 .mode = 0644, 624 .mode = 0644,
628 .proc_handler = proc_dointvec_jiffies, 625 .proc_handler = proc_dointvec_jiffies,
629 .strategy = sysctl_jiffies
630 }, 626 },
631 { } 627 { }
632}; 628};
633 629
634static struct ctl_table ip4_frags_ctl_table[] = { 630static struct ctl_table ip4_frags_ctl_table[] = {
635 { 631 {
636 .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL,
637 .procname = "ipfrag_secret_interval", 632 .procname = "ipfrag_secret_interval",
638 .data = &ip4_frags.secret_interval, 633 .data = &ip4_frags.secret_interval,
639 .maxlen = sizeof(int), 634 .maxlen = sizeof(int),
640 .mode = 0644, 635 .mode = 0644,
641 .proc_handler = proc_dointvec_jiffies, 636 .proc_handler = proc_dointvec_jiffies,
642 .strategy = sysctl_jiffies
643 }, 637 },
644 { 638 {
645 .procname = "ipfrag_max_dist", 639 .procname = "ipfrag_max_dist",
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index f53cb8df4182..c14623fc4d5e 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -248,9 +248,9 @@ module_exit(ipv4_netfilter_fini);
248 248
249#ifdef CONFIG_SYSCTL 249#ifdef CONFIG_SYSCTL
250struct ctl_path nf_net_ipv4_netfilter_sysctl_path[] = { 250struct ctl_path nf_net_ipv4_netfilter_sysctl_path[] = {
251 { .procname = "net", .ctl_name = CTL_NET, }, 251 { .procname = "net", },
252 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 252 { .procname = "ipv4", },
253 { .procname = "netfilter", .ctl_name = NET_IPV4_NETFILTER, }, 253 { .procname = "netfilter", },
254 { } 254 { }
255}; 255};
256EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path); 256EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 49ad44712f46..2855f1f38cbc 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -515,14 +515,13 @@ static struct ctl_table_header *ipq_sysctl_header;
515 515
516static ctl_table ipq_table[] = { 516static ctl_table ipq_table[] = {
517 { 517 {
518 .ctl_name = NET_IPQ_QMAX,
519 .procname = NET_IPQ_QMAX_NAME, 518 .procname = NET_IPQ_QMAX_NAME,
520 .data = &queue_maxlen, 519 .data = &queue_maxlen,
521 .maxlen = sizeof(queue_maxlen), 520 .maxlen = sizeof(queue_maxlen),
522 .mode = 0644, 521 .mode = 0644,
523 .proc_handler = proc_dointvec 522 .proc_handler = proc_dointvec
524 }, 523 },
525 { .ctl_name = 0 } 524 { }
526}; 525};
527#endif 526#endif
528 527
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 9cd423ffafa8..d171b123a656 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -195,7 +195,6 @@ static int log_invalid_proto_max = 255;
195 195
196static ctl_table ip_ct_sysctl_table[] = { 196static ctl_table ip_ct_sysctl_table[] = {
197 { 197 {
198 .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
199 .procname = "ip_conntrack_max", 198 .procname = "ip_conntrack_max",
200 .data = &nf_conntrack_max, 199 .data = &nf_conntrack_max,
201 .maxlen = sizeof(int), 200 .maxlen = sizeof(int),
@@ -203,7 +202,6 @@ static ctl_table ip_ct_sysctl_table[] = {
203 .proc_handler = proc_dointvec, 202 .proc_handler = proc_dointvec,
204 }, 203 },
205 { 204 {
206 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
207 .procname = "ip_conntrack_count", 205 .procname = "ip_conntrack_count",
208 .data = &init_net.ct.count, 206 .data = &init_net.ct.count,
209 .maxlen = sizeof(int), 207 .maxlen = sizeof(int),
@@ -211,7 +209,6 @@ static ctl_table ip_ct_sysctl_table[] = {
211 .proc_handler = proc_dointvec, 209 .proc_handler = proc_dointvec,
212 }, 210 },
213 { 211 {
214 .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
215 .procname = "ip_conntrack_buckets", 212 .procname = "ip_conntrack_buckets",
216 .data = &nf_conntrack_htable_size, 213 .data = &nf_conntrack_htable_size,
217 .maxlen = sizeof(unsigned int), 214 .maxlen = sizeof(unsigned int),
@@ -219,7 +216,6 @@ static ctl_table ip_ct_sysctl_table[] = {
219 .proc_handler = proc_dointvec, 216 .proc_handler = proc_dointvec,
220 }, 217 },
221 { 218 {
222 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM,
223 .procname = "ip_conntrack_checksum", 219 .procname = "ip_conntrack_checksum",
224 .data = &init_net.ct.sysctl_checksum, 220 .data = &init_net.ct.sysctl_checksum,
225 .maxlen = sizeof(int), 221 .maxlen = sizeof(int),
@@ -227,19 +223,15 @@ static ctl_table ip_ct_sysctl_table[] = {
227 .proc_handler = proc_dointvec, 223 .proc_handler = proc_dointvec,
228 }, 224 },
229 { 225 {
230 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
231 .procname = "ip_conntrack_log_invalid", 226 .procname = "ip_conntrack_log_invalid",
232 .data = &init_net.ct.sysctl_log_invalid, 227 .data = &init_net.ct.sysctl_log_invalid,
233 .maxlen = sizeof(unsigned int), 228 .maxlen = sizeof(unsigned int),
234 .mode = 0644, 229 .mode = 0644,
235 .proc_handler = proc_dointvec_minmax, 230 .proc_handler = proc_dointvec_minmax,
236 .strategy = sysctl_intvec,
237 .extra1 = &log_invalid_proto_min, 231 .extra1 = &log_invalid_proto_min,
238 .extra2 = &log_invalid_proto_max, 232 .extra2 = &log_invalid_proto_max,
239 }, 233 },
240 { 234 { }
241 .ctl_name = 0
242 }
243}; 235};
244#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */ 236#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */
245 237
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index e3dd93623df8..7afd39b5b781 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -270,9 +270,7 @@ static struct ctl_table icmp_sysctl_table[] = {
270 .mode = 0644, 270 .mode = 0644,
271 .proc_handler = proc_dointvec_jiffies, 271 .proc_handler = proc_dointvec_jiffies,
272 }, 272 },
273 { 273 { }
274 .ctl_name = 0
275 }
276}; 274};
277#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 275#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
278static struct ctl_table icmp_compat_sysctl_table[] = { 276static struct ctl_table icmp_compat_sysctl_table[] = {
@@ -283,9 +281,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = {
283 .mode = 0644, 281 .mode = 0644,
284 .proc_handler = proc_dointvec_jiffies, 282 .proc_handler = proc_dointvec_jiffies,
285 }, 283 },
286 { 284 { }
287 .ctl_name = 0
288 }
289}; 285};
290#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 286#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
291#endif /* CONFIG_SYSCTL */ 287#endif /* CONFIG_SYSCTL */
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 90cdcfc32937..e446496f564f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3058,23 +3058,6 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
3058 return -EINVAL; 3058 return -EINVAL;
3059} 3059}
3060 3060
3061static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
3062 void __user *oldval,
3063 size_t __user *oldlenp,
3064 void __user *newval,
3065 size_t newlen)
3066{
3067 int delay;
3068 struct net *net;
3069 if (newlen != sizeof(int))
3070 return -EINVAL;
3071 if (get_user(delay, (int __user *)newval))
3072 return -EFAULT;
3073 net = (struct net *)table->extra1;
3074 rt_cache_flush(net, delay);
3075 return 0;
3076}
3077
3078static void rt_secret_reschedule(int old) 3061static void rt_secret_reschedule(int old)
3079{ 3062{
3080 struct net *net; 3063 struct net *net;
@@ -3119,23 +3102,8 @@ static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
3119 return ret; 3102 return ret;
3120} 3103}
3121 3104
3122static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
3123 void __user *oldval,
3124 size_t __user *oldlenp,
3125 void __user *newval,
3126 size_t newlen)
3127{
3128 int old = ip_rt_secret_interval;
3129 int ret = sysctl_jiffies(table, oldval, oldlenp, newval, newlen);
3130
3131 rt_secret_reschedule(old);
3132
3133 return ret;
3134}
3135
3136static ctl_table ipv4_route_table[] = { 3105static ctl_table ipv4_route_table[] = {
3137 { 3106 {
3138 .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
3139 .procname = "gc_thresh", 3107 .procname = "gc_thresh",
3140 .data = &ipv4_dst_ops.gc_thresh, 3108 .data = &ipv4_dst_ops.gc_thresh,
3141 .maxlen = sizeof(int), 3109 .maxlen = sizeof(int),
@@ -3143,7 +3111,6 @@ static ctl_table ipv4_route_table[] = {
3143 .proc_handler = proc_dointvec, 3111 .proc_handler = proc_dointvec,
3144 }, 3112 },
3145 { 3113 {
3146 .ctl_name = NET_IPV4_ROUTE_MAX_SIZE,
3147 .procname = "max_size", 3114 .procname = "max_size",
3148 .data = &ip_rt_max_size, 3115 .data = &ip_rt_max_size,
3149 .maxlen = sizeof(int), 3116 .maxlen = sizeof(int),
@@ -3153,43 +3120,34 @@ static ctl_table ipv4_route_table[] = {
3153 { 3120 {
3154 /* Deprecated. Use gc_min_interval_ms */ 3121 /* Deprecated. Use gc_min_interval_ms */
3155 3122
3156 .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL,
3157 .procname = "gc_min_interval", 3123 .procname = "gc_min_interval",
3158 .data = &ip_rt_gc_min_interval, 3124 .data = &ip_rt_gc_min_interval,
3159 .maxlen = sizeof(int), 3125 .maxlen = sizeof(int),
3160 .mode = 0644, 3126 .mode = 0644,
3161 .proc_handler = proc_dointvec_jiffies, 3127 .proc_handler = proc_dointvec_jiffies,
3162 .strategy = sysctl_jiffies,
3163 }, 3128 },
3164 { 3129 {
3165 .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS,
3166 .procname = "gc_min_interval_ms", 3130 .procname = "gc_min_interval_ms",
3167 .data = &ip_rt_gc_min_interval, 3131 .data = &ip_rt_gc_min_interval,
3168 .maxlen = sizeof(int), 3132 .maxlen = sizeof(int),
3169 .mode = 0644, 3133 .mode = 0644,
3170 .proc_handler = proc_dointvec_ms_jiffies, 3134 .proc_handler = proc_dointvec_ms_jiffies,
3171 .strategy = sysctl_ms_jiffies,
3172 }, 3135 },
3173 { 3136 {
3174 .ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
3175 .procname = "gc_timeout", 3137 .procname = "gc_timeout",
3176 .data = &ip_rt_gc_timeout, 3138 .data = &ip_rt_gc_timeout,
3177 .maxlen = sizeof(int), 3139 .maxlen = sizeof(int),
3178 .mode = 0644, 3140 .mode = 0644,
3179 .proc_handler = proc_dointvec_jiffies, 3141 .proc_handler = proc_dointvec_jiffies,
3180 .strategy = sysctl_jiffies,
3181 }, 3142 },
3182 { 3143 {
3183 .ctl_name = NET_IPV4_ROUTE_GC_INTERVAL,
3184 .procname = "gc_interval", 3144 .procname = "gc_interval",
3185 .data = &ip_rt_gc_interval, 3145 .data = &ip_rt_gc_interval,
3186 .maxlen = sizeof(int), 3146 .maxlen = sizeof(int),
3187 .mode = 0644, 3147 .mode = 0644,
3188 .proc_handler = proc_dointvec_jiffies, 3148 .proc_handler = proc_dointvec_jiffies,
3189 .strategy = sysctl_jiffies,
3190 }, 3149 },
3191 { 3150 {
3192 .ctl_name = NET_IPV4_ROUTE_REDIRECT_LOAD,
3193 .procname = "redirect_load", 3151 .procname = "redirect_load",
3194 .data = &ip_rt_redirect_load, 3152 .data = &ip_rt_redirect_load,
3195 .maxlen = sizeof(int), 3153 .maxlen = sizeof(int),
@@ -3197,7 +3155,6 @@ static ctl_table ipv4_route_table[] = {
3197 .proc_handler = proc_dointvec, 3155 .proc_handler = proc_dointvec,
3198 }, 3156 },
3199 { 3157 {
3200 .ctl_name = NET_IPV4_ROUTE_REDIRECT_NUMBER,
3201 .procname = "redirect_number", 3158 .procname = "redirect_number",
3202 .data = &ip_rt_redirect_number, 3159 .data = &ip_rt_redirect_number,
3203 .maxlen = sizeof(int), 3160 .maxlen = sizeof(int),
@@ -3205,7 +3162,6 @@ static ctl_table ipv4_route_table[] = {
3205 .proc_handler = proc_dointvec, 3162 .proc_handler = proc_dointvec,
3206 }, 3163 },
3207 { 3164 {
3208 .ctl_name = NET_IPV4_ROUTE_REDIRECT_SILENCE,
3209 .procname = "redirect_silence", 3165 .procname = "redirect_silence",
3210 .data = &ip_rt_redirect_silence, 3166 .data = &ip_rt_redirect_silence,
3211 .maxlen = sizeof(int), 3167 .maxlen = sizeof(int),
@@ -3213,7 +3169,6 @@ static ctl_table ipv4_route_table[] = {
3213 .proc_handler = proc_dointvec, 3169 .proc_handler = proc_dointvec,
3214 }, 3170 },
3215 { 3171 {
3216 .ctl_name = NET_IPV4_ROUTE_ERROR_COST,
3217 .procname = "error_cost", 3172 .procname = "error_cost",
3218 .data = &ip_rt_error_cost, 3173 .data = &ip_rt_error_cost,
3219 .maxlen = sizeof(int), 3174 .maxlen = sizeof(int),
@@ -3221,7 +3176,6 @@ static ctl_table ipv4_route_table[] = {
3221 .proc_handler = proc_dointvec, 3176 .proc_handler = proc_dointvec,
3222 }, 3177 },
3223 { 3178 {
3224 .ctl_name = NET_IPV4_ROUTE_ERROR_BURST,
3225 .procname = "error_burst", 3179 .procname = "error_burst",
3226 .data = &ip_rt_error_burst, 3180 .data = &ip_rt_error_burst,
3227 .maxlen = sizeof(int), 3181 .maxlen = sizeof(int),
@@ -3229,7 +3183,6 @@ static ctl_table ipv4_route_table[] = {
3229 .proc_handler = proc_dointvec, 3183 .proc_handler = proc_dointvec,
3230 }, 3184 },
3231 { 3185 {
3232 .ctl_name = NET_IPV4_ROUTE_GC_ELASTICITY,
3233 .procname = "gc_elasticity", 3186 .procname = "gc_elasticity",
3234 .data = &ip_rt_gc_elasticity, 3187 .data = &ip_rt_gc_elasticity,
3235 .maxlen = sizeof(int), 3188 .maxlen = sizeof(int),
@@ -3237,16 +3190,13 @@ static ctl_table ipv4_route_table[] = {
3237 .proc_handler = proc_dointvec, 3190 .proc_handler = proc_dointvec,
3238 }, 3191 },
3239 { 3192 {
3240 .ctl_name = NET_IPV4_ROUTE_MTU_EXPIRES,
3241 .procname = "mtu_expires", 3193 .procname = "mtu_expires",
3242 .data = &ip_rt_mtu_expires, 3194 .data = &ip_rt_mtu_expires,
3243 .maxlen = sizeof(int), 3195 .maxlen = sizeof(int),
3244 .mode = 0644, 3196 .mode = 0644,
3245 .proc_handler = proc_dointvec_jiffies, 3197 .proc_handler = proc_dointvec_jiffies,
3246 .strategy = sysctl_jiffies,
3247 }, 3198 },
3248 { 3199 {
3249 .ctl_name = NET_IPV4_ROUTE_MIN_PMTU,
3250 .procname = "min_pmtu", 3200 .procname = "min_pmtu",
3251 .data = &ip_rt_min_pmtu, 3201 .data = &ip_rt_min_pmtu,
3252 .maxlen = sizeof(int), 3202 .maxlen = sizeof(int),
@@ -3254,7 +3204,6 @@ static ctl_table ipv4_route_table[] = {
3254 .proc_handler = proc_dointvec, 3204 .proc_handler = proc_dointvec,
3255 }, 3205 },
3256 { 3206 {
3257 .ctl_name = NET_IPV4_ROUTE_MIN_ADVMSS,
3258 .procname = "min_adv_mss", 3207 .procname = "min_adv_mss",
3259 .data = &ip_rt_min_advmss, 3208 .data = &ip_rt_min_advmss,
3260 .maxlen = sizeof(int), 3209 .maxlen = sizeof(int),
@@ -3262,50 +3211,46 @@ static ctl_table ipv4_route_table[] = {
3262 .proc_handler = proc_dointvec, 3211 .proc_handler = proc_dointvec,
3263 }, 3212 },
3264 { 3213 {
3265 .ctl_name = NET_IPV4_ROUTE_SECRET_INTERVAL,
3266 .procname = "secret_interval", 3214 .procname = "secret_interval",
3267 .data = &ip_rt_secret_interval, 3215 .data = &ip_rt_secret_interval,
3268 .maxlen = sizeof(int), 3216 .maxlen = sizeof(int),
3269 .mode = 0644, 3217 .mode = 0644,
3270 .proc_handler = ipv4_sysctl_rt_secret_interval, 3218 .proc_handler = ipv4_sysctl_rt_secret_interval,
3271 .strategy = ipv4_sysctl_rt_secret_interval_strategy,
3272 }, 3219 },
3273 { .ctl_name = 0 } 3220 { }
3274}; 3221};
3275 3222
3276static struct ctl_table empty[1]; 3223static struct ctl_table empty[1];
3277 3224
3278static struct ctl_table ipv4_skeleton[] = 3225static struct ctl_table ipv4_skeleton[] =
3279{ 3226{
3280 { .procname = "route", .ctl_name = NET_IPV4_ROUTE, 3227 { .procname = "route",
3281 .mode = 0555, .child = ipv4_route_table}, 3228 .mode = 0555, .child = ipv4_route_table},
3282 { .procname = "neigh", .ctl_name = NET_IPV4_NEIGH, 3229 { .procname = "neigh",
3283 .mode = 0555, .child = empty}, 3230 .mode = 0555, .child = empty},
3284 { } 3231 { }
3285}; 3232};
3286 3233
3287static __net_initdata struct ctl_path ipv4_path[] = { 3234static __net_initdata struct ctl_path ipv4_path[] = {
3288 { .procname = "net", .ctl_name = CTL_NET, }, 3235 { .procname = "net", },
3289 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 3236 { .procname = "ipv4", },
3290 { }, 3237 { },
3291}; 3238};
3292 3239
3293static struct ctl_table ipv4_route_flush_table[] = { 3240static struct ctl_table ipv4_route_flush_table[] = {
3294 { 3241 {
3295 .ctl_name = NET_IPV4_ROUTE_FLUSH,
3296 .procname = "flush", 3242 .procname = "flush",
3297 .maxlen = sizeof(int), 3243 .maxlen = sizeof(int),
3298 .mode = 0200, 3244 .mode = 0200,
3299 .proc_handler = ipv4_sysctl_rtcache_flush, 3245 .proc_handler = ipv4_sysctl_rtcache_flush,
3300 .strategy = ipv4_sysctl_rtcache_flush_strategy,
3301 }, 3246 },
3302 { .ctl_name = 0 }, 3247 { },
3303}; 3248};
3304 3249
3305static __net_initdata struct ctl_path ipv4_route_path[] = { 3250static __net_initdata struct ctl_path ipv4_route_path[] = {
3306 { .procname = "net", .ctl_name = CTL_NET, }, 3251 { .procname = "net", },
3307 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 3252 { .procname = "ipv4", },
3308 { .procname = "route", .ctl_name = NET_IPV4_ROUTE, }, 3253 { .procname = "route", },
3309 { }, 3254 { },
3310}; 3255};
3311 3256
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 13f7ab6ad6a0..7e3712ce3994 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -63,34 +63,6 @@ static int ipv4_local_port_range(ctl_table *table, int write,
63 return ret; 63 return ret;
64} 64}
65 65
66/* Validate changes from sysctl interface. */
67static int ipv4_sysctl_local_port_range(ctl_table *table,
68 void __user *oldval,
69 size_t __user *oldlenp,
70 void __user *newval, size_t newlen)
71{
72 int ret;
73 int range[2];
74 ctl_table tmp = {
75 .data = &range,
76 .maxlen = sizeof(range),
77 .mode = table->mode,
78 .extra1 = &ip_local_port_range_min,
79 .extra2 = &ip_local_port_range_max,
80 };
81
82 inet_get_local_port_range(range, range + 1);
83 ret = sysctl_intvec(&tmp, oldval, oldlenp, newval, newlen);
84 if (ret == 0 && newval && newlen) {
85 if (range[1] < range[0])
86 ret = -EINVAL;
87 else
88 set_local_port_range(range);
89 }
90 return ret;
91}
92
93
94static int proc_tcp_congestion_control(ctl_table *ctl, int write, 66static int proc_tcp_congestion_control(ctl_table *ctl, int write,
95 void __user *buffer, size_t *lenp, loff_t *ppos) 67 void __user *buffer, size_t *lenp, loff_t *ppos)
96{ 68{
@@ -109,25 +81,6 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write,
109 return ret; 81 return ret;
110} 82}
111 83
112static int sysctl_tcp_congestion_control(ctl_table *table,
113 void __user *oldval,
114 size_t __user *oldlenp,
115 void __user *newval, size_t newlen)
116{
117 char val[TCP_CA_NAME_MAX];
118 ctl_table tbl = {
119 .data = val,
120 .maxlen = TCP_CA_NAME_MAX,
121 };
122 int ret;
123
124 tcp_get_default_congestion_control(val);
125 ret = sysctl_string(&tbl, oldval, oldlenp, newval, newlen);
126 if (ret == 1 && newval && newlen)
127 ret = tcp_set_default_congestion_control(val);
128 return ret;
129}
130
131static int proc_tcp_available_congestion_control(ctl_table *ctl, 84static int proc_tcp_available_congestion_control(ctl_table *ctl,
132 int write, 85 int write,
133 void __user *buffer, size_t *lenp, 86 void __user *buffer, size_t *lenp,
@@ -165,32 +118,8 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
165 return ret; 118 return ret;
166} 119}
167 120
168static int strategy_allowed_congestion_control(ctl_table *table,
169 void __user *oldval,
170 size_t __user *oldlenp,
171 void __user *newval,
172 size_t newlen)
173{
174 ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
175 int ret;
176
177 tbl.data = kmalloc(tbl.maxlen, GFP_USER);
178 if (!tbl.data)
179 return -ENOMEM;
180
181 tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
182 ret = sysctl_string(&tbl, oldval, oldlenp, newval, newlen);
183 if (ret == 1 && newval && newlen)
184 ret = tcp_set_allowed_congestion_control(tbl.data);
185 kfree(tbl.data);
186
187 return ret;
188
189}
190
191static struct ctl_table ipv4_table[] = { 121static struct ctl_table ipv4_table[] = {
192 { 122 {
193 .ctl_name = NET_IPV4_TCP_TIMESTAMPS,
194 .procname = "tcp_timestamps", 123 .procname = "tcp_timestamps",
195 .data = &sysctl_tcp_timestamps, 124 .data = &sysctl_tcp_timestamps,
196 .maxlen = sizeof(int), 125 .maxlen = sizeof(int),
@@ -198,7 +127,6 @@ static struct ctl_table ipv4_table[] = {
198 .proc_handler = proc_dointvec 127 .proc_handler = proc_dointvec
199 }, 128 },
200 { 129 {
201 .ctl_name = NET_IPV4_TCP_WINDOW_SCALING,
202 .procname = "tcp_window_scaling", 130 .procname = "tcp_window_scaling",
203 .data = &sysctl_tcp_window_scaling, 131 .data = &sysctl_tcp_window_scaling,
204 .maxlen = sizeof(int), 132 .maxlen = sizeof(int),
@@ -206,7 +134,6 @@ static struct ctl_table ipv4_table[] = {
206 .proc_handler = proc_dointvec 134 .proc_handler = proc_dointvec
207 }, 135 },
208 { 136 {
209 .ctl_name = NET_IPV4_TCP_SACK,
210 .procname = "tcp_sack", 137 .procname = "tcp_sack",
211 .data = &sysctl_tcp_sack, 138 .data = &sysctl_tcp_sack,
212 .maxlen = sizeof(int), 139 .maxlen = sizeof(int),
@@ -214,7 +141,6 @@ static struct ctl_table ipv4_table[] = {
214 .proc_handler = proc_dointvec 141 .proc_handler = proc_dointvec
215 }, 142 },
216 { 143 {
217 .ctl_name = NET_IPV4_TCP_RETRANS_COLLAPSE,
218 .procname = "tcp_retrans_collapse", 144 .procname = "tcp_retrans_collapse",
219 .data = &sysctl_tcp_retrans_collapse, 145 .data = &sysctl_tcp_retrans_collapse,
220 .maxlen = sizeof(int), 146 .maxlen = sizeof(int),
@@ -222,17 +148,14 @@ static struct ctl_table ipv4_table[] = {
222 .proc_handler = proc_dointvec 148 .proc_handler = proc_dointvec
223 }, 149 },
224 { 150 {
225 .ctl_name = NET_IPV4_DEFAULT_TTL,
226 .procname = "ip_default_ttl", 151 .procname = "ip_default_ttl",
227 .data = &sysctl_ip_default_ttl, 152 .data = &sysctl_ip_default_ttl,
228 .maxlen = sizeof(int), 153 .maxlen = sizeof(int),
229 .mode = 0644, 154 .mode = 0644,
230 .proc_handler = ipv4_doint_and_flush, 155 .proc_handler = ipv4_doint_and_flush,
231 .strategy = ipv4_doint_and_flush_strategy,
232 .extra2 = &init_net, 156 .extra2 = &init_net,
233 }, 157 },
234 { 158 {
235 .ctl_name = NET_IPV4_NO_PMTU_DISC,
236 .procname = "ip_no_pmtu_disc", 159 .procname = "ip_no_pmtu_disc",
237 .data = &ipv4_config.no_pmtu_disc, 160 .data = &ipv4_config.no_pmtu_disc,
238 .maxlen = sizeof(int), 161 .maxlen = sizeof(int),
@@ -240,7 +163,6 @@ static struct ctl_table ipv4_table[] = {
240 .proc_handler = proc_dointvec 163 .proc_handler = proc_dointvec
241 }, 164 },
242 { 165 {
243 .ctl_name = NET_IPV4_NONLOCAL_BIND,
244 .procname = "ip_nonlocal_bind", 166 .procname = "ip_nonlocal_bind",
245 .data = &sysctl_ip_nonlocal_bind, 167 .data = &sysctl_ip_nonlocal_bind,
246 .maxlen = sizeof(int), 168 .maxlen = sizeof(int),
@@ -248,7 +170,6 @@ static struct ctl_table ipv4_table[] = {
248 .proc_handler = proc_dointvec 170 .proc_handler = proc_dointvec
249 }, 171 },
250 { 172 {
251 .ctl_name = NET_IPV4_TCP_SYN_RETRIES,
252 .procname = "tcp_syn_retries", 173 .procname = "tcp_syn_retries",
253 .data = &sysctl_tcp_syn_retries, 174 .data = &sysctl_tcp_syn_retries,
254 .maxlen = sizeof(int), 175 .maxlen = sizeof(int),
@@ -256,7 +177,6 @@ static struct ctl_table ipv4_table[] = {
256 .proc_handler = proc_dointvec 177 .proc_handler = proc_dointvec
257 }, 178 },
258 { 179 {
259 .ctl_name = NET_TCP_SYNACK_RETRIES,
260 .procname = "tcp_synack_retries", 180 .procname = "tcp_synack_retries",
261 .data = &sysctl_tcp_synack_retries, 181 .data = &sysctl_tcp_synack_retries,
262 .maxlen = sizeof(int), 182 .maxlen = sizeof(int),
@@ -264,7 +184,6 @@ static struct ctl_table ipv4_table[] = {
264 .proc_handler = proc_dointvec 184 .proc_handler = proc_dointvec
265 }, 185 },
266 { 186 {
267 .ctl_name = NET_TCP_MAX_ORPHANS,
268 .procname = "tcp_max_orphans", 187 .procname = "tcp_max_orphans",
269 .data = &sysctl_tcp_max_orphans, 188 .data = &sysctl_tcp_max_orphans,
270 .maxlen = sizeof(int), 189 .maxlen = sizeof(int),
@@ -272,7 +191,6 @@ static struct ctl_table ipv4_table[] = {
272 .proc_handler = proc_dointvec 191 .proc_handler = proc_dointvec
273 }, 192 },
274 { 193 {
275 .ctl_name = NET_TCP_MAX_TW_BUCKETS,
276 .procname = "tcp_max_tw_buckets", 194 .procname = "tcp_max_tw_buckets",
277 .data = &tcp_death_row.sysctl_max_tw_buckets, 195 .data = &tcp_death_row.sysctl_max_tw_buckets,
278 .maxlen = sizeof(int), 196 .maxlen = sizeof(int),
@@ -280,7 +198,6 @@ static struct ctl_table ipv4_table[] = {
280 .proc_handler = proc_dointvec 198 .proc_handler = proc_dointvec
281 }, 199 },
282 { 200 {
283 .ctl_name = NET_IPV4_DYNADDR,
284 .procname = "ip_dynaddr", 201 .procname = "ip_dynaddr",
285 .data = &sysctl_ip_dynaddr, 202 .data = &sysctl_ip_dynaddr,
286 .maxlen = sizeof(int), 203 .maxlen = sizeof(int),
@@ -288,16 +205,13 @@ static struct ctl_table ipv4_table[] = {
288 .proc_handler = proc_dointvec 205 .proc_handler = proc_dointvec
289 }, 206 },
290 { 207 {
291 .ctl_name = NET_IPV4_TCP_KEEPALIVE_TIME,
292 .procname = "tcp_keepalive_time", 208 .procname = "tcp_keepalive_time",
293 .data = &sysctl_tcp_keepalive_time, 209 .data = &sysctl_tcp_keepalive_time,
294 .maxlen = sizeof(int), 210 .maxlen = sizeof(int),
295 .mode = 0644, 211 .mode = 0644,
296 .proc_handler = proc_dointvec_jiffies, 212 .proc_handler = proc_dointvec_jiffies,
297 .strategy = sysctl_jiffies
298 }, 213 },
299 { 214 {
300 .ctl_name = NET_IPV4_TCP_KEEPALIVE_PROBES,
301 .procname = "tcp_keepalive_probes", 215 .procname = "tcp_keepalive_probes",
302 .data = &sysctl_tcp_keepalive_probes, 216 .data = &sysctl_tcp_keepalive_probes,
303 .maxlen = sizeof(int), 217 .maxlen = sizeof(int),
@@ -305,26 +219,21 @@ static struct ctl_table ipv4_table[] = {
305 .proc_handler = proc_dointvec 219 .proc_handler = proc_dointvec
306 }, 220 },
307 { 221 {
308 .ctl_name = NET_IPV4_TCP_KEEPALIVE_INTVL,
309 .procname = "tcp_keepalive_intvl", 222 .procname = "tcp_keepalive_intvl",
310 .data = &sysctl_tcp_keepalive_intvl, 223 .data = &sysctl_tcp_keepalive_intvl,
311 .maxlen = sizeof(int), 224 .maxlen = sizeof(int),
312 .mode = 0644, 225 .mode = 0644,
313 .proc_handler = proc_dointvec_jiffies, 226 .proc_handler = proc_dointvec_jiffies,
314 .strategy = sysctl_jiffies
315 }, 227 },
316 { 228 {
317 .ctl_name = NET_IPV4_TCP_RETRIES1,
318 .procname = "tcp_retries1", 229 .procname = "tcp_retries1",
319 .data = &sysctl_tcp_retries1, 230 .data = &sysctl_tcp_retries1,
320 .maxlen = sizeof(int), 231 .maxlen = sizeof(int),
321 .mode = 0644, 232 .mode = 0644,
322 .proc_handler = proc_dointvec_minmax, 233 .proc_handler = proc_dointvec_minmax,
323 .strategy = sysctl_intvec,
324 .extra2 = &tcp_retr1_max 234 .extra2 = &tcp_retr1_max
325 }, 235 },
326 { 236 {
327 .ctl_name = NET_IPV4_TCP_RETRIES2,
328 .procname = "tcp_retries2", 237 .procname = "tcp_retries2",
329 .data = &sysctl_tcp_retries2, 238 .data = &sysctl_tcp_retries2,
330 .maxlen = sizeof(int), 239 .maxlen = sizeof(int),
@@ -332,17 +241,14 @@ static struct ctl_table ipv4_table[] = {
332 .proc_handler = proc_dointvec 241 .proc_handler = proc_dointvec
333 }, 242 },
334 { 243 {
335 .ctl_name = NET_IPV4_TCP_FIN_TIMEOUT,
336 .procname = "tcp_fin_timeout", 244 .procname = "tcp_fin_timeout",
337 .data = &sysctl_tcp_fin_timeout, 245 .data = &sysctl_tcp_fin_timeout,
338 .maxlen = sizeof(int), 246 .maxlen = sizeof(int),
339 .mode = 0644, 247 .mode = 0644,
340 .proc_handler = proc_dointvec_jiffies, 248 .proc_handler = proc_dointvec_jiffies,
341 .strategy = sysctl_jiffies
342 }, 249 },
343#ifdef CONFIG_SYN_COOKIES 250#ifdef CONFIG_SYN_COOKIES
344 { 251 {
345 .ctl_name = NET_TCP_SYNCOOKIES,
346 .procname = "tcp_syncookies", 252 .procname = "tcp_syncookies",
347 .data = &sysctl_tcp_syncookies, 253 .data = &sysctl_tcp_syncookies,
348 .maxlen = sizeof(int), 254 .maxlen = sizeof(int),
@@ -351,7 +257,6 @@ static struct ctl_table ipv4_table[] = {
351 }, 257 },
352#endif 258#endif
353 { 259 {
354 .ctl_name = NET_TCP_TW_RECYCLE,
355 .procname = "tcp_tw_recycle", 260 .procname = "tcp_tw_recycle",
356 .data = &tcp_death_row.sysctl_tw_recycle, 261 .data = &tcp_death_row.sysctl_tw_recycle,
357 .maxlen = sizeof(int), 262 .maxlen = sizeof(int),
@@ -359,7 +264,6 @@ static struct ctl_table ipv4_table[] = {
359 .proc_handler = proc_dointvec 264 .proc_handler = proc_dointvec
360 }, 265 },
361 { 266 {
362 .ctl_name = NET_TCP_ABORT_ON_OVERFLOW,
363 .procname = "tcp_abort_on_overflow", 267 .procname = "tcp_abort_on_overflow",
364 .data = &sysctl_tcp_abort_on_overflow, 268 .data = &sysctl_tcp_abort_on_overflow,
365 .maxlen = sizeof(int), 269 .maxlen = sizeof(int),
@@ -367,7 +271,6 @@ static struct ctl_table ipv4_table[] = {
367 .proc_handler = proc_dointvec 271 .proc_handler = proc_dointvec
368 }, 272 },
369 { 273 {
370 .ctl_name = NET_TCP_STDURG,
371 .procname = "tcp_stdurg", 274 .procname = "tcp_stdurg",
372 .data = &sysctl_tcp_stdurg, 275 .data = &sysctl_tcp_stdurg,
373 .maxlen = sizeof(int), 276 .maxlen = sizeof(int),
@@ -375,7 +278,6 @@ static struct ctl_table ipv4_table[] = {
375 .proc_handler = proc_dointvec 278 .proc_handler = proc_dointvec
376 }, 279 },
377 { 280 {
378 .ctl_name = NET_TCP_RFC1337,
379 .procname = "tcp_rfc1337", 281 .procname = "tcp_rfc1337",
380 .data = &sysctl_tcp_rfc1337, 282 .data = &sysctl_tcp_rfc1337,
381 .maxlen = sizeof(int), 283 .maxlen = sizeof(int),
@@ -383,7 +285,6 @@ static struct ctl_table ipv4_table[] = {
383 .proc_handler = proc_dointvec 285 .proc_handler = proc_dointvec
384 }, 286 },
385 { 287 {
386 .ctl_name = NET_TCP_MAX_SYN_BACKLOG,
387 .procname = "tcp_max_syn_backlog", 288 .procname = "tcp_max_syn_backlog",
388 .data = &sysctl_max_syn_backlog, 289 .data = &sysctl_max_syn_backlog,
389 .maxlen = sizeof(int), 290 .maxlen = sizeof(int),
@@ -391,17 +292,14 @@ static struct ctl_table ipv4_table[] = {
391 .proc_handler = proc_dointvec 292 .proc_handler = proc_dointvec
392 }, 293 },
393 { 294 {
394 .ctl_name = NET_IPV4_LOCAL_PORT_RANGE,
395 .procname = "ip_local_port_range", 295 .procname = "ip_local_port_range",
396 .data = &sysctl_local_ports.range, 296 .data = &sysctl_local_ports.range,
397 .maxlen = sizeof(sysctl_local_ports.range), 297 .maxlen = sizeof(sysctl_local_ports.range),
398 .mode = 0644, 298 .mode = 0644,
399 .proc_handler = ipv4_local_port_range, 299 .proc_handler = ipv4_local_port_range,
400 .strategy = ipv4_sysctl_local_port_range,
401 }, 300 },
402#ifdef CONFIG_IP_MULTICAST 301#ifdef CONFIG_IP_MULTICAST
403 { 302 {
404 .ctl_name = NET_IPV4_IGMP_MAX_MEMBERSHIPS,
405 .procname = "igmp_max_memberships", 303 .procname = "igmp_max_memberships",
406 .data = &sysctl_igmp_max_memberships, 304 .data = &sysctl_igmp_max_memberships,
407 .maxlen = sizeof(int), 305 .maxlen = sizeof(int),
@@ -411,7 +309,6 @@ static struct ctl_table ipv4_table[] = {
411 309
412#endif 310#endif
413 { 311 {
414 .ctl_name = NET_IPV4_IGMP_MAX_MSF,
415 .procname = "igmp_max_msf", 312 .procname = "igmp_max_msf",
416 .data = &sysctl_igmp_max_msf, 313 .data = &sysctl_igmp_max_msf,
417 .maxlen = sizeof(int), 314 .maxlen = sizeof(int),
@@ -419,7 +316,6 @@ static struct ctl_table ipv4_table[] = {
419 .proc_handler = proc_dointvec 316 .proc_handler = proc_dointvec
420 }, 317 },
421 { 318 {
422 .ctl_name = NET_IPV4_INET_PEER_THRESHOLD,
423 .procname = "inet_peer_threshold", 319 .procname = "inet_peer_threshold",
424 .data = &inet_peer_threshold, 320 .data = &inet_peer_threshold,
425 .maxlen = sizeof(int), 321 .maxlen = sizeof(int),
@@ -427,43 +323,34 @@ static struct ctl_table ipv4_table[] = {
427 .proc_handler = proc_dointvec 323 .proc_handler = proc_dointvec
428 }, 324 },
429 { 325 {
430 .ctl_name = NET_IPV4_INET_PEER_MINTTL,
431 .procname = "inet_peer_minttl", 326 .procname = "inet_peer_minttl",
432 .data = &inet_peer_minttl, 327 .data = &inet_peer_minttl,
433 .maxlen = sizeof(int), 328 .maxlen = sizeof(int),
434 .mode = 0644, 329 .mode = 0644,
435 .proc_handler = proc_dointvec_jiffies, 330 .proc_handler = proc_dointvec_jiffies,
436 .strategy = sysctl_jiffies
437 }, 331 },
438 { 332 {
439 .ctl_name = NET_IPV4_INET_PEER_MAXTTL,
440 .procname = "inet_peer_maxttl", 333 .procname = "inet_peer_maxttl",
441 .data = &inet_peer_maxttl, 334 .data = &inet_peer_maxttl,
442 .maxlen = sizeof(int), 335 .maxlen = sizeof(int),
443 .mode = 0644, 336 .mode = 0644,
444 .proc_handler = proc_dointvec_jiffies, 337 .proc_handler = proc_dointvec_jiffies,
445 .strategy = sysctl_jiffies
446 }, 338 },
447 { 339 {
448 .ctl_name = NET_IPV4_INET_PEER_GC_MINTIME,
449 .procname = "inet_peer_gc_mintime", 340 .procname = "inet_peer_gc_mintime",
450 .data = &inet_peer_gc_mintime, 341 .data = &inet_peer_gc_mintime,
451 .maxlen = sizeof(int), 342 .maxlen = sizeof(int),
452 .mode = 0644, 343 .mode = 0644,
453 .proc_handler = proc_dointvec_jiffies, 344 .proc_handler = proc_dointvec_jiffies,
454 .strategy = sysctl_jiffies
455 }, 345 },
456 { 346 {
457 .ctl_name = NET_IPV4_INET_PEER_GC_MAXTIME,
458 .procname = "inet_peer_gc_maxtime", 347 .procname = "inet_peer_gc_maxtime",
459 .data = &inet_peer_gc_maxtime, 348 .data = &inet_peer_gc_maxtime,
460 .maxlen = sizeof(int), 349 .maxlen = sizeof(int),
461 .mode = 0644, 350 .mode = 0644,
462 .proc_handler = proc_dointvec_jiffies, 351 .proc_handler = proc_dointvec_jiffies,
463 .strategy = sysctl_jiffies
464 }, 352 },
465 { 353 {
466 .ctl_name = NET_TCP_ORPHAN_RETRIES,
467 .procname = "tcp_orphan_retries", 354 .procname = "tcp_orphan_retries",
468 .data = &sysctl_tcp_orphan_retries, 355 .data = &sysctl_tcp_orphan_retries,
469 .maxlen = sizeof(int), 356 .maxlen = sizeof(int),
@@ -471,7 +358,6 @@ static struct ctl_table ipv4_table[] = {
471 .proc_handler = proc_dointvec 358 .proc_handler = proc_dointvec
472 }, 359 },
473 { 360 {
474 .ctl_name = NET_TCP_FACK,
475 .procname = "tcp_fack", 361 .procname = "tcp_fack",
476 .data = &sysctl_tcp_fack, 362 .data = &sysctl_tcp_fack,
477 .maxlen = sizeof(int), 363 .maxlen = sizeof(int),
@@ -479,7 +365,6 @@ static struct ctl_table ipv4_table[] = {
479 .proc_handler = proc_dointvec 365 .proc_handler = proc_dointvec
480 }, 366 },
481 { 367 {
482 .ctl_name = NET_TCP_REORDERING,
483 .procname = "tcp_reordering", 368 .procname = "tcp_reordering",
484 .data = &sysctl_tcp_reordering, 369 .data = &sysctl_tcp_reordering,
485 .maxlen = sizeof(int), 370 .maxlen = sizeof(int),
@@ -487,7 +372,6 @@ static struct ctl_table ipv4_table[] = {
487 .proc_handler = proc_dointvec 372 .proc_handler = proc_dointvec
488 }, 373 },
489 { 374 {
490 .ctl_name = NET_TCP_ECN,
491 .procname = "tcp_ecn", 375 .procname = "tcp_ecn",
492 .data = &sysctl_tcp_ecn, 376 .data = &sysctl_tcp_ecn,
493 .maxlen = sizeof(int), 377 .maxlen = sizeof(int),
@@ -495,7 +379,6 @@ static struct ctl_table ipv4_table[] = {
495 .proc_handler = proc_dointvec 379 .proc_handler = proc_dointvec
496 }, 380 },
497 { 381 {
498 .ctl_name = NET_TCP_DSACK,
499 .procname = "tcp_dsack", 382 .procname = "tcp_dsack",
500 .data = &sysctl_tcp_dsack, 383 .data = &sysctl_tcp_dsack,
501 .maxlen = sizeof(int), 384 .maxlen = sizeof(int),
@@ -503,7 +386,6 @@ static struct ctl_table ipv4_table[] = {
503 .proc_handler = proc_dointvec 386 .proc_handler = proc_dointvec
504 }, 387 },
505 { 388 {
506 .ctl_name = NET_TCP_MEM,
507 .procname = "tcp_mem", 389 .procname = "tcp_mem",
508 .data = &sysctl_tcp_mem, 390 .data = &sysctl_tcp_mem,
509 .maxlen = sizeof(sysctl_tcp_mem), 391 .maxlen = sizeof(sysctl_tcp_mem),
@@ -511,7 +393,6 @@ static struct ctl_table ipv4_table[] = {
511 .proc_handler = proc_dointvec 393 .proc_handler = proc_dointvec
512 }, 394 },
513 { 395 {
514 .ctl_name = NET_TCP_WMEM,
515 .procname = "tcp_wmem", 396 .procname = "tcp_wmem",
516 .data = &sysctl_tcp_wmem, 397 .data = &sysctl_tcp_wmem,
517 .maxlen = sizeof(sysctl_tcp_wmem), 398 .maxlen = sizeof(sysctl_tcp_wmem),
@@ -519,7 +400,6 @@ static struct ctl_table ipv4_table[] = {
519 .proc_handler = proc_dointvec 400 .proc_handler = proc_dointvec
520 }, 401 },
521 { 402 {
522 .ctl_name = NET_TCP_RMEM,
523 .procname = "tcp_rmem", 403 .procname = "tcp_rmem",
524 .data = &sysctl_tcp_rmem, 404 .data = &sysctl_tcp_rmem,
525 .maxlen = sizeof(sysctl_tcp_rmem), 405 .maxlen = sizeof(sysctl_tcp_rmem),
@@ -527,7 +407,6 @@ static struct ctl_table ipv4_table[] = {
527 .proc_handler = proc_dointvec 407 .proc_handler = proc_dointvec
528 }, 408 },
529 { 409 {
530 .ctl_name = NET_TCP_APP_WIN,
531 .procname = "tcp_app_win", 410 .procname = "tcp_app_win",
532 .data = &sysctl_tcp_app_win, 411 .data = &sysctl_tcp_app_win,
533 .maxlen = sizeof(int), 412 .maxlen = sizeof(int),
@@ -535,7 +414,6 @@ static struct ctl_table ipv4_table[] = {
535 .proc_handler = proc_dointvec 414 .proc_handler = proc_dointvec
536 }, 415 },
537 { 416 {
538 .ctl_name = NET_TCP_ADV_WIN_SCALE,
539 .procname = "tcp_adv_win_scale", 417 .procname = "tcp_adv_win_scale",
540 .data = &sysctl_tcp_adv_win_scale, 418 .data = &sysctl_tcp_adv_win_scale,
541 .maxlen = sizeof(int), 419 .maxlen = sizeof(int),
@@ -543,7 +421,6 @@ static struct ctl_table ipv4_table[] = {
543 .proc_handler = proc_dointvec 421 .proc_handler = proc_dointvec
544 }, 422 },
545 { 423 {
546 .ctl_name = NET_TCP_TW_REUSE,
547 .procname = "tcp_tw_reuse", 424 .procname = "tcp_tw_reuse",
548 .data = &sysctl_tcp_tw_reuse, 425 .data = &sysctl_tcp_tw_reuse,
549 .maxlen = sizeof(int), 426 .maxlen = sizeof(int),
@@ -551,7 +428,6 @@ static struct ctl_table ipv4_table[] = {
551 .proc_handler = proc_dointvec 428 .proc_handler = proc_dointvec
552 }, 429 },
553 { 430 {
554 .ctl_name = NET_TCP_FRTO,
555 .procname = "tcp_frto", 431 .procname = "tcp_frto",
556 .data = &sysctl_tcp_frto, 432 .data = &sysctl_tcp_frto,
557 .maxlen = sizeof(int), 433 .maxlen = sizeof(int),
@@ -559,7 +435,6 @@ static struct ctl_table ipv4_table[] = {
559 .proc_handler = proc_dointvec 435 .proc_handler = proc_dointvec
560 }, 436 },
561 { 437 {
562 .ctl_name = NET_TCP_FRTO_RESPONSE,
563 .procname = "tcp_frto_response", 438 .procname = "tcp_frto_response",
564 .data = &sysctl_tcp_frto_response, 439 .data = &sysctl_tcp_frto_response,
565 .maxlen = sizeof(int), 440 .maxlen = sizeof(int),
@@ -567,7 +442,6 @@ static struct ctl_table ipv4_table[] = {
567 .proc_handler = proc_dointvec 442 .proc_handler = proc_dointvec
568 }, 443 },
569 { 444 {
570 .ctl_name = NET_TCP_LOW_LATENCY,
571 .procname = "tcp_low_latency", 445 .procname = "tcp_low_latency",
572 .data = &sysctl_tcp_low_latency, 446 .data = &sysctl_tcp_low_latency,
573 .maxlen = sizeof(int), 447 .maxlen = sizeof(int),
@@ -575,7 +449,6 @@ static struct ctl_table ipv4_table[] = {
575 .proc_handler = proc_dointvec 449 .proc_handler = proc_dointvec
576 }, 450 },
577 { 451 {
578 .ctl_name = NET_TCP_NO_METRICS_SAVE,
579 .procname = "tcp_no_metrics_save", 452 .procname = "tcp_no_metrics_save",
580 .data = &sysctl_tcp_nometrics_save, 453 .data = &sysctl_tcp_nometrics_save,
581 .maxlen = sizeof(int), 454 .maxlen = sizeof(int),
@@ -583,7 +456,6 @@ static struct ctl_table ipv4_table[] = {
583 .proc_handler = proc_dointvec, 456 .proc_handler = proc_dointvec,
584 }, 457 },
585 { 458 {
586 .ctl_name = NET_TCP_MODERATE_RCVBUF,
587 .procname = "tcp_moderate_rcvbuf", 459 .procname = "tcp_moderate_rcvbuf",
588 .data = &sysctl_tcp_moderate_rcvbuf, 460 .data = &sysctl_tcp_moderate_rcvbuf,
589 .maxlen = sizeof(int), 461 .maxlen = sizeof(int),
@@ -591,7 +463,6 @@ static struct ctl_table ipv4_table[] = {
591 .proc_handler = proc_dointvec, 463 .proc_handler = proc_dointvec,
592 }, 464 },
593 { 465 {
594 .ctl_name = NET_TCP_TSO_WIN_DIVISOR,
595 .procname = "tcp_tso_win_divisor", 466 .procname = "tcp_tso_win_divisor",
596 .data = &sysctl_tcp_tso_win_divisor, 467 .data = &sysctl_tcp_tso_win_divisor,
597 .maxlen = sizeof(int), 468 .maxlen = sizeof(int),
@@ -599,15 +470,12 @@ static struct ctl_table ipv4_table[] = {
599 .proc_handler = proc_dointvec, 470 .proc_handler = proc_dointvec,
600 }, 471 },
601 { 472 {
602 .ctl_name = NET_TCP_CONG_CONTROL,
603 .procname = "tcp_congestion_control", 473 .procname = "tcp_congestion_control",
604 .mode = 0644, 474 .mode = 0644,
605 .maxlen = TCP_CA_NAME_MAX, 475 .maxlen = TCP_CA_NAME_MAX,
606 .proc_handler = proc_tcp_congestion_control, 476 .proc_handler = proc_tcp_congestion_control,
607 .strategy = sysctl_tcp_congestion_control,
608 }, 477 },
609 { 478 {
610 .ctl_name = NET_TCP_ABC,
611 .procname = "tcp_abc", 479 .procname = "tcp_abc",
612 .data = &sysctl_tcp_abc, 480 .data = &sysctl_tcp_abc,
613 .maxlen = sizeof(int), 481 .maxlen = sizeof(int),
@@ -615,7 +483,6 @@ static struct ctl_table ipv4_table[] = {
615 .proc_handler = proc_dointvec, 483 .proc_handler = proc_dointvec,
616 }, 484 },
617 { 485 {
618 .ctl_name = NET_TCP_MTU_PROBING,
619 .procname = "tcp_mtu_probing", 486 .procname = "tcp_mtu_probing",
620 .data = &sysctl_tcp_mtu_probing, 487 .data = &sysctl_tcp_mtu_probing,
621 .maxlen = sizeof(int), 488 .maxlen = sizeof(int),
@@ -623,7 +490,6 @@ static struct ctl_table ipv4_table[] = {
623 .proc_handler = proc_dointvec, 490 .proc_handler = proc_dointvec,
624 }, 491 },
625 { 492 {
626 .ctl_name = NET_TCP_BASE_MSS,
627 .procname = "tcp_base_mss", 493 .procname = "tcp_base_mss",
628 .data = &sysctl_tcp_base_mss, 494 .data = &sysctl_tcp_base_mss,
629 .maxlen = sizeof(int), 495 .maxlen = sizeof(int),
@@ -631,7 +497,6 @@ static struct ctl_table ipv4_table[] = {
631 .proc_handler = proc_dointvec, 497 .proc_handler = proc_dointvec,
632 }, 498 },
633 { 499 {
634 .ctl_name = NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
635 .procname = "tcp_workaround_signed_windows", 500 .procname = "tcp_workaround_signed_windows",
636 .data = &sysctl_tcp_workaround_signed_windows, 501 .data = &sysctl_tcp_workaround_signed_windows,
637 .maxlen = sizeof(int), 502 .maxlen = sizeof(int),
@@ -640,7 +505,6 @@ static struct ctl_table ipv4_table[] = {
640 }, 505 },
641#ifdef CONFIG_NET_DMA 506#ifdef CONFIG_NET_DMA
642 { 507 {
643 .ctl_name = NET_TCP_DMA_COPYBREAK,
644 .procname = "tcp_dma_copybreak", 508 .procname = "tcp_dma_copybreak",
645 .data = &sysctl_tcp_dma_copybreak, 509 .data = &sysctl_tcp_dma_copybreak,
646 .maxlen = sizeof(int), 510 .maxlen = sizeof(int),
@@ -649,7 +513,6 @@ static struct ctl_table ipv4_table[] = {
649 }, 513 },
650#endif 514#endif
651 { 515 {
652 .ctl_name = NET_TCP_SLOW_START_AFTER_IDLE,
653 .procname = "tcp_slow_start_after_idle", 516 .procname = "tcp_slow_start_after_idle",
654 .data = &sysctl_tcp_slow_start_after_idle, 517 .data = &sysctl_tcp_slow_start_after_idle,
655 .maxlen = sizeof(int), 518 .maxlen = sizeof(int),
@@ -658,7 +521,6 @@ static struct ctl_table ipv4_table[] = {
658 }, 521 },
659#ifdef CONFIG_NETLABEL 522#ifdef CONFIG_NETLABEL
660 { 523 {
661 .ctl_name = NET_CIPSOV4_CACHE_ENABLE,
662 .procname = "cipso_cache_enable", 524 .procname = "cipso_cache_enable",
663 .data = &cipso_v4_cache_enabled, 525 .data = &cipso_v4_cache_enabled,
664 .maxlen = sizeof(int), 526 .maxlen = sizeof(int),
@@ -666,7 +528,6 @@ static struct ctl_table ipv4_table[] = {
666 .proc_handler = proc_dointvec, 528 .proc_handler = proc_dointvec,
667 }, 529 },
668 { 530 {
669 .ctl_name = NET_CIPSOV4_CACHE_BUCKET_SIZE,
670 .procname = "cipso_cache_bucket_size", 531 .procname = "cipso_cache_bucket_size",
671 .data = &cipso_v4_cache_bucketsize, 532 .data = &cipso_v4_cache_bucketsize,
672 .maxlen = sizeof(int), 533 .maxlen = sizeof(int),
@@ -674,7 +535,6 @@ static struct ctl_table ipv4_table[] = {
674 .proc_handler = proc_dointvec, 535 .proc_handler = proc_dointvec,
675 }, 536 },
676 { 537 {
677 .ctl_name = NET_CIPSOV4_RBM_OPTFMT,
678 .procname = "cipso_rbm_optfmt", 538 .procname = "cipso_rbm_optfmt",
679 .data = &cipso_v4_rbm_optfmt, 539 .data = &cipso_v4_rbm_optfmt,
680 .maxlen = sizeof(int), 540 .maxlen = sizeof(int),
@@ -682,7 +542,6 @@ static struct ctl_table ipv4_table[] = {
682 .proc_handler = proc_dointvec, 542 .proc_handler = proc_dointvec,
683 }, 543 },
684 { 544 {
685 .ctl_name = NET_CIPSOV4_RBM_STRICTVALID,
686 .procname = "cipso_rbm_strictvalid", 545 .procname = "cipso_rbm_strictvalid",
687 .data = &cipso_v4_rbm_strictvalid, 546 .data = &cipso_v4_rbm_strictvalid,
688 .maxlen = sizeof(int), 547 .maxlen = sizeof(int),
@@ -697,15 +556,12 @@ static struct ctl_table ipv4_table[] = {
697 .proc_handler = proc_tcp_available_congestion_control, 556 .proc_handler = proc_tcp_available_congestion_control,
698 }, 557 },
699 { 558 {
700 .ctl_name = NET_TCP_ALLOWED_CONG_CONTROL,
701 .procname = "tcp_allowed_congestion_control", 559 .procname = "tcp_allowed_congestion_control",
702 .maxlen = TCP_CA_BUF_MAX, 560 .maxlen = TCP_CA_BUF_MAX,
703 .mode = 0644, 561 .mode = 0644,
704 .proc_handler = proc_allowed_congestion_control, 562 .proc_handler = proc_allowed_congestion_control,
705 .strategy = strategy_allowed_congestion_control,
706 }, 563 },
707 { 564 {
708 .ctl_name = NET_TCP_MAX_SSTHRESH,
709 .procname = "tcp_max_ssthresh", 565 .procname = "tcp_max_ssthresh",
710 .data = &sysctl_tcp_max_ssthresh, 566 .data = &sysctl_tcp_max_ssthresh,
711 .maxlen = sizeof(int), 567 .maxlen = sizeof(int),
@@ -713,7 +569,6 @@ static struct ctl_table ipv4_table[] = {
713 .proc_handler = proc_dointvec, 569 .proc_handler = proc_dointvec,
714 }, 570 },
715 { 571 {
716 .ctl_name = CTL_UNNUMBERED,
717 .procname = "tcp_cookie_size", 572 .procname = "tcp_cookie_size",
718 .data = &sysctl_tcp_cookie_size, 573 .data = &sysctl_tcp_cookie_size,
719 .maxlen = sizeof(int), 574 .maxlen = sizeof(int),
@@ -721,41 +576,34 @@ static struct ctl_table ipv4_table[] = {
721 .proc_handler = proc_dointvec 576 .proc_handler = proc_dointvec
722 }, 577 },
723 { 578 {
724 .ctl_name = CTL_UNNUMBERED,
725 .procname = "udp_mem", 579 .procname = "udp_mem",
726 .data = &sysctl_udp_mem, 580 .data = &sysctl_udp_mem,
727 .maxlen = sizeof(sysctl_udp_mem), 581 .maxlen = sizeof(sysctl_udp_mem),
728 .mode = 0644, 582 .mode = 0644,
729 .proc_handler = proc_dointvec_minmax, 583 .proc_handler = proc_dointvec_minmax,
730 .strategy = sysctl_intvec,
731 .extra1 = &zero 584 .extra1 = &zero
732 }, 585 },
733 { 586 {
734 .ctl_name = CTL_UNNUMBERED,
735 .procname = "udp_rmem_min", 587 .procname = "udp_rmem_min",
736 .data = &sysctl_udp_rmem_min, 588 .data = &sysctl_udp_rmem_min,
737 .maxlen = sizeof(sysctl_udp_rmem_min), 589 .maxlen = sizeof(sysctl_udp_rmem_min),
738 .mode = 0644, 590 .mode = 0644,
739 .proc_handler = proc_dointvec_minmax, 591 .proc_handler = proc_dointvec_minmax,
740 .strategy = sysctl_intvec,
741 .extra1 = &zero 592 .extra1 = &zero
742 }, 593 },
743 { 594 {
744 .ctl_name = CTL_UNNUMBERED,
745 .procname = "udp_wmem_min", 595 .procname = "udp_wmem_min",
746 .data = &sysctl_udp_wmem_min, 596 .data = &sysctl_udp_wmem_min,
747 .maxlen = sizeof(sysctl_udp_wmem_min), 597 .maxlen = sizeof(sysctl_udp_wmem_min),
748 .mode = 0644, 598 .mode = 0644,
749 .proc_handler = proc_dointvec_minmax, 599 .proc_handler = proc_dointvec_minmax,
750 .strategy = sysctl_intvec,
751 .extra1 = &zero 600 .extra1 = &zero
752 }, 601 },
753 { .ctl_name = 0 } 602 { }
754}; 603};
755 604
756static struct ctl_table ipv4_net_table[] = { 605static struct ctl_table ipv4_net_table[] = {
757 { 606 {
758 .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_ALL,
759 .procname = "icmp_echo_ignore_all", 607 .procname = "icmp_echo_ignore_all",
760 .data = &init_net.ipv4.sysctl_icmp_echo_ignore_all, 608 .data = &init_net.ipv4.sysctl_icmp_echo_ignore_all,
761 .maxlen = sizeof(int), 609 .maxlen = sizeof(int),
@@ -763,7 +611,6 @@ static struct ctl_table ipv4_net_table[] = {
763 .proc_handler = proc_dointvec 611 .proc_handler = proc_dointvec
764 }, 612 },
765 { 613 {
766 .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
767 .procname = "icmp_echo_ignore_broadcasts", 614 .procname = "icmp_echo_ignore_broadcasts",
768 .data = &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts, 615 .data = &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
769 .maxlen = sizeof(int), 616 .maxlen = sizeof(int),
@@ -771,7 +618,6 @@ static struct ctl_table ipv4_net_table[] = {
771 .proc_handler = proc_dointvec 618 .proc_handler = proc_dointvec
772 }, 619 },
773 { 620 {
774 .ctl_name = NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
775 .procname = "icmp_ignore_bogus_error_responses", 621 .procname = "icmp_ignore_bogus_error_responses",
776 .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, 622 .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
777 .maxlen = sizeof(int), 623 .maxlen = sizeof(int),
@@ -779,7 +625,6 @@ static struct ctl_table ipv4_net_table[] = {
779 .proc_handler = proc_dointvec 625 .proc_handler = proc_dointvec
780 }, 626 },
781 { 627 {
782 .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
783 .procname = "icmp_errors_use_inbound_ifaddr", 628 .procname = "icmp_errors_use_inbound_ifaddr",
784 .data = &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr, 629 .data = &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr,
785 .maxlen = sizeof(int), 630 .maxlen = sizeof(int),
@@ -787,16 +632,13 @@ static struct ctl_table ipv4_net_table[] = {
787 .proc_handler = proc_dointvec 632 .proc_handler = proc_dointvec
788 }, 633 },
789 { 634 {
790 .ctl_name = NET_IPV4_ICMP_RATELIMIT,
791 .procname = "icmp_ratelimit", 635 .procname = "icmp_ratelimit",
792 .data = &init_net.ipv4.sysctl_icmp_ratelimit, 636 .data = &init_net.ipv4.sysctl_icmp_ratelimit,
793 .maxlen = sizeof(int), 637 .maxlen = sizeof(int),
794 .mode = 0644, 638 .mode = 0644,
795 .proc_handler = proc_dointvec_ms_jiffies, 639 .proc_handler = proc_dointvec_ms_jiffies,
796 .strategy = sysctl_ms_jiffies
797 }, 640 },
798 { 641 {
799 .ctl_name = NET_IPV4_ICMP_RATEMASK,
800 .procname = "icmp_ratemask", 642 .procname = "icmp_ratemask",
801 .data = &init_net.ipv4.sysctl_icmp_ratemask, 643 .data = &init_net.ipv4.sysctl_icmp_ratemask,
802 .maxlen = sizeof(int), 644 .maxlen = sizeof(int),
@@ -804,7 +646,6 @@ static struct ctl_table ipv4_net_table[] = {
804 .proc_handler = proc_dointvec 646 .proc_handler = proc_dointvec
805 }, 647 },
806 { 648 {
807 .ctl_name = CTL_UNNUMBERED,
808 .procname = "rt_cache_rebuild_count", 649 .procname = "rt_cache_rebuild_count",
809 .data = &init_net.ipv4.sysctl_rt_cache_rebuild_count, 650 .data = &init_net.ipv4.sysctl_rt_cache_rebuild_count,
810 .maxlen = sizeof(int), 651 .maxlen = sizeof(int),
@@ -815,8 +656,8 @@ static struct ctl_table ipv4_net_table[] = {
815}; 656};
816 657
817struct ctl_path net_ipv4_ctl_path[] = { 658struct ctl_path net_ipv4_ctl_path[] = {
818 { .procname = "net", .ctl_name = CTL_NET, }, 659 { .procname = "net", },
819 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 660 { .procname = "ipv4", },
820 { }, 661 { },
821}; 662};
822EXPORT_SYMBOL_GPL(net_ipv4_ctl_path); 663EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 74fb2eb833ec..8c08a28d8f83 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -267,7 +267,6 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
267#ifdef CONFIG_SYSCTL 267#ifdef CONFIG_SYSCTL
268static struct ctl_table xfrm4_policy_table[] = { 268static struct ctl_table xfrm4_policy_table[] = {
269 { 269 {
270 .ctl_name = CTL_UNNUMBERED,
271 .procname = "xfrm4_gc_thresh", 270 .procname = "xfrm4_gc_thresh",
272 .data = &xfrm4_dst_ops.gc_thresh, 271 .data = &xfrm4_dst_ops.gc_thresh,
273 .maxlen = sizeof(int), 272 .maxlen = sizeof(int),
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b1ce8fc62049..de7a194a64ab 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4037,41 +4037,6 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
4037 return ret; 4037 return ret;
4038} 4038}
4039 4039
4040static int addrconf_sysctl_forward_strategy(ctl_table *table,
4041 void __user *oldval,
4042 size_t __user *oldlenp,
4043 void __user *newval, size_t newlen)
4044{
4045 int *valp = table->data;
4046 int val = *valp;
4047 int new;
4048
4049 if (!newval || !newlen)
4050 return 0;
4051 if (newlen != sizeof(int))
4052 return -EINVAL;
4053 if (get_user(new, (int __user *)newval))
4054 return -EFAULT;
4055 if (new == *valp)
4056 return 0;
4057 if (oldval && oldlenp) {
4058 size_t len;
4059 if (get_user(len, oldlenp))
4060 return -EFAULT;
4061 if (len) {
4062 if (len > table->maxlen)
4063 len = table->maxlen;
4064 if (copy_to_user(oldval, valp, len))
4065 return -EFAULT;
4066 if (put_user(len, oldlenp))
4067 return -EFAULT;
4068 }
4069 }
4070
4071 *valp = new;
4072 return addrconf_fixup_forwarding(table, valp, val);
4073}
4074
4075static void dev_disable_change(struct inet6_dev *idev) 4040static void dev_disable_change(struct inet6_dev *idev)
4076{ 4041{
4077 if (!idev || !idev->dev) 4042 if (!idev || !idev->dev)
@@ -4148,16 +4113,13 @@ static struct addrconf_sysctl_table
4148 .sysctl_header = NULL, 4113 .sysctl_header = NULL,
4149 .addrconf_vars = { 4114 .addrconf_vars = {
4150 { 4115 {
4151 .ctl_name = NET_IPV6_FORWARDING,
4152 .procname = "forwarding", 4116 .procname = "forwarding",
4153 .data = &ipv6_devconf.forwarding, 4117 .data = &ipv6_devconf.forwarding,
4154 .maxlen = sizeof(int), 4118 .maxlen = sizeof(int),
4155 .mode = 0644, 4119 .mode = 0644,
4156 .proc_handler = addrconf_sysctl_forward, 4120 .proc_handler = addrconf_sysctl_forward,
4157 .strategy = addrconf_sysctl_forward_strategy,
4158 }, 4121 },
4159 { 4122 {
4160 .ctl_name = NET_IPV6_HOP_LIMIT,
4161 .procname = "hop_limit", 4123 .procname = "hop_limit",
4162 .data = &ipv6_devconf.hop_limit, 4124 .data = &ipv6_devconf.hop_limit,
4163 .maxlen = sizeof(int), 4125 .maxlen = sizeof(int),
@@ -4165,7 +4127,6 @@ static struct addrconf_sysctl_table
4165 .proc_handler = proc_dointvec, 4127 .proc_handler = proc_dointvec,
4166 }, 4128 },
4167 { 4129 {
4168 .ctl_name = NET_IPV6_MTU,
4169 .procname = "mtu", 4130 .procname = "mtu",
4170 .data = &ipv6_devconf.mtu6, 4131 .data = &ipv6_devconf.mtu6,
4171 .maxlen = sizeof(int), 4132 .maxlen = sizeof(int),
@@ -4173,7 +4134,6 @@ static struct addrconf_sysctl_table
4173 .proc_handler = proc_dointvec, 4134 .proc_handler = proc_dointvec,
4174 }, 4135 },
4175 { 4136 {
4176 .ctl_name = NET_IPV6_ACCEPT_RA,
4177 .procname = "accept_ra", 4137 .procname = "accept_ra",
4178 .data = &ipv6_devconf.accept_ra, 4138 .data = &ipv6_devconf.accept_ra,
4179 .maxlen = sizeof(int), 4139 .maxlen = sizeof(int),
@@ -4181,7 +4141,6 @@ static struct addrconf_sysctl_table
4181 .proc_handler = proc_dointvec, 4141 .proc_handler = proc_dointvec,
4182 }, 4142 },
4183 { 4143 {
4184 .ctl_name = NET_IPV6_ACCEPT_REDIRECTS,
4185 .procname = "accept_redirects", 4144 .procname = "accept_redirects",
4186 .data = &ipv6_devconf.accept_redirects, 4145 .data = &ipv6_devconf.accept_redirects,
4187 .maxlen = sizeof(int), 4146 .maxlen = sizeof(int),
@@ -4189,7 +4148,6 @@ static struct addrconf_sysctl_table
4189 .proc_handler = proc_dointvec, 4148 .proc_handler = proc_dointvec,
4190 }, 4149 },
4191 { 4150 {
4192 .ctl_name = NET_IPV6_AUTOCONF,
4193 .procname = "autoconf", 4151 .procname = "autoconf",
4194 .data = &ipv6_devconf.autoconf, 4152 .data = &ipv6_devconf.autoconf,
4195 .maxlen = sizeof(int), 4153 .maxlen = sizeof(int),
@@ -4197,7 +4155,6 @@ static struct addrconf_sysctl_table
4197 .proc_handler = proc_dointvec, 4155 .proc_handler = proc_dointvec,
4198 }, 4156 },
4199 { 4157 {
4200 .ctl_name = NET_IPV6_DAD_TRANSMITS,
4201 .procname = "dad_transmits", 4158 .procname = "dad_transmits",
4202 .data = &ipv6_devconf.dad_transmits, 4159 .data = &ipv6_devconf.dad_transmits,
4203 .maxlen = sizeof(int), 4160 .maxlen = sizeof(int),
@@ -4205,7 +4162,6 @@ static struct addrconf_sysctl_table
4205 .proc_handler = proc_dointvec, 4162 .proc_handler = proc_dointvec,
4206 }, 4163 },
4207 { 4164 {
4208 .ctl_name = NET_IPV6_RTR_SOLICITS,
4209 .procname = "router_solicitations", 4165 .procname = "router_solicitations",
4210 .data = &ipv6_devconf.rtr_solicits, 4166 .data = &ipv6_devconf.rtr_solicits,
4211 .maxlen = sizeof(int), 4167 .maxlen = sizeof(int),
@@ -4213,25 +4169,20 @@ static struct addrconf_sysctl_table
4213 .proc_handler = proc_dointvec, 4169 .proc_handler = proc_dointvec,
4214 }, 4170 },
4215 { 4171 {
4216 .ctl_name = NET_IPV6_RTR_SOLICIT_INTERVAL,
4217 .procname = "router_solicitation_interval", 4172 .procname = "router_solicitation_interval",
4218 .data = &ipv6_devconf.rtr_solicit_interval, 4173 .data = &ipv6_devconf.rtr_solicit_interval,
4219 .maxlen = sizeof(int), 4174 .maxlen = sizeof(int),
4220 .mode = 0644, 4175 .mode = 0644,
4221 .proc_handler = proc_dointvec_jiffies, 4176 .proc_handler = proc_dointvec_jiffies,
4222 .strategy = sysctl_jiffies,
4223 }, 4177 },
4224 { 4178 {
4225 .ctl_name = NET_IPV6_RTR_SOLICIT_DELAY,
4226 .procname = "router_solicitation_delay", 4179 .procname = "router_solicitation_delay",
4227 .data = &ipv6_devconf.rtr_solicit_delay, 4180 .data = &ipv6_devconf.rtr_solicit_delay,
4228 .maxlen = sizeof(int), 4181 .maxlen = sizeof(int),
4229 .mode = 0644, 4182 .mode = 0644,
4230 .proc_handler = proc_dointvec_jiffies, 4183 .proc_handler = proc_dointvec_jiffies,
4231 .strategy = sysctl_jiffies,
4232 }, 4184 },
4233 { 4185 {
4234 .ctl_name = NET_IPV6_FORCE_MLD_VERSION,
4235 .procname = "force_mld_version", 4186 .procname = "force_mld_version",
4236 .data = &ipv6_devconf.force_mld_version, 4187 .data = &ipv6_devconf.force_mld_version,
4237 .maxlen = sizeof(int), 4188 .maxlen = sizeof(int),
@@ -4240,7 +4191,6 @@ static struct addrconf_sysctl_table
4240 }, 4191 },
4241#ifdef CONFIG_IPV6_PRIVACY 4192#ifdef CONFIG_IPV6_PRIVACY
4242 { 4193 {
4243 .ctl_name = NET_IPV6_USE_TEMPADDR,
4244 .procname = "use_tempaddr", 4194 .procname = "use_tempaddr",
4245 .data = &ipv6_devconf.use_tempaddr, 4195 .data = &ipv6_devconf.use_tempaddr,
4246 .maxlen = sizeof(int), 4196 .maxlen = sizeof(int),
@@ -4248,7 +4198,6 @@ static struct addrconf_sysctl_table
4248 .proc_handler = proc_dointvec, 4198 .proc_handler = proc_dointvec,
4249 }, 4199 },
4250 { 4200 {
4251 .ctl_name = NET_IPV6_TEMP_VALID_LFT,
4252 .procname = "temp_valid_lft", 4201 .procname = "temp_valid_lft",
4253 .data = &ipv6_devconf.temp_valid_lft, 4202 .data = &ipv6_devconf.temp_valid_lft,
4254 .maxlen = sizeof(int), 4203 .maxlen = sizeof(int),
@@ -4256,7 +4205,6 @@ static struct addrconf_sysctl_table
4256 .proc_handler = proc_dointvec, 4205 .proc_handler = proc_dointvec,
4257 }, 4206 },
4258 { 4207 {
4259 .ctl_name = NET_IPV6_TEMP_PREFERED_LFT,
4260 .procname = "temp_prefered_lft", 4208 .procname = "temp_prefered_lft",
4261 .data = &ipv6_devconf.temp_prefered_lft, 4209 .data = &ipv6_devconf.temp_prefered_lft,
4262 .maxlen = sizeof(int), 4210 .maxlen = sizeof(int),
@@ -4264,7 +4212,6 @@ static struct addrconf_sysctl_table
4264 .proc_handler = proc_dointvec, 4212 .proc_handler = proc_dointvec,
4265 }, 4213 },
4266 { 4214 {
4267 .ctl_name = NET_IPV6_REGEN_MAX_RETRY,
4268 .procname = "regen_max_retry", 4215 .procname = "regen_max_retry",
4269 .data = &ipv6_devconf.regen_max_retry, 4216 .data = &ipv6_devconf.regen_max_retry,
4270 .maxlen = sizeof(int), 4217 .maxlen = sizeof(int),
@@ -4272,7 +4219,6 @@ static struct addrconf_sysctl_table
4272 .proc_handler = proc_dointvec, 4219 .proc_handler = proc_dointvec,
4273 }, 4220 },
4274 { 4221 {
4275 .ctl_name = NET_IPV6_MAX_DESYNC_FACTOR,
4276 .procname = "max_desync_factor", 4222 .procname = "max_desync_factor",
4277 .data = &ipv6_devconf.max_desync_factor, 4223 .data = &ipv6_devconf.max_desync_factor,
4278 .maxlen = sizeof(int), 4224 .maxlen = sizeof(int),
@@ -4281,7 +4227,6 @@ static struct addrconf_sysctl_table
4281 }, 4227 },
4282#endif 4228#endif
4283 { 4229 {
4284 .ctl_name = NET_IPV6_MAX_ADDRESSES,
4285 .procname = "max_addresses", 4230 .procname = "max_addresses",
4286 .data = &ipv6_devconf.max_addresses, 4231 .data = &ipv6_devconf.max_addresses,
4287 .maxlen = sizeof(int), 4232 .maxlen = sizeof(int),
@@ -4289,7 +4234,6 @@ static struct addrconf_sysctl_table
4289 .proc_handler = proc_dointvec, 4234 .proc_handler = proc_dointvec,
4290 }, 4235 },
4291 { 4236 {
4292 .ctl_name = NET_IPV6_ACCEPT_RA_DEFRTR,
4293 .procname = "accept_ra_defrtr", 4237 .procname = "accept_ra_defrtr",
4294 .data = &ipv6_devconf.accept_ra_defrtr, 4238 .data = &ipv6_devconf.accept_ra_defrtr,
4295 .maxlen = sizeof(int), 4239 .maxlen = sizeof(int),
@@ -4297,7 +4241,6 @@ static struct addrconf_sysctl_table
4297 .proc_handler = proc_dointvec, 4241 .proc_handler = proc_dointvec,
4298 }, 4242 },
4299 { 4243 {
4300 .ctl_name = NET_IPV6_ACCEPT_RA_PINFO,
4301 .procname = "accept_ra_pinfo", 4244 .procname = "accept_ra_pinfo",
4302 .data = &ipv6_devconf.accept_ra_pinfo, 4245 .data = &ipv6_devconf.accept_ra_pinfo,
4303 .maxlen = sizeof(int), 4246 .maxlen = sizeof(int),
@@ -4306,7 +4249,6 @@ static struct addrconf_sysctl_table
4306 }, 4249 },
4307#ifdef CONFIG_IPV6_ROUTER_PREF 4250#ifdef CONFIG_IPV6_ROUTER_PREF
4308 { 4251 {
4309 .ctl_name = NET_IPV6_ACCEPT_RA_RTR_PREF,
4310 .procname = "accept_ra_rtr_pref", 4252 .procname = "accept_ra_rtr_pref",
4311 .data = &ipv6_devconf.accept_ra_rtr_pref, 4253 .data = &ipv6_devconf.accept_ra_rtr_pref,
4312 .maxlen = sizeof(int), 4254 .maxlen = sizeof(int),
@@ -4314,17 +4256,14 @@ static struct addrconf_sysctl_table
4314 .proc_handler = proc_dointvec, 4256 .proc_handler = proc_dointvec,
4315 }, 4257 },
4316 { 4258 {
4317 .ctl_name = NET_IPV6_RTR_PROBE_INTERVAL,
4318 .procname = "router_probe_interval", 4259 .procname = "router_probe_interval",
4319 .data = &ipv6_devconf.rtr_probe_interval, 4260 .data = &ipv6_devconf.rtr_probe_interval,
4320 .maxlen = sizeof(int), 4261 .maxlen = sizeof(int),
4321 .mode = 0644, 4262 .mode = 0644,
4322 .proc_handler = proc_dointvec_jiffies, 4263 .proc_handler = proc_dointvec_jiffies,
4323 .strategy = sysctl_jiffies,
4324 }, 4264 },
4325#ifdef CONFIG_IPV6_ROUTE_INFO 4265#ifdef CONFIG_IPV6_ROUTE_INFO
4326 { 4266 {
4327 .ctl_name = NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
4328 .procname = "accept_ra_rt_info_max_plen", 4267 .procname = "accept_ra_rt_info_max_plen",
4329 .data = &ipv6_devconf.accept_ra_rt_info_max_plen, 4268 .data = &ipv6_devconf.accept_ra_rt_info_max_plen,
4330 .maxlen = sizeof(int), 4269 .maxlen = sizeof(int),
@@ -4334,7 +4273,6 @@ static struct addrconf_sysctl_table
4334#endif 4273#endif
4335#endif 4274#endif
4336 { 4275 {
4337 .ctl_name = NET_IPV6_PROXY_NDP,
4338 .procname = "proxy_ndp", 4276 .procname = "proxy_ndp",
4339 .data = &ipv6_devconf.proxy_ndp, 4277 .data = &ipv6_devconf.proxy_ndp,
4340 .maxlen = sizeof(int), 4278 .maxlen = sizeof(int),
@@ -4342,7 +4280,6 @@ static struct addrconf_sysctl_table
4342 .proc_handler = proc_dointvec, 4280 .proc_handler = proc_dointvec,
4343 }, 4281 },
4344 { 4282 {
4345 .ctl_name = NET_IPV6_ACCEPT_SOURCE_ROUTE,
4346 .procname = "accept_source_route", 4283 .procname = "accept_source_route",
4347 .data = &ipv6_devconf.accept_source_route, 4284 .data = &ipv6_devconf.accept_source_route,
4348 .maxlen = sizeof(int), 4285 .maxlen = sizeof(int),
@@ -4351,7 +4288,6 @@ static struct addrconf_sysctl_table
4351 }, 4288 },
4352#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 4289#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
4353 { 4290 {
4354 .ctl_name = CTL_UNNUMBERED,
4355 .procname = "optimistic_dad", 4291 .procname = "optimistic_dad",
4356 .data = &ipv6_devconf.optimistic_dad, 4292 .data = &ipv6_devconf.optimistic_dad,
4357 .maxlen = sizeof(int), 4293 .maxlen = sizeof(int),
@@ -4362,7 +4298,6 @@ static struct addrconf_sysctl_table
4362#endif 4298#endif
4363#ifdef CONFIG_IPV6_MROUTE 4299#ifdef CONFIG_IPV6_MROUTE
4364 { 4300 {
4365 .ctl_name = CTL_UNNUMBERED,
4366 .procname = "mc_forwarding", 4301 .procname = "mc_forwarding",
4367 .data = &ipv6_devconf.mc_forwarding, 4302 .data = &ipv6_devconf.mc_forwarding,
4368 .maxlen = sizeof(int), 4303 .maxlen = sizeof(int),
@@ -4371,16 +4306,13 @@ static struct addrconf_sysctl_table
4371 }, 4306 },
4372#endif 4307#endif
4373 { 4308 {
4374 .ctl_name = CTL_UNNUMBERED,
4375 .procname = "disable_ipv6", 4309 .procname = "disable_ipv6",
4376 .data = &ipv6_devconf.disable_ipv6, 4310 .data = &ipv6_devconf.disable_ipv6,
4377 .maxlen = sizeof(int), 4311 .maxlen = sizeof(int),
4378 .mode = 0644, 4312 .mode = 0644,
4379 .proc_handler = addrconf_sysctl_disable, 4313 .proc_handler = addrconf_sysctl_disable,
4380 .strategy = sysctl_intvec,
4381 }, 4314 },
4382 { 4315 {
4383 .ctl_name = CTL_UNNUMBERED,
4384 .procname = "accept_dad", 4316 .procname = "accept_dad",
4385 .data = &ipv6_devconf.accept_dad, 4317 .data = &ipv6_devconf.accept_dad,
4386 .maxlen = sizeof(int), 4318 .maxlen = sizeof(int),
@@ -4388,7 +4320,6 @@ static struct addrconf_sysctl_table
4388 .proc_handler = proc_dointvec, 4320 .proc_handler = proc_dointvec,
4389 }, 4321 },
4390 { 4322 {
4391 .ctl_name = CTL_UNNUMBERED,
4392 .procname = "force_tllao", 4323 .procname = "force_tllao",
4393 .data = &ipv6_devconf.force_tllao, 4324 .data = &ipv6_devconf.force_tllao,
4394 .maxlen = sizeof(int), 4325 .maxlen = sizeof(int),
@@ -4396,13 +4327,13 @@ static struct addrconf_sysctl_table
4396 .proc_handler = proc_dointvec 4327 .proc_handler = proc_dointvec
4397 }, 4328 },
4398 { 4329 {
4399 .ctl_name = 0, /* sentinel */ 4330 /* sentinel */
4400 } 4331 }
4401 }, 4332 },
4402}; 4333};
4403 4334
4404static int __addrconf_sysctl_register(struct net *net, char *dev_name, 4335static int __addrconf_sysctl_register(struct net *net, char *dev_name,
4405 int ctl_name, struct inet6_dev *idev, struct ipv6_devconf *p) 4336 struct inet6_dev *idev, struct ipv6_devconf *p)
4406{ 4337{
4407 int i; 4338 int i;
4408 struct addrconf_sysctl_table *t; 4339 struct addrconf_sysctl_table *t;
@@ -4410,9 +4341,9 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
4410#define ADDRCONF_CTL_PATH_DEV 3 4341#define ADDRCONF_CTL_PATH_DEV 3
4411 4342
4412 struct ctl_path addrconf_ctl_path[] = { 4343 struct ctl_path addrconf_ctl_path[] = {
4413 { .procname = "net", .ctl_name = CTL_NET, }, 4344 { .procname = "net", },
4414 { .procname = "ipv6", .ctl_name = NET_IPV6, }, 4345 { .procname = "ipv6", },
4415 { .procname = "conf", .ctl_name = NET_IPV6_CONF, }, 4346 { .procname = "conf", },
4416 { /* to be set */ }, 4347 { /* to be set */ },
4417 { }, 4348 { },
4418 }; 4349 };
@@ -4438,7 +4369,6 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
4438 goto free; 4369 goto free;
4439 4370
4440 addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].procname = t->dev_name; 4371 addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].procname = t->dev_name;
4441 addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].ctl_name = ctl_name;
4442 4372
4443 t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path, 4373 t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path,
4444 t->addrconf_vars); 4374 t->addrconf_vars);
@@ -4474,10 +4404,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev)
4474{ 4404{
4475 neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, 4405 neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6,
4476 NET_IPV6_NEIGH, "ipv6", 4406 NET_IPV6_NEIGH, "ipv6",
4477 &ndisc_ifinfo_sysctl_change, 4407 &ndisc_ifinfo_sysctl_change);
4478 ndisc_ifinfo_sysctl_strategy);
4479 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, 4408 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
4480 idev->dev->ifindex, idev, &idev->cnf); 4409 idev, &idev->cnf);
4481} 4410}
4482 4411
4483static void addrconf_sysctl_unregister(struct inet6_dev *idev) 4412static void addrconf_sysctl_unregister(struct inet6_dev *idev)
@@ -4516,13 +4445,11 @@ static int addrconf_init_net(struct net *net)
4516 net->ipv6.devconf_dflt = dflt; 4445 net->ipv6.devconf_dflt = dflt;
4517 4446
4518#ifdef CONFIG_SYSCTL 4447#ifdef CONFIG_SYSCTL
4519 err = __addrconf_sysctl_register(net, "all", NET_PROTO_CONF_ALL, 4448 err = __addrconf_sysctl_register(net, "all", NULL, all);
4520 NULL, all);
4521 if (err < 0) 4449 if (err < 0)
4522 goto err_reg_all; 4450 goto err_reg_all;
4523 4451
4524 err = __addrconf_sysctl_register(net, "default", NET_PROTO_CONF_DEFAULT, 4452 err = __addrconf_sysctl_register(net, "default", NULL, dflt);
4525 NULL, dflt);
4526 if (err < 0) 4453 if (err < 0)
4527 goto err_reg_dflt; 4454 goto err_reg_dflt;
4528#endif 4455#endif
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index f23ebbec0631..4ae661bc3677 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -942,15 +942,13 @@ EXPORT_SYMBOL(icmpv6_err_convert);
942#ifdef CONFIG_SYSCTL 942#ifdef CONFIG_SYSCTL
943ctl_table ipv6_icmp_table_template[] = { 943ctl_table ipv6_icmp_table_template[] = {
944 { 944 {
945 .ctl_name = NET_IPV6_ICMP_RATELIMIT,
946 .procname = "ratelimit", 945 .procname = "ratelimit",
947 .data = &init_net.ipv6.sysctl.icmpv6_time, 946 .data = &init_net.ipv6.sysctl.icmpv6_time,
948 .maxlen = sizeof(int), 947 .maxlen = sizeof(int),
949 .mode = 0644, 948 .mode = 0644,
950 .proc_handler = proc_dointvec_ms_jiffies, 949 .proc_handler = proc_dointvec_ms_jiffies,
951 .strategy = sysctl_ms_jiffies
952 }, 950 },
953 { .ctl_name = 0 }, 951 { },
954}; 952};
955 953
956struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) 954struct ctl_table *ipv6_icmp_sysctl_init(struct net *net)
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 3507cfe1e7a2..c45852798092 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1769,42 +1769,6 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu
1769 return ret; 1769 return ret;
1770} 1770}
1771 1771
1772int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
1773 void __user *oldval, size_t __user *oldlenp,
1774 void __user *newval, size_t newlen)
1775{
1776 struct net_device *dev = ctl->extra1;
1777 struct inet6_dev *idev;
1778 int ret;
1779
1780 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1781 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1782 ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
1783
1784 switch (ctl->ctl_name) {
1785 case NET_NEIGH_REACHABLE_TIME:
1786 ret = sysctl_jiffies(ctl, oldval, oldlenp, newval, newlen);
1787 break;
1788 case NET_NEIGH_RETRANS_TIME_MS:
1789 case NET_NEIGH_REACHABLE_TIME_MS:
1790 ret = sysctl_ms_jiffies(ctl, oldval, oldlenp, newval, newlen);
1791 break;
1792 default:
1793 ret = 0;
1794 }
1795
1796 if (newval && newlen && ret > 0 &&
1797 dev && (idev = in6_dev_get(dev)) != NULL) {
1798 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1799 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1800 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1801 idev->tstamp = jiffies;
1802 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1803 in6_dev_put(idev);
1804 }
1805
1806 return ret;
1807}
1808 1772
1809#endif 1773#endif
1810 1774
@@ -1858,8 +1822,7 @@ int __init ndisc_init(void)
1858#ifdef CONFIG_SYSCTL 1822#ifdef CONFIG_SYSCTL
1859 err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, 1823 err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6,
1860 NET_IPV6_NEIGH, "ipv6", 1824 NET_IPV6_NEIGH, "ipv6",
1861 &ndisc_ifinfo_sysctl_change, 1825 &ndisc_ifinfo_sysctl_change);
1862 &ndisc_ifinfo_sysctl_strategy);
1863 if (err) 1826 if (err)
1864 goto out_unregister_pernet; 1827 goto out_unregister_pernet;
1865#endif 1828#endif
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index db4d5725cce8..7854052be60b 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -36,7 +36,6 @@
36 36
37#define IPQ_QMAX_DEFAULT 1024 37#define IPQ_QMAX_DEFAULT 1024
38#define IPQ_PROC_FS_NAME "ip6_queue" 38#define IPQ_PROC_FS_NAME "ip6_queue"
39#define NET_IPQ_QMAX 2088
40#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" 39#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
41 40
42typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); 41typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
@@ -517,14 +516,13 @@ static struct ctl_table_header *ipq_sysctl_header;
517 516
518static ctl_table ipq_table[] = { 517static ctl_table ipq_table[] = {
519 { 518 {
520 .ctl_name = NET_IPQ_QMAX,
521 .procname = NET_IPQ_QMAX_NAME, 519 .procname = NET_IPQ_QMAX_NAME,
522 .data = &queue_maxlen, 520 .data = &queue_maxlen,
523 .maxlen = sizeof(queue_maxlen), 521 .maxlen = sizeof(queue_maxlen),
524 .mode = 0644, 522 .mode = 0644,
525 .proc_handler = proc_dointvec 523 .proc_handler = proc_dointvec
526 }, 524 },
527 { .ctl_name = 0 } 525 { }
528}; 526};
529#endif 527#endif
530 528
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 0f3df45718ac..c7b8bd1d7984 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -277,9 +277,7 @@ static struct ctl_table icmpv6_sysctl_table[] = {
277 .mode = 0644, 277 .mode = 0644,
278 .proc_handler = proc_dointvec_jiffies, 278 .proc_handler = proc_dointvec_jiffies,
279 }, 279 },
280 { 280 { }
281 .ctl_name = 0
282 }
283}; 281};
284#endif /* CONFIG_SYSCTL */ 282#endif /* CONFIG_SYSCTL */
285 283
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index f3aba255ad9f..e0b9424fa1b2 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -83,7 +83,6 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
83 .proc_handler = proc_dointvec_jiffies, 83 .proc_handler = proc_dointvec_jiffies,
84 }, 84 },
85 { 85 {
86 .ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH,
87 .procname = "nf_conntrack_frag6_low_thresh", 86 .procname = "nf_conntrack_frag6_low_thresh",
88 .data = &nf_init_frags.low_thresh, 87 .data = &nf_init_frags.low_thresh,
89 .maxlen = sizeof(unsigned int), 88 .maxlen = sizeof(unsigned int),
@@ -91,14 +90,13 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
91 .proc_handler = proc_dointvec, 90 .proc_handler = proc_dointvec,
92 }, 91 },
93 { 92 {
94 .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH,
95 .procname = "nf_conntrack_frag6_high_thresh", 93 .procname = "nf_conntrack_frag6_high_thresh",
96 .data = &nf_init_frags.high_thresh, 94 .data = &nf_init_frags.high_thresh,
97 .maxlen = sizeof(unsigned int), 95 .maxlen = sizeof(unsigned int),
98 .mode = 0644, 96 .mode = 0644,
99 .proc_handler = proc_dointvec, 97 .proc_handler = proc_dointvec,
100 }, 98 },
101 { .ctl_name = 0 } 99 { }
102}; 100};
103#endif 101#endif
104 102
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 45efc39753e2..4d98549a6868 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -635,7 +635,6 @@ static const struct inet6_protocol frag_protocol =
635#ifdef CONFIG_SYSCTL 635#ifdef CONFIG_SYSCTL
636static struct ctl_table ip6_frags_ns_ctl_table[] = { 636static struct ctl_table ip6_frags_ns_ctl_table[] = {
637 { 637 {
638 .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH,
639 .procname = "ip6frag_high_thresh", 638 .procname = "ip6frag_high_thresh",
640 .data = &init_net.ipv6.frags.high_thresh, 639 .data = &init_net.ipv6.frags.high_thresh,
641 .maxlen = sizeof(int), 640 .maxlen = sizeof(int),
@@ -643,7 +642,6 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = {
643 .proc_handler = proc_dointvec 642 .proc_handler = proc_dointvec
644 }, 643 },
645 { 644 {
646 .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH,
647 .procname = "ip6frag_low_thresh", 645 .procname = "ip6frag_low_thresh",
648 .data = &init_net.ipv6.frags.low_thresh, 646 .data = &init_net.ipv6.frags.low_thresh,
649 .maxlen = sizeof(int), 647 .maxlen = sizeof(int),
@@ -651,26 +649,22 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = {
651 .proc_handler = proc_dointvec 649 .proc_handler = proc_dointvec
652 }, 650 },
653 { 651 {
654 .ctl_name = NET_IPV6_IP6FRAG_TIME,
655 .procname = "ip6frag_time", 652 .procname = "ip6frag_time",
656 .data = &init_net.ipv6.frags.timeout, 653 .data = &init_net.ipv6.frags.timeout,
657 .maxlen = sizeof(int), 654 .maxlen = sizeof(int),
658 .mode = 0644, 655 .mode = 0644,
659 .proc_handler = proc_dointvec_jiffies, 656 .proc_handler = proc_dointvec_jiffies,
660 .strategy = sysctl_jiffies,
661 }, 657 },
662 { } 658 { }
663}; 659};
664 660
665static struct ctl_table ip6_frags_ctl_table[] = { 661static struct ctl_table ip6_frags_ctl_table[] = {
666 { 662 {
667 .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL,
668 .procname = "ip6frag_secret_interval", 663 .procname = "ip6frag_secret_interval",
669 .data = &ip6_frags.secret_interval, 664 .data = &ip6_frags.secret_interval,
670 .maxlen = sizeof(int), 665 .maxlen = sizeof(int),
671 .mode = 0644, 666 .mode = 0644,
672 .proc_handler = proc_dointvec_jiffies, 667 .proc_handler = proc_dointvec_jiffies,
673 .strategy = sysctl_jiffies
674 }, 668 },
675 { } 669 { }
676}; 670};
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index df9432a46ffc..db3b27303890 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2547,7 +2547,6 @@ ctl_table ipv6_route_table_template[] = {
2547 .proc_handler = ipv6_sysctl_rtcache_flush 2547 .proc_handler = ipv6_sysctl_rtcache_flush
2548 }, 2548 },
2549 { 2549 {
2550 .ctl_name = NET_IPV6_ROUTE_GC_THRESH,
2551 .procname = "gc_thresh", 2550 .procname = "gc_thresh",
2552 .data = &ip6_dst_ops_template.gc_thresh, 2551 .data = &ip6_dst_ops_template.gc_thresh,
2553 .maxlen = sizeof(int), 2552 .maxlen = sizeof(int),
@@ -2555,7 +2554,6 @@ ctl_table ipv6_route_table_template[] = {
2555 .proc_handler = proc_dointvec, 2554 .proc_handler = proc_dointvec,
2556 }, 2555 },
2557 { 2556 {
2558 .ctl_name = NET_IPV6_ROUTE_MAX_SIZE,
2559 .procname = "max_size", 2557 .procname = "max_size",
2560 .data = &init_net.ipv6.sysctl.ip6_rt_max_size, 2558 .data = &init_net.ipv6.sysctl.ip6_rt_max_size,
2561 .maxlen = sizeof(int), 2559 .maxlen = sizeof(int),
@@ -2563,69 +2561,55 @@ ctl_table ipv6_route_table_template[] = {
2563 .proc_handler = proc_dointvec, 2561 .proc_handler = proc_dointvec,
2564 }, 2562 },
2565 { 2563 {
2566 .ctl_name = NET_IPV6_ROUTE_GC_MIN_INTERVAL,
2567 .procname = "gc_min_interval", 2564 .procname = "gc_min_interval",
2568 .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval, 2565 .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
2569 .maxlen = sizeof(int), 2566 .maxlen = sizeof(int),
2570 .mode = 0644, 2567 .mode = 0644,
2571 .proc_handler = proc_dointvec_jiffies, 2568 .proc_handler = proc_dointvec_jiffies,
2572 .strategy = sysctl_jiffies,
2573 }, 2569 },
2574 { 2570 {
2575 .ctl_name = NET_IPV6_ROUTE_GC_TIMEOUT,
2576 .procname = "gc_timeout", 2571 .procname = "gc_timeout",
2577 .data = &init_net.ipv6.sysctl.ip6_rt_gc_timeout, 2572 .data = &init_net.ipv6.sysctl.ip6_rt_gc_timeout,
2578 .maxlen = sizeof(int), 2573 .maxlen = sizeof(int),
2579 .mode = 0644, 2574 .mode = 0644,
2580 .proc_handler = proc_dointvec_jiffies, 2575 .proc_handler = proc_dointvec_jiffies,
2581 .strategy = sysctl_jiffies,
2582 }, 2576 },
2583 { 2577 {
2584 .ctl_name = NET_IPV6_ROUTE_GC_INTERVAL,
2585 .procname = "gc_interval", 2578 .procname = "gc_interval",
2586 .data = &init_net.ipv6.sysctl.ip6_rt_gc_interval, 2579 .data = &init_net.ipv6.sysctl.ip6_rt_gc_interval,
2587 .maxlen = sizeof(int), 2580 .maxlen = sizeof(int),
2588 .mode = 0644, 2581 .mode = 0644,
2589 .proc_handler = proc_dointvec_jiffies, 2582 .proc_handler = proc_dointvec_jiffies,
2590 .strategy = sysctl_jiffies,
2591 }, 2583 },
2592 { 2584 {
2593 .ctl_name = NET_IPV6_ROUTE_GC_ELASTICITY,
2594 .procname = "gc_elasticity", 2585 .procname = "gc_elasticity",
2595 .data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity, 2586 .data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
2596 .maxlen = sizeof(int), 2587 .maxlen = sizeof(int),
2597 .mode = 0644, 2588 .mode = 0644,
2598 .proc_handler = proc_dointvec_jiffies, 2589 .proc_handler = proc_dointvec_jiffies,
2599 .strategy = sysctl_jiffies,
2600 }, 2590 },
2601 { 2591 {
2602 .ctl_name = NET_IPV6_ROUTE_MTU_EXPIRES,
2603 .procname = "mtu_expires", 2592 .procname = "mtu_expires",
2604 .data = &init_net.ipv6.sysctl.ip6_rt_mtu_expires, 2593 .data = &init_net.ipv6.sysctl.ip6_rt_mtu_expires,
2605 .maxlen = sizeof(int), 2594 .maxlen = sizeof(int),
2606 .mode = 0644, 2595 .mode = 0644,
2607 .proc_handler = proc_dointvec_jiffies, 2596 .proc_handler = proc_dointvec_jiffies,
2608 .strategy = sysctl_jiffies,
2609 }, 2597 },
2610 { 2598 {
2611 .ctl_name = NET_IPV6_ROUTE_MIN_ADVMSS,
2612 .procname = "min_adv_mss", 2599 .procname = "min_adv_mss",
2613 .data = &init_net.ipv6.sysctl.ip6_rt_min_advmss, 2600 .data = &init_net.ipv6.sysctl.ip6_rt_min_advmss,
2614 .maxlen = sizeof(int), 2601 .maxlen = sizeof(int),
2615 .mode = 0644, 2602 .mode = 0644,
2616 .proc_handler = proc_dointvec_jiffies, 2603 .proc_handler = proc_dointvec_jiffies,
2617 .strategy = sysctl_jiffies,
2618 }, 2604 },
2619 { 2605 {
2620 .ctl_name = NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
2621 .procname = "gc_min_interval_ms", 2606 .procname = "gc_min_interval_ms",
2622 .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval, 2607 .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
2623 .maxlen = sizeof(int), 2608 .maxlen = sizeof(int),
2624 .mode = 0644, 2609 .mode = 0644,
2625 .proc_handler = proc_dointvec_ms_jiffies, 2610 .proc_handler = proc_dointvec_ms_jiffies,
2626 .strategy = sysctl_ms_jiffies,
2627 }, 2611 },
2628 { .ctl_name = 0 } 2612 { }
2629}; 2613};
2630 2614
2631struct ctl_table *ipv6_route_sysctl_init(struct net *net) 2615struct ctl_table *ipv6_route_sysctl_init(struct net *net)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 0dc6a4e5ed4a..c690736885b4 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -16,45 +16,41 @@
16 16
17static ctl_table ipv6_table_template[] = { 17static ctl_table ipv6_table_template[] = {
18 { 18 {
19 .ctl_name = NET_IPV6_ROUTE,
20 .procname = "route", 19 .procname = "route",
21 .maxlen = 0, 20 .maxlen = 0,
22 .mode = 0555, 21 .mode = 0555,
23 .child = ipv6_route_table_template 22 .child = ipv6_route_table_template
24 }, 23 },
25 { 24 {
26 .ctl_name = NET_IPV6_ICMP,
27 .procname = "icmp", 25 .procname = "icmp",
28 .maxlen = 0, 26 .maxlen = 0,
29 .mode = 0555, 27 .mode = 0555,
30 .child = ipv6_icmp_table_template 28 .child = ipv6_icmp_table_template
31 }, 29 },
32 { 30 {
33 .ctl_name = NET_IPV6_BINDV6ONLY,
34 .procname = "bindv6only", 31 .procname = "bindv6only",
35 .data = &init_net.ipv6.sysctl.bindv6only, 32 .data = &init_net.ipv6.sysctl.bindv6only,
36 .maxlen = sizeof(int), 33 .maxlen = sizeof(int),
37 .mode = 0644, 34 .mode = 0644,
38 .proc_handler = proc_dointvec 35 .proc_handler = proc_dointvec
39 }, 36 },
40 { .ctl_name = 0 } 37 { }
41}; 38};
42 39
43static ctl_table ipv6_rotable[] = { 40static ctl_table ipv6_rotable[] = {
44 { 41 {
45 .ctl_name = NET_IPV6_MLD_MAX_MSF,
46 .procname = "mld_max_msf", 42 .procname = "mld_max_msf",
47 .data = &sysctl_mld_max_msf, 43 .data = &sysctl_mld_max_msf,
48 .maxlen = sizeof(int), 44 .maxlen = sizeof(int),
49 .mode = 0644, 45 .mode = 0644,
50 .proc_handler = proc_dointvec 46 .proc_handler = proc_dointvec
51 }, 47 },
52 { .ctl_name = 0 } 48 { }
53}; 49};
54 50
55struct ctl_path net_ipv6_ctl_path[] = { 51struct ctl_path net_ipv6_ctl_path[] = {
56 { .procname = "net", .ctl_name = CTL_NET, }, 52 { .procname = "net", },
57 { .procname = "ipv6", .ctl_name = NET_IPV6, }, 53 { .procname = "ipv6", },
58 { }, 54 { },
59}; 55};
60EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); 56EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8ec3d45cd1d9..7254e3f899a7 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -309,7 +309,6 @@ static void xfrm6_policy_fini(void)
309#ifdef CONFIG_SYSCTL 309#ifdef CONFIG_SYSCTL
310static struct ctl_table xfrm6_policy_table[] = { 310static struct ctl_table xfrm6_policy_table[] = {
311 { 311 {
312 .ctl_name = CTL_UNNUMBERED,
313 .procname = "xfrm6_gc_thresh", 312 .procname = "xfrm6_gc_thresh",
314 .data = &xfrm6_dst_ops.gc_thresh, 313 .data = &xfrm6_dst_ops.gc_thresh,
315 .maxlen = sizeof(int), 314 .maxlen = sizeof(int),
diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c
index 633fcab35580..bd6dca00fb85 100644
--- a/net/ipx/sysctl_net_ipx.c
+++ b/net/ipx/sysctl_net_ipx.c
@@ -18,19 +18,18 @@ extern int sysctl_ipx_pprop_broadcasting;
18 18
19static struct ctl_table ipx_table[] = { 19static struct ctl_table ipx_table[] = {
20 { 20 {
21 .ctl_name = NET_IPX_PPROP_BROADCASTING,
22 .procname = "ipx_pprop_broadcasting", 21 .procname = "ipx_pprop_broadcasting",
23 .data = &sysctl_ipx_pprop_broadcasting, 22 .data = &sysctl_ipx_pprop_broadcasting,
24 .maxlen = sizeof(int), 23 .maxlen = sizeof(int),
25 .mode = 0644, 24 .mode = 0644,
26 .proc_handler = proc_dointvec, 25 .proc_handler = proc_dointvec,
27 }, 26 },
28 { 0 }, 27 { },
29}; 28};
30 29
31static struct ctl_path ipx_path[] = { 30static struct ctl_path ipx_path[] = {
32 { .procname = "net", .ctl_name = CTL_NET, }, 31 { .procname = "net", },
33 { .procname = "ipx", .ctl_name = NET_IPX, }, 32 { .procname = "ipx", },
34 { } 33 { }
35}; 34};
36 35
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 5c86567e5a78..d0b70dadf73b 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -113,26 +113,21 @@ static int do_discovery(ctl_table *table, int write,
113/* One file */ 113/* One file */
114static ctl_table irda_table[] = { 114static ctl_table irda_table[] = {
115 { 115 {
116 .ctl_name = NET_IRDA_DISCOVERY,
117 .procname = "discovery", 116 .procname = "discovery",
118 .data = &sysctl_discovery, 117 .data = &sysctl_discovery,
119 .maxlen = sizeof(int), 118 .maxlen = sizeof(int),
120 .mode = 0644, 119 .mode = 0644,
121 .proc_handler = do_discovery, 120 .proc_handler = do_discovery,
122 .strategy = sysctl_intvec
123 }, 121 },
124 { 122 {
125 .ctl_name = NET_IRDA_DEVNAME,
126 .procname = "devname", 123 .procname = "devname",
127 .data = sysctl_devname, 124 .data = sysctl_devname,
128 .maxlen = 65, 125 .maxlen = 65,
129 .mode = 0644, 126 .mode = 0644,
130 .proc_handler = do_devname, 127 .proc_handler = do_devname,
131 .strategy = sysctl_string
132 }, 128 },
133#ifdef CONFIG_IRDA_DEBUG 129#ifdef CONFIG_IRDA_DEBUG
134 { 130 {
135 .ctl_name = NET_IRDA_DEBUG,
136 .procname = "debug", 131 .procname = "debug",
137 .data = &irda_debug, 132 .data = &irda_debug,
138 .maxlen = sizeof(int), 133 .maxlen = sizeof(int),
@@ -142,7 +137,6 @@ static ctl_table irda_table[] = {
142#endif 137#endif
143#ifdef CONFIG_IRDA_FAST_RR 138#ifdef CONFIG_IRDA_FAST_RR
144 { 139 {
145 .ctl_name = NET_IRDA_FAST_POLL,
146 .procname = "fast_poll_increase", 140 .procname = "fast_poll_increase",
147 .data = &sysctl_fast_poll_increase, 141 .data = &sysctl_fast_poll_increase,
148 .maxlen = sizeof(int), 142 .maxlen = sizeof(int),
@@ -151,18 +145,15 @@ static ctl_table irda_table[] = {
151 }, 145 },
152#endif 146#endif
153 { 147 {
154 .ctl_name = NET_IRDA_DISCOVERY_SLOTS,
155 .procname = "discovery_slots", 148 .procname = "discovery_slots",
156 .data = &sysctl_discovery_slots, 149 .data = &sysctl_discovery_slots,
157 .maxlen = sizeof(int), 150 .maxlen = sizeof(int),
158 .mode = 0644, 151 .mode = 0644,
159 .proc_handler = proc_dointvec_minmax, 152 .proc_handler = proc_dointvec_minmax,
160 .strategy = sysctl_intvec,
161 .extra1 = &min_discovery_slots, 153 .extra1 = &min_discovery_slots,
162 .extra2 = &max_discovery_slots 154 .extra2 = &max_discovery_slots
163 }, 155 },
164 { 156 {
165 .ctl_name = NET_IRDA_DISCOVERY_TIMEOUT,
166 .procname = "discovery_timeout", 157 .procname = "discovery_timeout",
167 .data = &sysctl_discovery_timeout, 158 .data = &sysctl_discovery_timeout,
168 .maxlen = sizeof(int), 159 .maxlen = sizeof(int),
@@ -170,99 +161,83 @@ static ctl_table irda_table[] = {
170 .proc_handler = proc_dointvec 161 .proc_handler = proc_dointvec
171 }, 162 },
172 { 163 {
173 .ctl_name = NET_IRDA_SLOT_TIMEOUT,
174 .procname = "slot_timeout", 164 .procname = "slot_timeout",
175 .data = &sysctl_slot_timeout, 165 .data = &sysctl_slot_timeout,
176 .maxlen = sizeof(int), 166 .maxlen = sizeof(int),
177 .mode = 0644, 167 .mode = 0644,
178 .proc_handler = proc_dointvec_minmax, 168 .proc_handler = proc_dointvec_minmax,
179 .strategy = sysctl_intvec,
180 .extra1 = &min_slot_timeout, 169 .extra1 = &min_slot_timeout,
181 .extra2 = &max_slot_timeout 170 .extra2 = &max_slot_timeout
182 }, 171 },
183 { 172 {
184 .ctl_name = NET_IRDA_MAX_BAUD_RATE,
185 .procname = "max_baud_rate", 173 .procname = "max_baud_rate",
186 .data = &sysctl_max_baud_rate, 174 .data = &sysctl_max_baud_rate,
187 .maxlen = sizeof(int), 175 .maxlen = sizeof(int),
188 .mode = 0644, 176 .mode = 0644,
189 .proc_handler = proc_dointvec_minmax, 177 .proc_handler = proc_dointvec_minmax,
190 .strategy = sysctl_intvec,
191 .extra1 = &min_max_baud_rate, 178 .extra1 = &min_max_baud_rate,
192 .extra2 = &max_max_baud_rate 179 .extra2 = &max_max_baud_rate
193 }, 180 },
194 { 181 {
195 .ctl_name = NET_IRDA_MIN_TX_TURN_TIME,
196 .procname = "min_tx_turn_time", 182 .procname = "min_tx_turn_time",
197 .data = &sysctl_min_tx_turn_time, 183 .data = &sysctl_min_tx_turn_time,
198 .maxlen = sizeof(int), 184 .maxlen = sizeof(int),
199 .mode = 0644, 185 .mode = 0644,
200 .proc_handler = proc_dointvec_minmax, 186 .proc_handler = proc_dointvec_minmax,
201 .strategy = sysctl_intvec,
202 .extra1 = &min_min_tx_turn_time, 187 .extra1 = &min_min_tx_turn_time,
203 .extra2 = &max_min_tx_turn_time 188 .extra2 = &max_min_tx_turn_time
204 }, 189 },
205 { 190 {
206 .ctl_name = NET_IRDA_MAX_TX_DATA_SIZE,
207 .procname = "max_tx_data_size", 191 .procname = "max_tx_data_size",
208 .data = &sysctl_max_tx_data_size, 192 .data = &sysctl_max_tx_data_size,
209 .maxlen = sizeof(int), 193 .maxlen = sizeof(int),
210 .mode = 0644, 194 .mode = 0644,
211 .proc_handler = proc_dointvec_minmax, 195 .proc_handler = proc_dointvec_minmax,
212 .strategy = sysctl_intvec,
213 .extra1 = &min_max_tx_data_size, 196 .extra1 = &min_max_tx_data_size,
214 .extra2 = &max_max_tx_data_size 197 .extra2 = &max_max_tx_data_size
215 }, 198 },
216 { 199 {
217 .ctl_name = NET_IRDA_MAX_TX_WINDOW,
218 .procname = "max_tx_window", 200 .procname = "max_tx_window",
219 .data = &sysctl_max_tx_window, 201 .data = &sysctl_max_tx_window,
220 .maxlen = sizeof(int), 202 .maxlen = sizeof(int),
221 .mode = 0644, 203 .mode = 0644,
222 .proc_handler = proc_dointvec_minmax, 204 .proc_handler = proc_dointvec_minmax,
223 .strategy = sysctl_intvec,
224 .extra1 = &min_max_tx_window, 205 .extra1 = &min_max_tx_window,
225 .extra2 = &max_max_tx_window 206 .extra2 = &max_max_tx_window
226 }, 207 },
227 { 208 {
228 .ctl_name = NET_IRDA_MAX_NOREPLY_TIME,
229 .procname = "max_noreply_time", 209 .procname = "max_noreply_time",
230 .data = &sysctl_max_noreply_time, 210 .data = &sysctl_max_noreply_time,
231 .maxlen = sizeof(int), 211 .maxlen = sizeof(int),
232 .mode = 0644, 212 .mode = 0644,
233 .proc_handler = proc_dointvec_minmax, 213 .proc_handler = proc_dointvec_minmax,
234 .strategy = sysctl_intvec,
235 .extra1 = &min_max_noreply_time, 214 .extra1 = &min_max_noreply_time,
236 .extra2 = &max_max_noreply_time 215 .extra2 = &max_max_noreply_time
237 }, 216 },
238 { 217 {
239 .ctl_name = NET_IRDA_WARN_NOREPLY_TIME,
240 .procname = "warn_noreply_time", 218 .procname = "warn_noreply_time",
241 .data = &sysctl_warn_noreply_time, 219 .data = &sysctl_warn_noreply_time,
242 .maxlen = sizeof(int), 220 .maxlen = sizeof(int),
243 .mode = 0644, 221 .mode = 0644,
244 .proc_handler = proc_dointvec_minmax, 222 .proc_handler = proc_dointvec_minmax,
245 .strategy = sysctl_intvec,
246 .extra1 = &min_warn_noreply_time, 223 .extra1 = &min_warn_noreply_time,
247 .extra2 = &max_warn_noreply_time 224 .extra2 = &max_warn_noreply_time
248 }, 225 },
249 { 226 {
250 .ctl_name = NET_IRDA_LAP_KEEPALIVE_TIME,
251 .procname = "lap_keepalive_time", 227 .procname = "lap_keepalive_time",
252 .data = &sysctl_lap_keepalive_time, 228 .data = &sysctl_lap_keepalive_time,
253 .maxlen = sizeof(int), 229 .maxlen = sizeof(int),
254 .mode = 0644, 230 .mode = 0644,
255 .proc_handler = proc_dointvec_minmax, 231 .proc_handler = proc_dointvec_minmax,
256 .strategy = sysctl_intvec,
257 .extra1 = &min_lap_keepalive_time, 232 .extra1 = &min_lap_keepalive_time,
258 .extra2 = &max_lap_keepalive_time 233 .extra2 = &max_lap_keepalive_time
259 }, 234 },
260 { .ctl_name = 0 } 235 { }
261}; 236};
262 237
263static struct ctl_path irda_path[] = { 238static struct ctl_path irda_path[] = {
264 { .procname = "net", .ctl_name = CTL_NET, }, 239 { .procname = "net", },
265 { .procname = "irda", .ctl_name = NET_IRDA, }, 240 { .procname = "irda", },
266 { } 241 { }
267}; 242};
268 243
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c
index 57b9304d444c..e2ebe3586263 100644
--- a/net/llc/sysctl_net_llc.c
+++ b/net/llc/sysctl_net_llc.c
@@ -15,86 +15,73 @@
15 15
16static struct ctl_table llc2_timeout_table[] = { 16static struct ctl_table llc2_timeout_table[] = {
17 { 17 {
18 .ctl_name = NET_LLC2_ACK_TIMEOUT,
19 .procname = "ack", 18 .procname = "ack",
20 .data = &sysctl_llc2_ack_timeout, 19 .data = &sysctl_llc2_ack_timeout,
21 .maxlen = sizeof(long), 20 .maxlen = sizeof(long),
22 .mode = 0644, 21 .mode = 0644,
23 .proc_handler = proc_dointvec_jiffies, 22 .proc_handler = proc_dointvec_jiffies,
24 .strategy = sysctl_jiffies,
25 }, 23 },
26 { 24 {
27 .ctl_name = NET_LLC2_BUSY_TIMEOUT,
28 .procname = "busy", 25 .procname = "busy",
29 .data = &sysctl_llc2_busy_timeout, 26 .data = &sysctl_llc2_busy_timeout,
30 .maxlen = sizeof(long), 27 .maxlen = sizeof(long),
31 .mode = 0644, 28 .mode = 0644,
32 .proc_handler = proc_dointvec_jiffies, 29 .proc_handler = proc_dointvec_jiffies,
33 .strategy = sysctl_jiffies,
34 }, 30 },
35 { 31 {
36 .ctl_name = NET_LLC2_P_TIMEOUT,
37 .procname = "p", 32 .procname = "p",
38 .data = &sysctl_llc2_p_timeout, 33 .data = &sysctl_llc2_p_timeout,
39 .maxlen = sizeof(long), 34 .maxlen = sizeof(long),
40 .mode = 0644, 35 .mode = 0644,
41 .proc_handler = proc_dointvec_jiffies, 36 .proc_handler = proc_dointvec_jiffies,
42 .strategy = sysctl_jiffies,
43 }, 37 },
44 { 38 {
45 .ctl_name = NET_LLC2_REJ_TIMEOUT,
46 .procname = "rej", 39 .procname = "rej",
47 .data = &sysctl_llc2_rej_timeout, 40 .data = &sysctl_llc2_rej_timeout,
48 .maxlen = sizeof(long), 41 .maxlen = sizeof(long),
49 .mode = 0644, 42 .mode = 0644,
50 .proc_handler = proc_dointvec_jiffies, 43 .proc_handler = proc_dointvec_jiffies,
51 .strategy = sysctl_jiffies,
52 }, 44 },
53 { 0 }, 45 { },
54}; 46};
55 47
56static struct ctl_table llc_station_table[] = { 48static struct ctl_table llc_station_table[] = {
57 { 49 {
58 .ctl_name = NET_LLC_STATION_ACK_TIMEOUT,
59 .procname = "ack_timeout", 50 .procname = "ack_timeout",
60 .data = &sysctl_llc_station_ack_timeout, 51 .data = &sysctl_llc_station_ack_timeout,
61 .maxlen = sizeof(long), 52 .maxlen = sizeof(long),
62 .mode = 0644, 53 .mode = 0644,
63 .proc_handler = proc_dointvec_jiffies, 54 .proc_handler = proc_dointvec_jiffies,
64 .strategy = sysctl_jiffies,
65 }, 55 },
66 { 0 }, 56 { },
67}; 57};
68 58
69static struct ctl_table llc2_dir_timeout_table[] = { 59static struct ctl_table llc2_dir_timeout_table[] = {
70 { 60 {
71 .ctl_name = NET_LLC2,
72 .procname = "timeout", 61 .procname = "timeout",
73 .mode = 0555, 62 .mode = 0555,
74 .child = llc2_timeout_table, 63 .child = llc2_timeout_table,
75 }, 64 },
76 { 0 }, 65 { },
77}; 66};
78 67
79static struct ctl_table llc_table[] = { 68static struct ctl_table llc_table[] = {
80 { 69 {
81 .ctl_name = NET_LLC2,
82 .procname = "llc2", 70 .procname = "llc2",
83 .mode = 0555, 71 .mode = 0555,
84 .child = llc2_dir_timeout_table, 72 .child = llc2_dir_timeout_table,
85 }, 73 },
86 { 74 {
87 .ctl_name = NET_LLC_STATION,
88 .procname = "station", 75 .procname = "station",
89 .mode = 0555, 76 .mode = 0555,
90 .child = llc_station_table, 77 .child = llc_station_table,
91 }, 78 },
92 { 0 }, 79 { },
93}; 80};
94 81
95static struct ctl_path llc_path[] = { 82static struct ctl_path llc_path[] = {
96 { .procname = "net", .ctl_name = CTL_NET, }, 83 { .procname = "net", },
97 { .procname = "llc", .ctl_name = NET_LLC, }, 84 { .procname = "llc", },
98 { } 85 { }
99}; 86};
100 87
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 5bb34737501f..60ec4e4badaa 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -273,8 +273,8 @@ void __init netfilter_init(void)
273 273
274#ifdef CONFIG_SYSCTL 274#ifdef CONFIG_SYSCTL
275struct ctl_path nf_net_netfilter_sysctl_path[] = { 275struct ctl_path nf_net_netfilter_sysctl_path[] = {
276 { .procname = "net", .ctl_name = CTL_NET, }, 276 { .procname = "net", },
277 { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, 277 { .procname = "netfilter", },
278 { } 278 { }
279}; 279};
280EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path); 280EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 446e9bd4b4bc..e55a6861d26f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1706,12 +1706,12 @@ static struct ctl_table vs_vars[] = {
1706 .mode = 0644, 1706 .mode = 0644,
1707 .proc_handler = proc_dointvec, 1707 .proc_handler = proc_dointvec,
1708 }, 1708 },
1709 { .ctl_name = 0 } 1709 { }
1710}; 1710};
1711 1711
1712const struct ctl_path net_vs_ctl_path[] = { 1712const struct ctl_path net_vs_ctl_path[] = {
1713 { .procname = "net", .ctl_name = CTL_NET, }, 1713 { .procname = "net", },
1714 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 1714 { .procname = "ipv4", },
1715 { .procname = "vs", }, 1715 { .procname = "vs", },
1716 { } 1716 { }
1717}; 1717};
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index c1757f3620cd..1b9370db2305 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -121,7 +121,7 @@ static ctl_table vs_vars_table[] = {
121 .mode = 0644, 121 .mode = 0644,
122 .proc_handler = proc_dointvec_jiffies, 122 .proc_handler = proc_dointvec_jiffies,
123 }, 123 },
124 { .ctl_name = 0 } 124 { }
125}; 125};
126 126
127static struct ctl_table_header * sysctl_header; 127static struct ctl_table_header * sysctl_header;
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 715b57f9540d..f7476b95ab46 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -302,7 +302,7 @@ static ctl_table vs_vars_table[] = {
302 .mode = 0644, 302 .mode = 0644,
303 .proc_handler = proc_dointvec_jiffies, 303 .proc_handler = proc_dointvec_jiffies,
304 }, 304 },
305 { .ctl_name = 0 } 305 { }
306}; 306};
307 307
308static struct ctl_table_header * sysctl_header; 308static struct ctl_table_header * sysctl_header;
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 4a1d94aac20b..018f90db511c 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -30,7 +30,6 @@ MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
30#ifdef CONFIG_SYSCTL 30#ifdef CONFIG_SYSCTL
31static struct ctl_table acct_sysctl_table[] = { 31static struct ctl_table acct_sysctl_table[] = {
32 { 32 {
33 .ctl_name = CTL_UNNUMBERED,
34 .procname = "nf_conntrack_acct", 33 .procname = "nf_conntrack_acct",
35 .data = &init_net.ct.sysctl_acct, 34 .data = &init_net.ct.sysctl_acct,
36 .maxlen = sizeof(unsigned int), 35 .maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index aee560b4768d..d5a9bcd7d61b 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -151,7 +151,6 @@ static int nf_ct_events_retry_timeout __read_mostly = 15*HZ;
151#ifdef CONFIG_SYSCTL 151#ifdef CONFIG_SYSCTL
152static struct ctl_table event_sysctl_table[] = { 152static struct ctl_table event_sysctl_table[] = {
153 { 153 {
154 .ctl_name = CTL_UNNUMBERED,
155 .procname = "nf_conntrack_events", 154 .procname = "nf_conntrack_events",
156 .data = &init_net.ct.sysctl_events, 155 .data = &init_net.ct.sysctl_events,
157 .maxlen = sizeof(unsigned int), 156 .maxlen = sizeof(unsigned int),
@@ -159,7 +158,6 @@ static struct ctl_table event_sysctl_table[] = {
159 .proc_handler = proc_dointvec, 158 .proc_handler = proc_dointvec,
160 }, 159 },
161 { 160 {
162 .ctl_name = CTL_UNNUMBERED,
163 .procname = "nf_conntrack_events_retry_timeout", 161 .procname = "nf_conntrack_events_retry_timeout",
164 .data = &init_net.ct.sysctl_events_retry_timeout, 162 .data = &init_net.ct.sysctl_events_retry_timeout,
165 .maxlen = sizeof(unsigned int), 163 .maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 98916ef26f5d..dd375500dccc 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -703,64 +703,54 @@ static int dccp_nlattr_size(void)
703/* template, data assigned later */ 703/* template, data assigned later */
704static struct ctl_table dccp_sysctl_table[] = { 704static struct ctl_table dccp_sysctl_table[] = {
705 { 705 {
706 .ctl_name = CTL_UNNUMBERED,
707 .procname = "nf_conntrack_dccp_timeout_request", 706 .procname = "nf_conntrack_dccp_timeout_request",
708 .maxlen = sizeof(unsigned int), 707 .maxlen = sizeof(unsigned int),
709 .mode = 0644, 708 .mode = 0644,
710 .proc_handler = proc_dointvec_jiffies, 709 .proc_handler = proc_dointvec_jiffies,
711 }, 710 },
712 { 711 {
713 .ctl_name = CTL_UNNUMBERED,
714 .procname = "nf_conntrack_dccp_timeout_respond", 712 .procname = "nf_conntrack_dccp_timeout_respond",
715 .maxlen = sizeof(unsigned int), 713 .maxlen = sizeof(unsigned int),
716 .mode = 0644, 714 .mode = 0644,
717 .proc_handler = proc_dointvec_jiffies, 715 .proc_handler = proc_dointvec_jiffies,
718 }, 716 },
719 { 717 {
720 .ctl_name = CTL_UNNUMBERED,
721 .procname = "nf_conntrack_dccp_timeout_partopen", 718 .procname = "nf_conntrack_dccp_timeout_partopen",
722 .maxlen = sizeof(unsigned int), 719 .maxlen = sizeof(unsigned int),
723 .mode = 0644, 720 .mode = 0644,
724 .proc_handler = proc_dointvec_jiffies, 721 .proc_handler = proc_dointvec_jiffies,
725 }, 722 },
726 { 723 {
727 .ctl_name = CTL_UNNUMBERED,
728 .procname = "nf_conntrack_dccp_timeout_open", 724 .procname = "nf_conntrack_dccp_timeout_open",
729 .maxlen = sizeof(unsigned int), 725 .maxlen = sizeof(unsigned int),
730 .mode = 0644, 726 .mode = 0644,
731 .proc_handler = proc_dointvec_jiffies, 727 .proc_handler = proc_dointvec_jiffies,
732 }, 728 },
733 { 729 {
734 .ctl_name = CTL_UNNUMBERED,
735 .procname = "nf_conntrack_dccp_timeout_closereq", 730 .procname = "nf_conntrack_dccp_timeout_closereq",
736 .maxlen = sizeof(unsigned int), 731 .maxlen = sizeof(unsigned int),
737 .mode = 0644, 732 .mode = 0644,
738 .proc_handler = proc_dointvec_jiffies, 733 .proc_handler = proc_dointvec_jiffies,
739 }, 734 },
740 { 735 {
741 .ctl_name = CTL_UNNUMBERED,
742 .procname = "nf_conntrack_dccp_timeout_closing", 736 .procname = "nf_conntrack_dccp_timeout_closing",
743 .maxlen = sizeof(unsigned int), 737 .maxlen = sizeof(unsigned int),
744 .mode = 0644, 738 .mode = 0644,
745 .proc_handler = proc_dointvec_jiffies, 739 .proc_handler = proc_dointvec_jiffies,
746 }, 740 },
747 { 741 {
748 .ctl_name = CTL_UNNUMBERED,
749 .procname = "nf_conntrack_dccp_timeout_timewait", 742 .procname = "nf_conntrack_dccp_timeout_timewait",
750 .maxlen = sizeof(unsigned int), 743 .maxlen = sizeof(unsigned int),
751 .mode = 0644, 744 .mode = 0644,
752 .proc_handler = proc_dointvec_jiffies, 745 .proc_handler = proc_dointvec_jiffies,
753 }, 746 },
754 { 747 {
755 .ctl_name = CTL_UNNUMBERED,
756 .procname = "nf_conntrack_dccp_loose", 748 .procname = "nf_conntrack_dccp_loose",
757 .maxlen = sizeof(int), 749 .maxlen = sizeof(int),
758 .mode = 0644, 750 .mode = 0644,
759 .proc_handler = proc_dointvec, 751 .proc_handler = proc_dointvec,
760 }, 752 },
761 { 753 { }
762 .ctl_name = 0,
763 }
764}; 754};
765#endif /* CONFIG_SYSCTL */ 755#endif /* CONFIG_SYSCTL */
766 756
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 829374f426c4..e2091d0c7a2f 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -69,9 +69,7 @@ static struct ctl_table generic_sysctl_table[] = {
69 .mode = 0644, 69 .mode = 0644,
70 .proc_handler = proc_dointvec_jiffies, 70 .proc_handler = proc_dointvec_jiffies,
71 }, 71 },
72 { 72 { }
73 .ctl_name = 0
74 }
75}; 73};
76#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 74#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
77static struct ctl_table generic_compat_sysctl_table[] = { 75static struct ctl_table generic_compat_sysctl_table[] = {
@@ -82,9 +80,7 @@ static struct ctl_table generic_compat_sysctl_table[] = {
82 .mode = 0644, 80 .mode = 0644,
83 .proc_handler = proc_dointvec_jiffies, 81 .proc_handler = proc_dointvec_jiffies,
84 }, 82 },
85 { 83 { }
86 .ctl_name = 0
87 }
88}; 84};
89#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 85#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
90#endif /* CONFIG_SYSCTL */ 86#endif /* CONFIG_SYSCTL */
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index c10e6f36e31e..f9d930f80276 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -595,9 +595,7 @@ static struct ctl_table sctp_sysctl_table[] = {
595 .mode = 0644, 595 .mode = 0644,
596 .proc_handler = proc_dointvec_jiffies, 596 .proc_handler = proc_dointvec_jiffies,
597 }, 597 },
598 { 598 { }
599 .ctl_name = 0
600 }
601}; 599};
602 600
603#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 601#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
@@ -651,9 +649,7 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
651 .mode = 0644, 649 .mode = 0644,
652 .proc_handler = proc_dointvec_jiffies, 650 .proc_handler = proc_dointvec_jiffies,
653 }, 651 },
654 { 652 { }
655 .ctl_name = 0
656 }
657}; 653};
658#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 654#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
659#endif 655#endif
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 37a8c74be619..3c96437b45ad 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1322,7 +1322,6 @@ static struct ctl_table tcp_sysctl_table[] = {
1322 .proc_handler = proc_dointvec_jiffies, 1322 .proc_handler = proc_dointvec_jiffies,
1323 }, 1323 },
1324 { 1324 {
1325 .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE,
1326 .procname = "nf_conntrack_tcp_loose", 1325 .procname = "nf_conntrack_tcp_loose",
1327 .data = &nf_ct_tcp_loose, 1326 .data = &nf_ct_tcp_loose,
1328 .maxlen = sizeof(unsigned int), 1327 .maxlen = sizeof(unsigned int),
@@ -1330,7 +1329,6 @@ static struct ctl_table tcp_sysctl_table[] = {
1330 .proc_handler = proc_dointvec, 1329 .proc_handler = proc_dointvec,
1331 }, 1330 },
1332 { 1331 {
1333 .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL,
1334 .procname = "nf_conntrack_tcp_be_liberal", 1332 .procname = "nf_conntrack_tcp_be_liberal",
1335 .data = &nf_ct_tcp_be_liberal, 1333 .data = &nf_ct_tcp_be_liberal,
1336 .maxlen = sizeof(unsigned int), 1334 .maxlen = sizeof(unsigned int),
@@ -1338,16 +1336,13 @@ static struct ctl_table tcp_sysctl_table[] = {
1338 .proc_handler = proc_dointvec, 1336 .proc_handler = proc_dointvec,
1339 }, 1337 },
1340 { 1338 {
1341 .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS,
1342 .procname = "nf_conntrack_tcp_max_retrans", 1339 .procname = "nf_conntrack_tcp_max_retrans",
1343 .data = &nf_ct_tcp_max_retrans, 1340 .data = &nf_ct_tcp_max_retrans,
1344 .maxlen = sizeof(unsigned int), 1341 .maxlen = sizeof(unsigned int),
1345 .mode = 0644, 1342 .mode = 0644,
1346 .proc_handler = proc_dointvec, 1343 .proc_handler = proc_dointvec,
1347 }, 1344 },
1348 { 1345 { }
1349 .ctl_name = 0
1350 }
1351}; 1346};
1352 1347
1353#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 1348#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
@@ -1423,7 +1418,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
1423 .proc_handler = proc_dointvec_jiffies, 1418 .proc_handler = proc_dointvec_jiffies,
1424 }, 1419 },
1425 { 1420 {
1426 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
1427 .procname = "ip_conntrack_tcp_loose", 1421 .procname = "ip_conntrack_tcp_loose",
1428 .data = &nf_ct_tcp_loose, 1422 .data = &nf_ct_tcp_loose,
1429 .maxlen = sizeof(unsigned int), 1423 .maxlen = sizeof(unsigned int),
@@ -1431,7 +1425,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
1431 .proc_handler = proc_dointvec, 1425 .proc_handler = proc_dointvec,
1432 }, 1426 },
1433 { 1427 {
1434 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
1435 .procname = "ip_conntrack_tcp_be_liberal", 1428 .procname = "ip_conntrack_tcp_be_liberal",
1436 .data = &nf_ct_tcp_be_liberal, 1429 .data = &nf_ct_tcp_be_liberal,
1437 .maxlen = sizeof(unsigned int), 1430 .maxlen = sizeof(unsigned int),
@@ -1439,16 +1432,13 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
1439 .proc_handler = proc_dointvec, 1432 .proc_handler = proc_dointvec,
1440 }, 1433 },
1441 { 1434 {
1442 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
1443 .procname = "ip_conntrack_tcp_max_retrans", 1435 .procname = "ip_conntrack_tcp_max_retrans",
1444 .data = &nf_ct_tcp_max_retrans, 1436 .data = &nf_ct_tcp_max_retrans,
1445 .maxlen = sizeof(unsigned int), 1437 .maxlen = sizeof(unsigned int),
1446 .mode = 0644, 1438 .mode = 0644,
1447 .proc_handler = proc_dointvec, 1439 .proc_handler = proc_dointvec,
1448 }, 1440 },
1449 { 1441 { }
1450 .ctl_name = 0
1451 }
1452}; 1442};
1453#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 1443#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
1454#endif /* CONFIG_SYSCTL */ 1444#endif /* CONFIG_SYSCTL */
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 70809d117b91..5c5518bedb4b 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -154,9 +154,7 @@ static struct ctl_table udp_sysctl_table[] = {
154 .mode = 0644, 154 .mode = 0644,
155 .proc_handler = proc_dointvec_jiffies, 155 .proc_handler = proc_dointvec_jiffies,
156 }, 156 },
157 { 157 { }
158 .ctl_name = 0
159 }
160}; 158};
161#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 159#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
162static struct ctl_table udp_compat_sysctl_table[] = { 160static struct ctl_table udp_compat_sysctl_table[] = {
@@ -174,9 +172,7 @@ static struct ctl_table udp_compat_sysctl_table[] = {
174 .mode = 0644, 172 .mode = 0644,
175 .proc_handler = proc_dointvec_jiffies, 173 .proc_handler = proc_dointvec_jiffies,
176 }, 174 },
177 { 175 { }
178 .ctl_name = 0
179 }
180}; 176};
181#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 177#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
182#endif /* CONFIG_SYSCTL */ 178#endif /* CONFIG_SYSCTL */
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 0badedc542d3..458655bb2106 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -146,7 +146,6 @@ static unsigned int udplite_sysctl_table_users;
146static struct ctl_table_header *udplite_sysctl_header; 146static struct ctl_table_header *udplite_sysctl_header;
147static struct ctl_table udplite_sysctl_table[] = { 147static struct ctl_table udplite_sysctl_table[] = {
148 { 148 {
149 .ctl_name = CTL_UNNUMBERED,
150 .procname = "nf_conntrack_udplite_timeout", 149 .procname = "nf_conntrack_udplite_timeout",
151 .data = &nf_ct_udplite_timeout, 150 .data = &nf_ct_udplite_timeout,
152 .maxlen = sizeof(unsigned int), 151 .maxlen = sizeof(unsigned int),
@@ -154,16 +153,13 @@ static struct ctl_table udplite_sysctl_table[] = {
154 .proc_handler = proc_dointvec_jiffies, 153 .proc_handler = proc_dointvec_jiffies,
155 }, 154 },
156 { 155 {
157 .ctl_name = CTL_UNNUMBERED,
158 .procname = "nf_conntrack_udplite_timeout_stream", 156 .procname = "nf_conntrack_udplite_timeout_stream",
159 .data = &nf_ct_udplite_timeout_stream, 157 .data = &nf_ct_udplite_timeout_stream,
160 .maxlen = sizeof(unsigned int), 158 .maxlen = sizeof(unsigned int),
161 .mode = 0644, 159 .mode = 0644,
162 .proc_handler = proc_dointvec_jiffies, 160 .proc_handler = proc_dointvec_jiffies,
163 }, 161 },
164 { 162 { }
165 .ctl_name = 0
166 }
167}; 163};
168#endif /* CONFIG_SYSCTL */ 164#endif /* CONFIG_SYSCTL */
169 165
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 193515381970..028aba667ef7 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -340,7 +340,6 @@ static struct ctl_table_header *nf_ct_netfilter_header;
340 340
341static ctl_table nf_ct_sysctl_table[] = { 341static ctl_table nf_ct_sysctl_table[] = {
342 { 342 {
343 .ctl_name = NET_NF_CONNTRACK_MAX,
344 .procname = "nf_conntrack_max", 343 .procname = "nf_conntrack_max",
345 .data = &nf_conntrack_max, 344 .data = &nf_conntrack_max,
346 .maxlen = sizeof(int), 345 .maxlen = sizeof(int),
@@ -348,7 +347,6 @@ static ctl_table nf_ct_sysctl_table[] = {
348 .proc_handler = proc_dointvec, 347 .proc_handler = proc_dointvec,
349 }, 348 },
350 { 349 {
351 .ctl_name = NET_NF_CONNTRACK_COUNT,
352 .procname = "nf_conntrack_count", 350 .procname = "nf_conntrack_count",
353 .data = &init_net.ct.count, 351 .data = &init_net.ct.count,
354 .maxlen = sizeof(int), 352 .maxlen = sizeof(int),
@@ -356,7 +354,6 @@ static ctl_table nf_ct_sysctl_table[] = {
356 .proc_handler = proc_dointvec, 354 .proc_handler = proc_dointvec,
357 }, 355 },
358 { 356 {
359 .ctl_name = NET_NF_CONNTRACK_BUCKETS,
360 .procname = "nf_conntrack_buckets", 357 .procname = "nf_conntrack_buckets",
361 .data = &nf_conntrack_htable_size, 358 .data = &nf_conntrack_htable_size,
362 .maxlen = sizeof(unsigned int), 359 .maxlen = sizeof(unsigned int),
@@ -364,7 +361,6 @@ static ctl_table nf_ct_sysctl_table[] = {
364 .proc_handler = proc_dointvec, 361 .proc_handler = proc_dointvec,
365 }, 362 },
366 { 363 {
367 .ctl_name = NET_NF_CONNTRACK_CHECKSUM,
368 .procname = "nf_conntrack_checksum", 364 .procname = "nf_conntrack_checksum",
369 .data = &init_net.ct.sysctl_checksum, 365 .data = &init_net.ct.sysctl_checksum,
370 .maxlen = sizeof(unsigned int), 366 .maxlen = sizeof(unsigned int),
@@ -372,43 +368,39 @@ static ctl_table nf_ct_sysctl_table[] = {
372 .proc_handler = proc_dointvec, 368 .proc_handler = proc_dointvec,
373 }, 369 },
374 { 370 {
375 .ctl_name = NET_NF_CONNTRACK_LOG_INVALID,
376 .procname = "nf_conntrack_log_invalid", 371 .procname = "nf_conntrack_log_invalid",
377 .data = &init_net.ct.sysctl_log_invalid, 372 .data = &init_net.ct.sysctl_log_invalid,
378 .maxlen = sizeof(unsigned int), 373 .maxlen = sizeof(unsigned int),
379 .mode = 0644, 374 .mode = 0644,
380 .proc_handler = proc_dointvec_minmax, 375 .proc_handler = proc_dointvec_minmax,
381 .strategy = sysctl_intvec,
382 .extra1 = &log_invalid_proto_min, 376 .extra1 = &log_invalid_proto_min,
383 .extra2 = &log_invalid_proto_max, 377 .extra2 = &log_invalid_proto_max,
384 }, 378 },
385 { 379 {
386 .ctl_name = CTL_UNNUMBERED,
387 .procname = "nf_conntrack_expect_max", 380 .procname = "nf_conntrack_expect_max",
388 .data = &nf_ct_expect_max, 381 .data = &nf_ct_expect_max,
389 .maxlen = sizeof(int), 382 .maxlen = sizeof(int),
390 .mode = 0644, 383 .mode = 0644,
391 .proc_handler = proc_dointvec, 384 .proc_handler = proc_dointvec,
392 }, 385 },
393 { .ctl_name = 0 } 386 { }
394}; 387};
395 388
396#define NET_NF_CONNTRACK_MAX 2089 389#define NET_NF_CONNTRACK_MAX 2089
397 390
398static ctl_table nf_ct_netfilter_table[] = { 391static ctl_table nf_ct_netfilter_table[] = {
399 { 392 {
400 .ctl_name = NET_NF_CONNTRACK_MAX,
401 .procname = "nf_conntrack_max", 393 .procname = "nf_conntrack_max",
402 .data = &nf_conntrack_max, 394 .data = &nf_conntrack_max,
403 .maxlen = sizeof(int), 395 .maxlen = sizeof(int),
404 .mode = 0644, 396 .mode = 0644,
405 .proc_handler = proc_dointvec, 397 .proc_handler = proc_dointvec,
406 }, 398 },
407 { .ctl_name = 0 } 399 { }
408}; 400};
409 401
410static struct ctl_path nf_ct_path[] = { 402static struct ctl_path nf_ct_path[] = {
411 { .procname = "net", .ctl_name = CTL_NET, }, 403 { .procname = "net", },
412 { } 404 { }
413}; 405};
414 406
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index d65d3481919c..015725a5cd50 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -208,9 +208,9 @@ static const struct file_operations nflog_file_ops = {
208 208
209#ifdef CONFIG_SYSCTL 209#ifdef CONFIG_SYSCTL
210static struct ctl_path nf_log_sysctl_path[] = { 210static struct ctl_path nf_log_sysctl_path[] = {
211 { .procname = "net", .ctl_name = CTL_NET, }, 211 { .procname = "net", },
212 { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, 212 { .procname = "netfilter", },
213 { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, }, 213 { .procname = "nf_log", },
214 { } 214 { }
215}; 215};
216 216
@@ -265,7 +265,6 @@ static __init int netfilter_log_sysctl_init(void)
265 265
266 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { 266 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
267 snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); 267 snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i);
268 nf_log_sysctl_table[i].ctl_name = CTL_UNNUMBERED;
269 nf_log_sysctl_table[i].procname = 268 nf_log_sysctl_table[i].procname =
270 nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; 269 nf_log_sysctl_fnames[i-NFPROTO_UNSPEC];
271 nf_log_sysctl_table[i].data = NULL; 270 nf_log_sysctl_table[i].data = NULL;
diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c
index 7b49591fe87c..1e0fa9e57aac 100644
--- a/net/netrom/sysctl_net_netrom.c
+++ b/net/netrom/sysctl_net_netrom.c
@@ -36,143 +36,119 @@ static struct ctl_table_header *nr_table_header;
36 36
37static ctl_table nr_table[] = { 37static ctl_table nr_table[] = {
38 { 38 {
39 .ctl_name = NET_NETROM_DEFAULT_PATH_QUALITY,
40 .procname = "default_path_quality", 39 .procname = "default_path_quality",
41 .data = &sysctl_netrom_default_path_quality, 40 .data = &sysctl_netrom_default_path_quality,
42 .maxlen = sizeof(int), 41 .maxlen = sizeof(int),
43 .mode = 0644, 42 .mode = 0644,
44 .proc_handler = proc_dointvec_minmax, 43 .proc_handler = proc_dointvec_minmax,
45 .strategy = sysctl_intvec,
46 .extra1 = &min_quality, 44 .extra1 = &min_quality,
47 .extra2 = &max_quality 45 .extra2 = &max_quality
48 }, 46 },
49 { 47 {
50 .ctl_name = NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER,
51 .procname = "obsolescence_count_initialiser", 48 .procname = "obsolescence_count_initialiser",
52 .data = &sysctl_netrom_obsolescence_count_initialiser, 49 .data = &sysctl_netrom_obsolescence_count_initialiser,
53 .maxlen = sizeof(int), 50 .maxlen = sizeof(int),
54 .mode = 0644, 51 .mode = 0644,
55 .proc_handler = proc_dointvec_minmax, 52 .proc_handler = proc_dointvec_minmax,
56 .strategy = sysctl_intvec,
57 .extra1 = &min_obs, 53 .extra1 = &min_obs,
58 .extra2 = &max_obs 54 .extra2 = &max_obs
59 }, 55 },
60 { 56 {
61 .ctl_name = NET_NETROM_NETWORK_TTL_INITIALISER,
62 .procname = "network_ttl_initialiser", 57 .procname = "network_ttl_initialiser",
63 .data = &sysctl_netrom_network_ttl_initialiser, 58 .data = &sysctl_netrom_network_ttl_initialiser,
64 .maxlen = sizeof(int), 59 .maxlen = sizeof(int),
65 .mode = 0644, 60 .mode = 0644,
66 .proc_handler = proc_dointvec_minmax, 61 .proc_handler = proc_dointvec_minmax,
67 .strategy = sysctl_intvec,
68 .extra1 = &min_ttl, 62 .extra1 = &min_ttl,
69 .extra2 = &max_ttl 63 .extra2 = &max_ttl
70 }, 64 },
71 { 65 {
72 .ctl_name = NET_NETROM_TRANSPORT_TIMEOUT,
73 .procname = "transport_timeout", 66 .procname = "transport_timeout",
74 .data = &sysctl_netrom_transport_timeout, 67 .data = &sysctl_netrom_transport_timeout,
75 .maxlen = sizeof(int), 68 .maxlen = sizeof(int),
76 .mode = 0644, 69 .mode = 0644,
77 .proc_handler = proc_dointvec_minmax, 70 .proc_handler = proc_dointvec_minmax,
78 .strategy = sysctl_intvec,
79 .extra1 = &min_t1, 71 .extra1 = &min_t1,
80 .extra2 = &max_t1 72 .extra2 = &max_t1
81 }, 73 },
82 { 74 {
83 .ctl_name = NET_NETROM_TRANSPORT_MAXIMUM_TRIES,
84 .procname = "transport_maximum_tries", 75 .procname = "transport_maximum_tries",
85 .data = &sysctl_netrom_transport_maximum_tries, 76 .data = &sysctl_netrom_transport_maximum_tries,
86 .maxlen = sizeof(int), 77 .maxlen = sizeof(int),
87 .mode = 0644, 78 .mode = 0644,
88 .proc_handler = proc_dointvec_minmax, 79 .proc_handler = proc_dointvec_minmax,
89 .strategy = sysctl_intvec,
90 .extra1 = &min_n2, 80 .extra1 = &min_n2,
91 .extra2 = &max_n2 81 .extra2 = &max_n2
92 }, 82 },
93 { 83 {
94 .ctl_name = NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY,
95 .procname = "transport_acknowledge_delay", 84 .procname = "transport_acknowledge_delay",
96 .data = &sysctl_netrom_transport_acknowledge_delay, 85 .data = &sysctl_netrom_transport_acknowledge_delay,
97 .maxlen = sizeof(int), 86 .maxlen = sizeof(int),
98 .mode = 0644, 87 .mode = 0644,
99 .proc_handler = proc_dointvec_minmax, 88 .proc_handler = proc_dointvec_minmax,
100 .strategy = sysctl_intvec,
101 .extra1 = &min_t2, 89 .extra1 = &min_t2,
102 .extra2 = &max_t2 90 .extra2 = &max_t2
103 }, 91 },
104 { 92 {
105 .ctl_name = NET_NETROM_TRANSPORT_BUSY_DELAY,
106 .procname = "transport_busy_delay", 93 .procname = "transport_busy_delay",
107 .data = &sysctl_netrom_transport_busy_delay, 94 .data = &sysctl_netrom_transport_busy_delay,
108 .maxlen = sizeof(int), 95 .maxlen = sizeof(int),
109 .mode = 0644, 96 .mode = 0644,
110 .proc_handler = proc_dointvec_minmax, 97 .proc_handler = proc_dointvec_minmax,
111 .strategy = sysctl_intvec,
112 .extra1 = &min_t4, 98 .extra1 = &min_t4,
113 .extra2 = &max_t4 99 .extra2 = &max_t4
114 }, 100 },
115 { 101 {
116 .ctl_name = NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE,
117 .procname = "transport_requested_window_size", 102 .procname = "transport_requested_window_size",
118 .data = &sysctl_netrom_transport_requested_window_size, 103 .data = &sysctl_netrom_transport_requested_window_size,
119 .maxlen = sizeof(int), 104 .maxlen = sizeof(int),
120 .mode = 0644, 105 .mode = 0644,
121 .proc_handler = proc_dointvec_minmax, 106 .proc_handler = proc_dointvec_minmax,
122 .strategy = sysctl_intvec,
123 .extra1 = &min_window, 107 .extra1 = &min_window,
124 .extra2 = &max_window 108 .extra2 = &max_window
125 }, 109 },
126 { 110 {
127 .ctl_name = NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT,
128 .procname = "transport_no_activity_timeout", 111 .procname = "transport_no_activity_timeout",
129 .data = &sysctl_netrom_transport_no_activity_timeout, 112 .data = &sysctl_netrom_transport_no_activity_timeout,
130 .maxlen = sizeof(int), 113 .maxlen = sizeof(int),
131 .mode = 0644, 114 .mode = 0644,
132 .proc_handler = proc_dointvec_minmax, 115 .proc_handler = proc_dointvec_minmax,
133 .strategy = sysctl_intvec,
134 .extra1 = &min_idle, 116 .extra1 = &min_idle,
135 .extra2 = &max_idle 117 .extra2 = &max_idle
136 }, 118 },
137 { 119 {
138 .ctl_name = NET_NETROM_ROUTING_CONTROL,
139 .procname = "routing_control", 120 .procname = "routing_control",
140 .data = &sysctl_netrom_routing_control, 121 .data = &sysctl_netrom_routing_control,
141 .maxlen = sizeof(int), 122 .maxlen = sizeof(int),
142 .mode = 0644, 123 .mode = 0644,
143 .proc_handler = proc_dointvec_minmax, 124 .proc_handler = proc_dointvec_minmax,
144 .strategy = sysctl_intvec,
145 .extra1 = &min_route, 125 .extra1 = &min_route,
146 .extra2 = &max_route 126 .extra2 = &max_route
147 }, 127 },
148 { 128 {
149 .ctl_name = NET_NETROM_LINK_FAILS_COUNT,
150 .procname = "link_fails_count", 129 .procname = "link_fails_count",
151 .data = &sysctl_netrom_link_fails_count, 130 .data = &sysctl_netrom_link_fails_count,
152 .maxlen = sizeof(int), 131 .maxlen = sizeof(int),
153 .mode = 0644, 132 .mode = 0644,
154 .proc_handler = proc_dointvec_minmax, 133 .proc_handler = proc_dointvec_minmax,
155 .strategy = sysctl_intvec,
156 .extra1 = &min_fails, 134 .extra1 = &min_fails,
157 .extra2 = &max_fails 135 .extra2 = &max_fails
158 }, 136 },
159 { 137 {
160 .ctl_name = NET_NETROM_RESET,
161 .procname = "reset", 138 .procname = "reset",
162 .data = &sysctl_netrom_reset_circuit, 139 .data = &sysctl_netrom_reset_circuit,
163 .maxlen = sizeof(int), 140 .maxlen = sizeof(int),
164 .mode = 0644, 141 .mode = 0644,
165 .proc_handler = proc_dointvec_minmax, 142 .proc_handler = proc_dointvec_minmax,
166 .strategy = sysctl_intvec,
167 .extra1 = &min_reset, 143 .extra1 = &min_reset,
168 .extra2 = &max_reset 144 .extra2 = &max_reset
169 }, 145 },
170 { .ctl_name = 0 } 146 { }
171}; 147};
172 148
173static struct ctl_path nr_path[] = { 149static struct ctl_path nr_path[] = {
174 { .procname = "net", .ctl_name = CTL_NET, }, 150 { .procname = "net", },
175 { .procname = "netrom", .ctl_name = NET_NETROM, }, 151 { .procname = "netrom", },
176 { } 152 { }
177}; 153};
178 154
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c
index 2220f3322326..cea1c7dbdae2 100644
--- a/net/phonet/sysctl.c
+++ b/net/phonet/sysctl.c
@@ -84,20 +84,18 @@ static int proc_local_port_range(ctl_table *table, int write,
84 84
85static struct ctl_table phonet_table[] = { 85static struct ctl_table phonet_table[] = {
86 { 86 {
87 .ctl_name = CTL_UNNUMBERED,
88 .procname = "local_port_range", 87 .procname = "local_port_range",
89 .data = &local_port_range, 88 .data = &local_port_range,
90 .maxlen = sizeof(local_port_range), 89 .maxlen = sizeof(local_port_range),
91 .mode = 0644, 90 .mode = 0644,
92 .proc_handler = proc_local_port_range, 91 .proc_handler = proc_local_port_range,
93 .strategy = NULL,
94 }, 92 },
95 { .ctl_name = 0 } 93 { }
96}; 94};
97 95
98static struct ctl_path phonet_ctl_path[] = { 96static struct ctl_path phonet_ctl_path[] = {
99 { .procname = "net", .ctl_name = CTL_NET, }, 97 { .procname = "net", },
100 { .procname = "phonet", .ctl_name = CTL_UNNUMBERED, }, 98 { .procname = "phonet", },
101 { }, 99 { },
102}; 100};
103 101
diff --git a/net/rds/ib_sysctl.c b/net/rds/ib_sysctl.c
index 84b5ffcb280f..03f01cb4e0fe 100644
--- a/net/rds/ib_sysctl.c
+++ b/net/rds/ib_sysctl.c
@@ -67,68 +67,62 @@ unsigned int rds_ib_sysctl_flow_control = 0;
67 67
68ctl_table rds_ib_sysctl_table[] = { 68ctl_table rds_ib_sysctl_table[] = {
69 { 69 {
70 .ctl_name = CTL_UNNUMBERED,
71 .procname = "max_send_wr", 70 .procname = "max_send_wr",
72 .data = &rds_ib_sysctl_max_send_wr, 71 .data = &rds_ib_sysctl_max_send_wr,
73 .maxlen = sizeof(unsigned long), 72 .maxlen = sizeof(unsigned long),
74 .mode = 0644, 73 .mode = 0644,
75 .proc_handler = &proc_doulongvec_minmax, 74 .proc_handler = proc_doulongvec_minmax,
76 .extra1 = &rds_ib_sysctl_max_wr_min, 75 .extra1 = &rds_ib_sysctl_max_wr_min,
77 .extra2 = &rds_ib_sysctl_max_wr_max, 76 .extra2 = &rds_ib_sysctl_max_wr_max,
78 }, 77 },
79 { 78 {
80 .ctl_name = CTL_UNNUMBERED,
81 .procname = "max_recv_wr", 79 .procname = "max_recv_wr",
82 .data = &rds_ib_sysctl_max_recv_wr, 80 .data = &rds_ib_sysctl_max_recv_wr,
83 .maxlen = sizeof(unsigned long), 81 .maxlen = sizeof(unsigned long),
84 .mode = 0644, 82 .mode = 0644,
85 .proc_handler = &proc_doulongvec_minmax, 83 .proc_handler = proc_doulongvec_minmax,
86 .extra1 = &rds_ib_sysctl_max_wr_min, 84 .extra1 = &rds_ib_sysctl_max_wr_min,
87 .extra2 = &rds_ib_sysctl_max_wr_max, 85 .extra2 = &rds_ib_sysctl_max_wr_max,
88 }, 86 },
89 { 87 {
90 .ctl_name = CTL_UNNUMBERED,
91 .procname = "max_unsignaled_wr", 88 .procname = "max_unsignaled_wr",
92 .data = &rds_ib_sysctl_max_unsig_wrs, 89 .data = &rds_ib_sysctl_max_unsig_wrs,
93 .maxlen = sizeof(unsigned long), 90 .maxlen = sizeof(unsigned long),
94 .mode = 0644, 91 .mode = 0644,
95 .proc_handler = &proc_doulongvec_minmax, 92 .proc_handler = proc_doulongvec_minmax,
96 .extra1 = &rds_ib_sysctl_max_unsig_wr_min, 93 .extra1 = &rds_ib_sysctl_max_unsig_wr_min,
97 .extra2 = &rds_ib_sysctl_max_unsig_wr_max, 94 .extra2 = &rds_ib_sysctl_max_unsig_wr_max,
98 }, 95 },
99 { 96 {
100 .ctl_name = CTL_UNNUMBERED,
101 .procname = "max_unsignaled_bytes", 97 .procname = "max_unsignaled_bytes",
102 .data = &rds_ib_sysctl_max_unsig_bytes, 98 .data = &rds_ib_sysctl_max_unsig_bytes,
103 .maxlen = sizeof(unsigned long), 99 .maxlen = sizeof(unsigned long),
104 .mode = 0644, 100 .mode = 0644,
105 .proc_handler = &proc_doulongvec_minmax, 101 .proc_handler = proc_doulongvec_minmax,
106 .extra1 = &rds_ib_sysctl_max_unsig_bytes_min, 102 .extra1 = &rds_ib_sysctl_max_unsig_bytes_min,
107 .extra2 = &rds_ib_sysctl_max_unsig_bytes_max, 103 .extra2 = &rds_ib_sysctl_max_unsig_bytes_max,
108 }, 104 },
109 { 105 {
110 .ctl_name = CTL_UNNUMBERED,
111 .procname = "max_recv_allocation", 106 .procname = "max_recv_allocation",
112 .data = &rds_ib_sysctl_max_recv_allocation, 107 .data = &rds_ib_sysctl_max_recv_allocation,
113 .maxlen = sizeof(unsigned long), 108 .maxlen = sizeof(unsigned long),
114 .mode = 0644, 109 .mode = 0644,
115 .proc_handler = &proc_doulongvec_minmax, 110 .proc_handler = proc_doulongvec_minmax,
116 }, 111 },
117 { 112 {
118 .ctl_name = CTL_UNNUMBERED,
119 .procname = "flow_control", 113 .procname = "flow_control",
120 .data = &rds_ib_sysctl_flow_control, 114 .data = &rds_ib_sysctl_flow_control,
121 .maxlen = sizeof(rds_ib_sysctl_flow_control), 115 .maxlen = sizeof(rds_ib_sysctl_flow_control),
122 .mode = 0644, 116 .mode = 0644,
123 .proc_handler = &proc_dointvec, 117 .proc_handler = proc_dointvec,
124 }, 118 },
125 { .ctl_name = 0} 119 { }
126}; 120};
127 121
128static struct ctl_path rds_ib_sysctl_path[] = { 122static struct ctl_path rds_ib_sysctl_path[] = {
129 { .procname = "net", .ctl_name = CTL_NET, }, 123 { .procname = "net", },
130 { .procname = "rds", .ctl_name = CTL_UNNUMBERED, }, 124 { .procname = "rds", },
131 { .procname = "ib", .ctl_name = CTL_UNNUMBERED, }, 125 { .procname = "ib", },
132 { } 126 { }
133}; 127};
134 128
diff --git a/net/rds/iw_sysctl.c b/net/rds/iw_sysctl.c
index 9590678cd616..1c4428a61a02 100644
--- a/net/rds/iw_sysctl.c
+++ b/net/rds/iw_sysctl.c
@@ -57,68 +57,62 @@ unsigned int rds_iw_sysctl_flow_control = 1;
57 57
58ctl_table rds_iw_sysctl_table[] = { 58ctl_table rds_iw_sysctl_table[] = {
59 { 59 {
60 .ctl_name = CTL_UNNUMBERED,
61 .procname = "max_send_wr", 60 .procname = "max_send_wr",
62 .data = &rds_iw_sysctl_max_send_wr, 61 .data = &rds_iw_sysctl_max_send_wr,
63 .maxlen = sizeof(unsigned long), 62 .maxlen = sizeof(unsigned long),
64 .mode = 0644, 63 .mode = 0644,
65 .proc_handler = &proc_doulongvec_minmax, 64 .proc_handler = proc_doulongvec_minmax,
66 .extra1 = &rds_iw_sysctl_max_wr_min, 65 .extra1 = &rds_iw_sysctl_max_wr_min,
67 .extra2 = &rds_iw_sysctl_max_wr_max, 66 .extra2 = &rds_iw_sysctl_max_wr_max,
68 }, 67 },
69 { 68 {
70 .ctl_name = CTL_UNNUMBERED,
71 .procname = "max_recv_wr", 69 .procname = "max_recv_wr",
72 .data = &rds_iw_sysctl_max_recv_wr, 70 .data = &rds_iw_sysctl_max_recv_wr,
73 .maxlen = sizeof(unsigned long), 71 .maxlen = sizeof(unsigned long),
74 .mode = 0644, 72 .mode = 0644,
75 .proc_handler = &proc_doulongvec_minmax, 73 .proc_handler = proc_doulongvec_minmax,
76 .extra1 = &rds_iw_sysctl_max_wr_min, 74 .extra1 = &rds_iw_sysctl_max_wr_min,
77 .extra2 = &rds_iw_sysctl_max_wr_max, 75 .extra2 = &rds_iw_sysctl_max_wr_max,
78 }, 76 },
79 { 77 {
80 .ctl_name = CTL_UNNUMBERED,
81 .procname = "max_unsignaled_wr", 78 .procname = "max_unsignaled_wr",
82 .data = &rds_iw_sysctl_max_unsig_wrs, 79 .data = &rds_iw_sysctl_max_unsig_wrs,
83 .maxlen = sizeof(unsigned long), 80 .maxlen = sizeof(unsigned long),
84 .mode = 0644, 81 .mode = 0644,
85 .proc_handler = &proc_doulongvec_minmax, 82 .proc_handler = proc_doulongvec_minmax,
86 .extra1 = &rds_iw_sysctl_max_unsig_wr_min, 83 .extra1 = &rds_iw_sysctl_max_unsig_wr_min,
87 .extra2 = &rds_iw_sysctl_max_unsig_wr_max, 84 .extra2 = &rds_iw_sysctl_max_unsig_wr_max,
88 }, 85 },
89 { 86 {
90 .ctl_name = CTL_UNNUMBERED,
91 .procname = "max_unsignaled_bytes", 87 .procname = "max_unsignaled_bytes",
92 .data = &rds_iw_sysctl_max_unsig_bytes, 88 .data = &rds_iw_sysctl_max_unsig_bytes,
93 .maxlen = sizeof(unsigned long), 89 .maxlen = sizeof(unsigned long),
94 .mode = 0644, 90 .mode = 0644,
95 .proc_handler = &proc_doulongvec_minmax, 91 .proc_handler = proc_doulongvec_minmax,
96 .extra1 = &rds_iw_sysctl_max_unsig_bytes_min, 92 .extra1 = &rds_iw_sysctl_max_unsig_bytes_min,
97 .extra2 = &rds_iw_sysctl_max_unsig_bytes_max, 93 .extra2 = &rds_iw_sysctl_max_unsig_bytes_max,
98 }, 94 },
99 { 95 {
100 .ctl_name = CTL_UNNUMBERED,
101 .procname = "max_recv_allocation", 96 .procname = "max_recv_allocation",
102 .data = &rds_iw_sysctl_max_recv_allocation, 97 .data = &rds_iw_sysctl_max_recv_allocation,
103 .maxlen = sizeof(unsigned long), 98 .maxlen = sizeof(unsigned long),
104 .mode = 0644, 99 .mode = 0644,
105 .proc_handler = &proc_doulongvec_minmax, 100 .proc_handler = proc_doulongvec_minmax,
106 }, 101 },
107 { 102 {
108 .ctl_name = CTL_UNNUMBERED,
109 .procname = "flow_control", 103 .procname = "flow_control",
110 .data = &rds_iw_sysctl_flow_control, 104 .data = &rds_iw_sysctl_flow_control,
111 .maxlen = sizeof(rds_iw_sysctl_flow_control), 105 .maxlen = sizeof(rds_iw_sysctl_flow_control),
112 .mode = 0644, 106 .mode = 0644,
113 .proc_handler = &proc_dointvec, 107 .proc_handler = proc_dointvec,
114 }, 108 },
115 { .ctl_name = 0} 109 { }
116}; 110};
117 111
118static struct ctl_path rds_iw_sysctl_path[] = { 112static struct ctl_path rds_iw_sysctl_path[] = {
119 { .procname = "net", .ctl_name = CTL_NET, }, 113 { .procname = "net", },
120 { .procname = "rds", .ctl_name = CTL_UNNUMBERED, }, 114 { .procname = "rds", },
121 { .procname = "iw", .ctl_name = CTL_UNNUMBERED, }, 115 { .procname = "iw", },
122 { } 116 { }
123}; 117};
124 118
diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c
index 307dc5c1be15..7829a20325d3 100644
--- a/net/rds/sysctl.c
+++ b/net/rds/sysctl.c
@@ -51,55 +51,50 @@ unsigned int rds_sysctl_ping_enable = 1;
51 51
52static ctl_table rds_sysctl_rds_table[] = { 52static ctl_table rds_sysctl_rds_table[] = {
53 { 53 {
54 .ctl_name = CTL_UNNUMBERED,
55 .procname = "reconnect_min_delay_ms", 54 .procname = "reconnect_min_delay_ms",
56 .data = &rds_sysctl_reconnect_min_jiffies, 55 .data = &rds_sysctl_reconnect_min_jiffies,
57 .maxlen = sizeof(unsigned long), 56 .maxlen = sizeof(unsigned long),
58 .mode = 0644, 57 .mode = 0644,
59 .proc_handler = &proc_doulongvec_ms_jiffies_minmax, 58 .proc_handler = proc_doulongvec_ms_jiffies_minmax,
60 .extra1 = &rds_sysctl_reconnect_min, 59 .extra1 = &rds_sysctl_reconnect_min,
61 .extra2 = &rds_sysctl_reconnect_max_jiffies, 60 .extra2 = &rds_sysctl_reconnect_max_jiffies,
62 }, 61 },
63 { 62 {
64 .ctl_name = CTL_UNNUMBERED,
65 .procname = "reconnect_max_delay_ms", 63 .procname = "reconnect_max_delay_ms",
66 .data = &rds_sysctl_reconnect_max_jiffies, 64 .data = &rds_sysctl_reconnect_max_jiffies,
67 .maxlen = sizeof(unsigned long), 65 .maxlen = sizeof(unsigned long),
68 .mode = 0644, 66 .mode = 0644,
69 .proc_handler = &proc_doulongvec_ms_jiffies_minmax, 67 .proc_handler = proc_doulongvec_ms_jiffies_minmax,
70 .extra1 = &rds_sysctl_reconnect_min_jiffies, 68 .extra1 = &rds_sysctl_reconnect_min_jiffies,
71 .extra2 = &rds_sysctl_reconnect_max, 69 .extra2 = &rds_sysctl_reconnect_max,
72 }, 70 },
73 { 71 {
74 .ctl_name = CTL_UNNUMBERED,
75 .procname = "max_unacked_packets", 72 .procname = "max_unacked_packets",
76 .data = &rds_sysctl_max_unacked_packets, 73 .data = &rds_sysctl_max_unacked_packets,
77 .maxlen = sizeof(unsigned long), 74 .maxlen = sizeof(unsigned long),
78 .mode = 0644, 75 .mode = 0644,
79 .proc_handler = &proc_dointvec, 76 .proc_handler = proc_dointvec,
80 }, 77 },
81 { 78 {
82 .ctl_name = CTL_UNNUMBERED,
83 .procname = "max_unacked_bytes", 79 .procname = "max_unacked_bytes",
84 .data = &rds_sysctl_max_unacked_bytes, 80 .data = &rds_sysctl_max_unacked_bytes,
85 .maxlen = sizeof(unsigned long), 81 .maxlen = sizeof(unsigned long),
86 .mode = 0644, 82 .mode = 0644,
87 .proc_handler = &proc_dointvec, 83 .proc_handler = proc_dointvec,
88 }, 84 },
89 { 85 {
90 .ctl_name = CTL_UNNUMBERED,
91 .procname = "ping_enable", 86 .procname = "ping_enable",
92 .data = &rds_sysctl_ping_enable, 87 .data = &rds_sysctl_ping_enable,
93 .maxlen = sizeof(int), 88 .maxlen = sizeof(int),
94 .mode = 0644, 89 .mode = 0644,
95 .proc_handler = &proc_dointvec, 90 .proc_handler = proc_dointvec,
96 }, 91 },
97 { .ctl_name = 0} 92 { }
98}; 93};
99 94
100static struct ctl_path rds_sysctl_path[] = { 95static struct ctl_path rds_sysctl_path[] = {
101 { .procname = "net", .ctl_name = CTL_NET, }, 96 { .procname = "net", },
102 { .procname = "rds", .ctl_name = CTL_UNNUMBERED, }, 97 { .procname = "rds", },
103 { } 98 { }
104}; 99};
105 100
diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c
index 3bfe504faf86..df6d9dac2186 100644
--- a/net/rose/sysctl_net_rose.c
+++ b/net/rose/sysctl_net_rose.c
@@ -26,121 +26,101 @@ static struct ctl_table_header *rose_table_header;
26 26
27static ctl_table rose_table[] = { 27static ctl_table rose_table[] = {
28 { 28 {
29 .ctl_name = NET_ROSE_RESTART_REQUEST_TIMEOUT,
30 .procname = "restart_request_timeout", 29 .procname = "restart_request_timeout",
31 .data = &sysctl_rose_restart_request_timeout, 30 .data = &sysctl_rose_restart_request_timeout,
32 .maxlen = sizeof(int), 31 .maxlen = sizeof(int),
33 .mode = 0644, 32 .mode = 0644,
34 .proc_handler = proc_dointvec_minmax, 33 .proc_handler = proc_dointvec_minmax,
35 .strategy = sysctl_intvec,
36 .extra1 = &min_timer, 34 .extra1 = &min_timer,
37 .extra2 = &max_timer 35 .extra2 = &max_timer
38 }, 36 },
39 { 37 {
40 .ctl_name = NET_ROSE_CALL_REQUEST_TIMEOUT,
41 .procname = "call_request_timeout", 38 .procname = "call_request_timeout",
42 .data = &sysctl_rose_call_request_timeout, 39 .data = &sysctl_rose_call_request_timeout,
43 .maxlen = sizeof(int), 40 .maxlen = sizeof(int),
44 .mode = 0644, 41 .mode = 0644,
45 .proc_handler = proc_dointvec_minmax, 42 .proc_handler = proc_dointvec_minmax,
46 .strategy = sysctl_intvec,
47 .extra1 = &min_timer, 43 .extra1 = &min_timer,
48 .extra2 = &max_timer 44 .extra2 = &max_timer
49 }, 45 },
50 { 46 {
51 .ctl_name = NET_ROSE_RESET_REQUEST_TIMEOUT,
52 .procname = "reset_request_timeout", 47 .procname = "reset_request_timeout",
53 .data = &sysctl_rose_reset_request_timeout, 48 .data = &sysctl_rose_reset_request_timeout,
54 .maxlen = sizeof(int), 49 .maxlen = sizeof(int),
55 .mode = 0644, 50 .mode = 0644,
56 .proc_handler = proc_dointvec_minmax, 51 .proc_handler = proc_dointvec_minmax,
57 .strategy = sysctl_intvec,
58 .extra1 = &min_timer, 52 .extra1 = &min_timer,
59 .extra2 = &max_timer 53 .extra2 = &max_timer
60 }, 54 },
61 { 55 {
62 .ctl_name = NET_ROSE_CLEAR_REQUEST_TIMEOUT,
63 .procname = "clear_request_timeout", 56 .procname = "clear_request_timeout",
64 .data = &sysctl_rose_clear_request_timeout, 57 .data = &sysctl_rose_clear_request_timeout,
65 .maxlen = sizeof(int), 58 .maxlen = sizeof(int),
66 .mode = 0644, 59 .mode = 0644,
67 .proc_handler = proc_dointvec_minmax, 60 .proc_handler = proc_dointvec_minmax,
68 .strategy = sysctl_intvec,
69 .extra1 = &min_timer, 61 .extra1 = &min_timer,
70 .extra2 = &max_timer 62 .extra2 = &max_timer
71 }, 63 },
72 { 64 {
73 .ctl_name = NET_ROSE_NO_ACTIVITY_TIMEOUT,
74 .procname = "no_activity_timeout", 65 .procname = "no_activity_timeout",
75 .data = &sysctl_rose_no_activity_timeout, 66 .data = &sysctl_rose_no_activity_timeout,
76 .maxlen = sizeof(int), 67 .maxlen = sizeof(int),
77 .mode = 0644, 68 .mode = 0644,
78 .proc_handler = proc_dointvec_minmax, 69 .proc_handler = proc_dointvec_minmax,
79 .strategy = sysctl_intvec,
80 .extra1 = &min_idle, 70 .extra1 = &min_idle,
81 .extra2 = &max_idle 71 .extra2 = &max_idle
82 }, 72 },
83 { 73 {
84 .ctl_name = NET_ROSE_ACK_HOLD_BACK_TIMEOUT,
85 .procname = "acknowledge_hold_back_timeout", 74 .procname = "acknowledge_hold_back_timeout",
86 .data = &sysctl_rose_ack_hold_back_timeout, 75 .data = &sysctl_rose_ack_hold_back_timeout,
87 .maxlen = sizeof(int), 76 .maxlen = sizeof(int),
88 .mode = 0644, 77 .mode = 0644,
89 .proc_handler = proc_dointvec_minmax, 78 .proc_handler = proc_dointvec_minmax,
90 .strategy = sysctl_intvec,
91 .extra1 = &min_timer, 79 .extra1 = &min_timer,
92 .extra2 = &max_timer 80 .extra2 = &max_timer
93 }, 81 },
94 { 82 {
95 .ctl_name = NET_ROSE_ROUTING_CONTROL,
96 .procname = "routing_control", 83 .procname = "routing_control",
97 .data = &sysctl_rose_routing_control, 84 .data = &sysctl_rose_routing_control,
98 .maxlen = sizeof(int), 85 .maxlen = sizeof(int),
99 .mode = 0644, 86 .mode = 0644,
100 .proc_handler = proc_dointvec_minmax, 87 .proc_handler = proc_dointvec_minmax,
101 .strategy = sysctl_intvec,
102 .extra1 = &min_route, 88 .extra1 = &min_route,
103 .extra2 = &max_route 89 .extra2 = &max_route
104 }, 90 },
105 { 91 {
106 .ctl_name = NET_ROSE_LINK_FAIL_TIMEOUT,
107 .procname = "link_fail_timeout", 92 .procname = "link_fail_timeout",
108 .data = &sysctl_rose_link_fail_timeout, 93 .data = &sysctl_rose_link_fail_timeout,
109 .maxlen = sizeof(int), 94 .maxlen = sizeof(int),
110 .mode = 0644, 95 .mode = 0644,
111 .proc_handler = proc_dointvec_minmax, 96 .proc_handler = proc_dointvec_minmax,
112 .strategy = sysctl_intvec,
113 .extra1 = &min_ftimer, 97 .extra1 = &min_ftimer,
114 .extra2 = &max_ftimer 98 .extra2 = &max_ftimer
115 }, 99 },
116 { 100 {
117 .ctl_name = NET_ROSE_MAX_VCS,
118 .procname = "maximum_virtual_circuits", 101 .procname = "maximum_virtual_circuits",
119 .data = &sysctl_rose_maximum_vcs, 102 .data = &sysctl_rose_maximum_vcs,
120 .maxlen = sizeof(int), 103 .maxlen = sizeof(int),
121 .mode = 0644, 104 .mode = 0644,
122 .proc_handler = proc_dointvec_minmax, 105 .proc_handler = proc_dointvec_minmax,
123 .strategy = sysctl_intvec,
124 .extra1 = &min_maxvcs, 106 .extra1 = &min_maxvcs,
125 .extra2 = &max_maxvcs 107 .extra2 = &max_maxvcs
126 }, 108 },
127 { 109 {
128 .ctl_name = NET_ROSE_WINDOW_SIZE,
129 .procname = "window_size", 110 .procname = "window_size",
130 .data = &sysctl_rose_window_size, 111 .data = &sysctl_rose_window_size,
131 .maxlen = sizeof(int), 112 .maxlen = sizeof(int),
132 .mode = 0644, 113 .mode = 0644,
133 .proc_handler = proc_dointvec_minmax, 114 .proc_handler = proc_dointvec_minmax,
134 .strategy = sysctl_intvec,
135 .extra1 = &min_window, 115 .extra1 = &min_window,
136 .extra2 = &max_window 116 .extra2 = &max_window
137 }, 117 },
138 { .ctl_name = 0 } 118 { }
139}; 119};
140 120
141static struct ctl_path rose_path[] = { 121static struct ctl_path rose_path[] = {
142 { .procname = "net", .ctl_name = CTL_NET, }, 122 { .procname = "net", },
143 { .procname = "rose", .ctl_name = NET_ROSE, }, 123 { .procname = "rose", },
144 { } 124 { }
145}; 125};
146 126
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index ae03ded2bf1a..419e1e962c55 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -60,180 +60,145 @@ extern int sysctl_sctp_wmem[3];
60 60
61static ctl_table sctp_table[] = { 61static ctl_table sctp_table[] = {
62 { 62 {
63 .ctl_name = NET_SCTP_RTO_INITIAL,
64 .procname = "rto_initial", 63 .procname = "rto_initial",
65 .data = &sctp_rto_initial, 64 .data = &sctp_rto_initial,
66 .maxlen = sizeof(unsigned int), 65 .maxlen = sizeof(unsigned int),
67 .mode = 0644, 66 .mode = 0644,
68 .proc_handler = proc_dointvec_minmax, 67 .proc_handler = proc_dointvec_minmax,
69 .strategy = sysctl_intvec,
70 .extra1 = &one, 68 .extra1 = &one,
71 .extra2 = &timer_max 69 .extra2 = &timer_max
72 }, 70 },
73 { 71 {
74 .ctl_name = NET_SCTP_RTO_MIN,
75 .procname = "rto_min", 72 .procname = "rto_min",
76 .data = &sctp_rto_min, 73 .data = &sctp_rto_min,
77 .maxlen = sizeof(unsigned int), 74 .maxlen = sizeof(unsigned int),
78 .mode = 0644, 75 .mode = 0644,
79 .proc_handler = proc_dointvec_minmax, 76 .proc_handler = proc_dointvec_minmax,
80 .strategy = sysctl_intvec,
81 .extra1 = &one, 77 .extra1 = &one,
82 .extra2 = &timer_max 78 .extra2 = &timer_max
83 }, 79 },
84 { 80 {
85 .ctl_name = NET_SCTP_RTO_MAX,
86 .procname = "rto_max", 81 .procname = "rto_max",
87 .data = &sctp_rto_max, 82 .data = &sctp_rto_max,
88 .maxlen = sizeof(unsigned int), 83 .maxlen = sizeof(unsigned int),
89 .mode = 0644, 84 .mode = 0644,
90 .proc_handler = proc_dointvec_minmax, 85 .proc_handler = proc_dointvec_minmax,
91 .strategy = sysctl_intvec,
92 .extra1 = &one, 86 .extra1 = &one,
93 .extra2 = &timer_max 87 .extra2 = &timer_max
94 }, 88 },
95 { 89 {
96 .ctl_name = NET_SCTP_VALID_COOKIE_LIFE,
97 .procname = "valid_cookie_life", 90 .procname = "valid_cookie_life",
98 .data = &sctp_valid_cookie_life, 91 .data = &sctp_valid_cookie_life,
99 .maxlen = sizeof(unsigned int), 92 .maxlen = sizeof(unsigned int),
100 .mode = 0644, 93 .mode = 0644,
101 .proc_handler = proc_dointvec_minmax, 94 .proc_handler = proc_dointvec_minmax,
102 .strategy = sysctl_intvec,
103 .extra1 = &one, 95 .extra1 = &one,
104 .extra2 = &timer_max 96 .extra2 = &timer_max
105 }, 97 },
106 { 98 {
107 .ctl_name = NET_SCTP_MAX_BURST,
108 .procname = "max_burst", 99 .procname = "max_burst",
109 .data = &sctp_max_burst, 100 .data = &sctp_max_burst,
110 .maxlen = sizeof(int), 101 .maxlen = sizeof(int),
111 .mode = 0644, 102 .mode = 0644,
112 .proc_handler = proc_dointvec_minmax, 103 .proc_handler = proc_dointvec_minmax,
113 .strategy = sysctl_intvec,
114 .extra1 = &zero, 104 .extra1 = &zero,
115 .extra2 = &int_max 105 .extra2 = &int_max
116 }, 106 },
117 { 107 {
118 .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS,
119 .procname = "association_max_retrans", 108 .procname = "association_max_retrans",
120 .data = &sctp_max_retrans_association, 109 .data = &sctp_max_retrans_association,
121 .maxlen = sizeof(int), 110 .maxlen = sizeof(int),
122 .mode = 0644, 111 .mode = 0644,
123 .proc_handler = proc_dointvec_minmax, 112 .proc_handler = proc_dointvec_minmax,
124 .strategy = sysctl_intvec,
125 .extra1 = &one, 113 .extra1 = &one,
126 .extra2 = &int_max 114 .extra2 = &int_max
127 }, 115 },
128 { 116 {
129 .ctl_name = NET_SCTP_SNDBUF_POLICY,
130 .procname = "sndbuf_policy", 117 .procname = "sndbuf_policy",
131 .data = &sctp_sndbuf_policy, 118 .data = &sctp_sndbuf_policy,
132 .maxlen = sizeof(int), 119 .maxlen = sizeof(int),
133 .mode = 0644, 120 .mode = 0644,
134 .proc_handler = proc_dointvec, 121 .proc_handler = proc_dointvec,
135 .strategy = sysctl_intvec
136 }, 122 },
137 { 123 {
138 .ctl_name = NET_SCTP_RCVBUF_POLICY,
139 .procname = "rcvbuf_policy", 124 .procname = "rcvbuf_policy",
140 .data = &sctp_rcvbuf_policy, 125 .data = &sctp_rcvbuf_policy,
141 .maxlen = sizeof(int), 126 .maxlen = sizeof(int),
142 .mode = 0644, 127 .mode = 0644,
143 .proc_handler = proc_dointvec, 128 .proc_handler = proc_dointvec,
144 .strategy = sysctl_intvec
145 }, 129 },
146 { 130 {
147 .ctl_name = NET_SCTP_PATH_MAX_RETRANS,
148 .procname = "path_max_retrans", 131 .procname = "path_max_retrans",
149 .data = &sctp_max_retrans_path, 132 .data = &sctp_max_retrans_path,
150 .maxlen = sizeof(int), 133 .maxlen = sizeof(int),
151 .mode = 0644, 134 .mode = 0644,
152 .proc_handler = proc_dointvec_minmax, 135 .proc_handler = proc_dointvec_minmax,
153 .strategy = sysctl_intvec,
154 .extra1 = &one, 136 .extra1 = &one,
155 .extra2 = &int_max 137 .extra2 = &int_max
156 }, 138 },
157 { 139 {
158 .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS,
159 .procname = "max_init_retransmits", 140 .procname = "max_init_retransmits",
160 .data = &sctp_max_retrans_init, 141 .data = &sctp_max_retrans_init,
161 .maxlen = sizeof(int), 142 .maxlen = sizeof(int),
162 .mode = 0644, 143 .mode = 0644,
163 .proc_handler = proc_dointvec_minmax, 144 .proc_handler = proc_dointvec_minmax,
164 .strategy = sysctl_intvec,
165 .extra1 = &one, 145 .extra1 = &one,
166 .extra2 = &int_max 146 .extra2 = &int_max
167 }, 147 },
168 { 148 {
169 .ctl_name = NET_SCTP_HB_INTERVAL,
170 .procname = "hb_interval", 149 .procname = "hb_interval",
171 .data = &sctp_hb_interval, 150 .data = &sctp_hb_interval,
172 .maxlen = sizeof(unsigned int), 151 .maxlen = sizeof(unsigned int),
173 .mode = 0644, 152 .mode = 0644,
174 .proc_handler = proc_dointvec_minmax, 153 .proc_handler = proc_dointvec_minmax,
175 .strategy = sysctl_intvec,
176 .extra1 = &one, 154 .extra1 = &one,
177 .extra2 = &timer_max 155 .extra2 = &timer_max
178 }, 156 },
179 { 157 {
180 .ctl_name = NET_SCTP_PRESERVE_ENABLE,
181 .procname = "cookie_preserve_enable", 158 .procname = "cookie_preserve_enable",
182 .data = &sctp_cookie_preserve_enable, 159 .data = &sctp_cookie_preserve_enable,
183 .maxlen = sizeof(int), 160 .maxlen = sizeof(int),
184 .mode = 0644, 161 .mode = 0644,
185 .proc_handler = proc_dointvec, 162 .proc_handler = proc_dointvec,
186 .strategy = sysctl_intvec
187 }, 163 },
188 { 164 {
189 .ctl_name = NET_SCTP_RTO_ALPHA,
190 .procname = "rto_alpha_exp_divisor", 165 .procname = "rto_alpha_exp_divisor",
191 .data = &sctp_rto_alpha, 166 .data = &sctp_rto_alpha,
192 .maxlen = sizeof(int), 167 .maxlen = sizeof(int),
193 .mode = 0444, 168 .mode = 0444,
194 .proc_handler = proc_dointvec, 169 .proc_handler = proc_dointvec,
195 .strategy = sysctl_intvec
196 }, 170 },
197 { 171 {
198 .ctl_name = NET_SCTP_RTO_BETA,
199 .procname = "rto_beta_exp_divisor", 172 .procname = "rto_beta_exp_divisor",
200 .data = &sctp_rto_beta, 173 .data = &sctp_rto_beta,
201 .maxlen = sizeof(int), 174 .maxlen = sizeof(int),
202 .mode = 0444, 175 .mode = 0444,
203 .proc_handler = proc_dointvec, 176 .proc_handler = proc_dointvec,
204 .strategy = sysctl_intvec
205 }, 177 },
206 { 178 {
207 .ctl_name = NET_SCTP_ADDIP_ENABLE,
208 .procname = "addip_enable", 179 .procname = "addip_enable",
209 .data = &sctp_addip_enable, 180 .data = &sctp_addip_enable,
210 .maxlen = sizeof(int), 181 .maxlen = sizeof(int),
211 .mode = 0644, 182 .mode = 0644,
212 .proc_handler = proc_dointvec, 183 .proc_handler = proc_dointvec,
213 .strategy = sysctl_intvec
214 }, 184 },
215 { 185 {
216 .ctl_name = NET_SCTP_PRSCTP_ENABLE,
217 .procname = "prsctp_enable", 186 .procname = "prsctp_enable",
218 .data = &sctp_prsctp_enable, 187 .data = &sctp_prsctp_enable,
219 .maxlen = sizeof(int), 188 .maxlen = sizeof(int),
220 .mode = 0644, 189 .mode = 0644,
221 .proc_handler = proc_dointvec, 190 .proc_handler = proc_dointvec,
222 .strategy = sysctl_intvec
223 }, 191 },
224 { 192 {
225 .ctl_name = NET_SCTP_SACK_TIMEOUT,
226 .procname = "sack_timeout", 193 .procname = "sack_timeout",
227 .data = &sctp_sack_timeout, 194 .data = &sctp_sack_timeout,
228 .maxlen = sizeof(int), 195 .maxlen = sizeof(int),
229 .mode = 0644, 196 .mode = 0644,
230 .proc_handler = proc_dointvec_minmax, 197 .proc_handler = proc_dointvec_minmax,
231 .strategy = sysctl_intvec,
232 .extra1 = &sack_timer_min, 198 .extra1 = &sack_timer_min,
233 .extra2 = &sack_timer_max, 199 .extra2 = &sack_timer_max,
234 }, 200 },
235 { 201 {
236 .ctl_name = CTL_UNNUMBERED,
237 .procname = "sctp_mem", 202 .procname = "sctp_mem",
238 .data = &sysctl_sctp_mem, 203 .data = &sysctl_sctp_mem,
239 .maxlen = sizeof(sysctl_sctp_mem), 204 .maxlen = sizeof(sysctl_sctp_mem),
@@ -241,7 +206,6 @@ static ctl_table sctp_table[] = {
241 .proc_handler = proc_dointvec, 206 .proc_handler = proc_dointvec,
242 }, 207 },
243 { 208 {
244 .ctl_name = CTL_UNNUMBERED,
245 .procname = "sctp_rmem", 209 .procname = "sctp_rmem",
246 .data = &sysctl_sctp_rmem, 210 .data = &sysctl_sctp_rmem,
247 .maxlen = sizeof(sysctl_sctp_rmem), 211 .maxlen = sizeof(sysctl_sctp_rmem),
@@ -249,7 +213,6 @@ static ctl_table sctp_table[] = {
249 .proc_handler = proc_dointvec, 213 .proc_handler = proc_dointvec,
250 }, 214 },
251 { 215 {
252 .ctl_name = CTL_UNNUMBERED,
253 .procname = "sctp_wmem", 216 .procname = "sctp_wmem",
254 .data = &sysctl_sctp_wmem, 217 .data = &sysctl_sctp_wmem,
255 .maxlen = sizeof(sysctl_sctp_wmem), 218 .maxlen = sizeof(sysctl_sctp_wmem),
@@ -257,36 +220,29 @@ static ctl_table sctp_table[] = {
257 .proc_handler = proc_dointvec, 220 .proc_handler = proc_dointvec,
258 }, 221 },
259 { 222 {
260 .ctl_name = CTL_UNNUMBERED,
261 .procname = "auth_enable", 223 .procname = "auth_enable",
262 .data = &sctp_auth_enable, 224 .data = &sctp_auth_enable,
263 .maxlen = sizeof(int), 225 .maxlen = sizeof(int),
264 .mode = 0644, 226 .mode = 0644,
265 .proc_handler = proc_dointvec, 227 .proc_handler = proc_dointvec,
266 .strategy = sysctl_intvec
267 }, 228 },
268 { 229 {
269 .ctl_name = CTL_UNNUMBERED,
270 .procname = "addip_noauth_enable", 230 .procname = "addip_noauth_enable",
271 .data = &sctp_addip_noauth, 231 .data = &sctp_addip_noauth,
272 .maxlen = sizeof(int), 232 .maxlen = sizeof(int),
273 .mode = 0644, 233 .mode = 0644,
274 .proc_handler = proc_dointvec, 234 .proc_handler = proc_dointvec,
275 .strategy = sysctl_intvec
276 }, 235 },
277 { 236 {
278 .ctl_name = CTL_UNNUMBERED,
279 .procname = "addr_scope_policy", 237 .procname = "addr_scope_policy",
280 .data = &sctp_scope_policy, 238 .data = &sctp_scope_policy,
281 .maxlen = sizeof(int), 239 .maxlen = sizeof(int),
282 .mode = 0644, 240 .mode = 0644,
283 .proc_handler = &proc_dointvec_minmax, 241 .proc_handler = proc_dointvec_minmax,
284 .strategy = &sysctl_intvec,
285 .extra1 = &zero, 242 .extra1 = &zero,
286 .extra2 = &addr_scope_max, 243 .extra2 = &addr_scope_max,
287 }, 244 },
288 { 245 {
289 .ctl_name = CTL_UNNUMBERED,
290 .procname = "rwnd_update_shift", 246 .procname = "rwnd_update_shift",
291 .data = &sctp_rwnd_upd_shift, 247 .data = &sctp_rwnd_upd_shift,
292 .maxlen = sizeof(int), 248 .maxlen = sizeof(int),
@@ -297,12 +253,12 @@ static ctl_table sctp_table[] = {
297 .extra2 = &rwnd_scale_max, 253 .extra2 = &rwnd_scale_max,
298 }, 254 },
299 255
300 { .ctl_name = 0 } 256 { /* sentinel */ }
301}; 257};
302 258
303static struct ctl_path sctp_path[] = { 259static struct ctl_path sctp_path[] = {
304 { .procname = "net", .ctl_name = CTL_NET, }, 260 { .procname = "net", },
305 { .procname = "sctp", .ctl_name = NET_SCTP, }, 261 { .procname = "sctp", },
306 { } 262 { }
307}; 263};
308 264
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 42f9748ae093..e65dcc613339 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -139,46 +139,45 @@ static ctl_table debug_table[] = {
139 .data = &rpc_debug, 139 .data = &rpc_debug,
140 .maxlen = sizeof(int), 140 .maxlen = sizeof(int),
141 .mode = 0644, 141 .mode = 0644,
142 .proc_handler = &proc_dodebug 142 .proc_handler = proc_dodebug
143 }, 143 },
144 { 144 {
145 .procname = "nfs_debug", 145 .procname = "nfs_debug",
146 .data = &nfs_debug, 146 .data = &nfs_debug,
147 .maxlen = sizeof(int), 147 .maxlen = sizeof(int),
148 .mode = 0644, 148 .mode = 0644,
149 .proc_handler = &proc_dodebug 149 .proc_handler = proc_dodebug
150 }, 150 },
151 { 151 {
152 .procname = "nfsd_debug", 152 .procname = "nfsd_debug",
153 .data = &nfsd_debug, 153 .data = &nfsd_debug,
154 .maxlen = sizeof(int), 154 .maxlen = sizeof(int),
155 .mode = 0644, 155 .mode = 0644,
156 .proc_handler = &proc_dodebug 156 .proc_handler = proc_dodebug
157 }, 157 },
158 { 158 {
159 .procname = "nlm_debug", 159 .procname = "nlm_debug",
160 .data = &nlm_debug, 160 .data = &nlm_debug,
161 .maxlen = sizeof(int), 161 .maxlen = sizeof(int),
162 .mode = 0644, 162 .mode = 0644,
163 .proc_handler = &proc_dodebug 163 .proc_handler = proc_dodebug
164 }, 164 },
165 { 165 {
166 .procname = "transports", 166 .procname = "transports",
167 .maxlen = 256, 167 .maxlen = 256,
168 .mode = 0444, 168 .mode = 0444,
169 .proc_handler = &proc_do_xprt, 169 .proc_handler = proc_do_xprt,
170 }, 170 },
171 { .ctl_name = 0 } 171 { }
172}; 172};
173 173
174static ctl_table sunrpc_table[] = { 174static ctl_table sunrpc_table[] = {
175 { 175 {
176 .ctl_name = CTL_SUNRPC,
177 .procname = "sunrpc", 176 .procname = "sunrpc",
178 .mode = 0555, 177 .mode = 0555,
179 .child = debug_table 178 .child = debug_table
180 }, 179 },
181 { .ctl_name = 0 } 180 { }
182}; 181};
183 182
184#endif 183#endif
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index 35fb68b9c8ec..5b8a8ff93a25 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -120,8 +120,7 @@ static ctl_table svcrdma_parm_table[] = {
120 .data = &svcrdma_max_requests, 120 .data = &svcrdma_max_requests,
121 .maxlen = sizeof(unsigned int), 121 .maxlen = sizeof(unsigned int),
122 .mode = 0644, 122 .mode = 0644,
123 .proc_handler = &proc_dointvec_minmax, 123 .proc_handler = proc_dointvec_minmax,
124 .strategy = &sysctl_intvec,
125 .extra1 = &min_max_requests, 124 .extra1 = &min_max_requests,
126 .extra2 = &max_max_requests 125 .extra2 = &max_max_requests
127 }, 126 },
@@ -130,8 +129,7 @@ static ctl_table svcrdma_parm_table[] = {
130 .data = &svcrdma_max_req_size, 129 .data = &svcrdma_max_req_size,
131 .maxlen = sizeof(unsigned int), 130 .maxlen = sizeof(unsigned int),
132 .mode = 0644, 131 .mode = 0644,
133 .proc_handler = &proc_dointvec_minmax, 132 .proc_handler = proc_dointvec_minmax,
134 .strategy = &sysctl_intvec,
135 .extra1 = &min_max_inline, 133 .extra1 = &min_max_inline,
136 .extra2 = &max_max_inline 134 .extra2 = &max_max_inline
137 }, 135 },
@@ -140,8 +138,7 @@ static ctl_table svcrdma_parm_table[] = {
140 .data = &svcrdma_ord, 138 .data = &svcrdma_ord,
141 .maxlen = sizeof(unsigned int), 139 .maxlen = sizeof(unsigned int),
142 .mode = 0644, 140 .mode = 0644,
143 .proc_handler = &proc_dointvec_minmax, 141 .proc_handler = proc_dointvec_minmax,
144 .strategy = &sysctl_intvec,
145 .extra1 = &min_ord, 142 .extra1 = &min_ord,
146 .extra2 = &max_ord, 143 .extra2 = &max_ord,
147 }, 144 },
@@ -151,67 +148,65 @@ static ctl_table svcrdma_parm_table[] = {
151 .data = &rdma_stat_read, 148 .data = &rdma_stat_read,
152 .maxlen = sizeof(atomic_t), 149 .maxlen = sizeof(atomic_t),
153 .mode = 0644, 150 .mode = 0644,
154 .proc_handler = &read_reset_stat, 151 .proc_handler = read_reset_stat,
155 }, 152 },
156 { 153 {
157 .procname = "rdma_stat_recv", 154 .procname = "rdma_stat_recv",
158 .data = &rdma_stat_recv, 155 .data = &rdma_stat_recv,
159 .maxlen = sizeof(atomic_t), 156 .maxlen = sizeof(atomic_t),
160 .mode = 0644, 157 .mode = 0644,
161 .proc_handler = &read_reset_stat, 158 .proc_handler = read_reset_stat,
162 }, 159 },
163 { 160 {
164 .procname = "rdma_stat_write", 161 .procname = "rdma_stat_write",
165 .data = &rdma_stat_write, 162 .data = &rdma_stat_write,
166 .maxlen = sizeof(atomic_t), 163 .maxlen = sizeof(atomic_t),
167 .mode = 0644, 164 .mode = 0644,
168 .proc_handler = &read_reset_stat, 165 .proc_handler = read_reset_stat,
169 }, 166 },
170 { 167 {
171 .procname = "rdma_stat_sq_starve", 168 .procname = "rdma_stat_sq_starve",
172 .data = &rdma_stat_sq_starve, 169 .data = &rdma_stat_sq_starve,
173 .maxlen = sizeof(atomic_t), 170 .maxlen = sizeof(atomic_t),
174 .mode = 0644, 171 .mode = 0644,
175 .proc_handler = &read_reset_stat, 172 .proc_handler = read_reset_stat,
176 }, 173 },
177 { 174 {
178 .procname = "rdma_stat_rq_starve", 175 .procname = "rdma_stat_rq_starve",
179 .data = &rdma_stat_rq_starve, 176 .data = &rdma_stat_rq_starve,
180 .maxlen = sizeof(atomic_t), 177 .maxlen = sizeof(atomic_t),
181 .mode = 0644, 178 .mode = 0644,
182 .proc_handler = &read_reset_stat, 179 .proc_handler = read_reset_stat,
183 }, 180 },
184 { 181 {
185 .procname = "rdma_stat_rq_poll", 182 .procname = "rdma_stat_rq_poll",
186 .data = &rdma_stat_rq_poll, 183 .data = &rdma_stat_rq_poll,
187 .maxlen = sizeof(atomic_t), 184 .maxlen = sizeof(atomic_t),
188 .mode = 0644, 185 .mode = 0644,
189 .proc_handler = &read_reset_stat, 186 .proc_handler = read_reset_stat,
190 }, 187 },
191 { 188 {
192 .procname = "rdma_stat_rq_prod", 189 .procname = "rdma_stat_rq_prod",
193 .data = &rdma_stat_rq_prod, 190 .data = &rdma_stat_rq_prod,
194 .maxlen = sizeof(atomic_t), 191 .maxlen = sizeof(atomic_t),
195 .mode = 0644, 192 .mode = 0644,
196 .proc_handler = &read_reset_stat, 193 .proc_handler = read_reset_stat,
197 }, 194 },
198 { 195 {
199 .procname = "rdma_stat_sq_poll", 196 .procname = "rdma_stat_sq_poll",
200 .data = &rdma_stat_sq_poll, 197 .data = &rdma_stat_sq_poll,
201 .maxlen = sizeof(atomic_t), 198 .maxlen = sizeof(atomic_t),
202 .mode = 0644, 199 .mode = 0644,
203 .proc_handler = &read_reset_stat, 200 .proc_handler = read_reset_stat,
204 }, 201 },
205 { 202 {
206 .procname = "rdma_stat_sq_prod", 203 .procname = "rdma_stat_sq_prod",
207 .data = &rdma_stat_sq_prod, 204 .data = &rdma_stat_sq_prod,
208 .maxlen = sizeof(atomic_t), 205 .maxlen = sizeof(atomic_t),
209 .mode = 0644, 206 .mode = 0644,
210 .proc_handler = &read_reset_stat, 207 .proc_handler = read_reset_stat,
211 },
212 {
213 .ctl_name = 0,
214 }, 208 },
209 { },
215}; 210};
216 211
217static ctl_table svcrdma_table[] = { 212static ctl_table svcrdma_table[] = {
@@ -220,21 +215,16 @@ static ctl_table svcrdma_table[] = {
220 .mode = 0555, 215 .mode = 0555,
221 .child = svcrdma_parm_table 216 .child = svcrdma_parm_table
222 }, 217 },
223 { 218 { },
224 .ctl_name = 0,
225 },
226}; 219};
227 220
228static ctl_table svcrdma_root_table[] = { 221static ctl_table svcrdma_root_table[] = {
229 { 222 {
230 .ctl_name = CTL_SUNRPC,
231 .procname = "sunrpc", 223 .procname = "sunrpc",
232 .mode = 0555, 224 .mode = 0555,
233 .child = svcrdma_table 225 .child = svcrdma_table
234 }, 226 },
235 { 227 { },
236 .ctl_name = 0,
237 },
238}; 228};
239 229
240void svc_rdma_cleanup(void) 230void svc_rdma_cleanup(void)
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 9a63f669ece4..7018eef1dcdd 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -86,79 +86,63 @@ static struct ctl_table_header *sunrpc_table_header;
86 86
87static ctl_table xr_tunables_table[] = { 87static ctl_table xr_tunables_table[] = {
88 { 88 {
89 .ctl_name = CTL_UNNUMBERED,
90 .procname = "rdma_slot_table_entries", 89 .procname = "rdma_slot_table_entries",
91 .data = &xprt_rdma_slot_table_entries, 90 .data = &xprt_rdma_slot_table_entries,
92 .maxlen = sizeof(unsigned int), 91 .maxlen = sizeof(unsigned int),
93 .mode = 0644, 92 .mode = 0644,
94 .proc_handler = &proc_dointvec_minmax, 93 .proc_handler = proc_dointvec_minmax,
95 .strategy = &sysctl_intvec,
96 .extra1 = &min_slot_table_size, 94 .extra1 = &min_slot_table_size,
97 .extra2 = &max_slot_table_size 95 .extra2 = &max_slot_table_size
98 }, 96 },
99 { 97 {
100 .ctl_name = CTL_UNNUMBERED,
101 .procname = "rdma_max_inline_read", 98 .procname = "rdma_max_inline_read",
102 .data = &xprt_rdma_max_inline_read, 99 .data = &xprt_rdma_max_inline_read,
103 .maxlen = sizeof(unsigned int), 100 .maxlen = sizeof(unsigned int),
104 .mode = 0644, 101 .mode = 0644,
105 .proc_handler = &proc_dointvec, 102 .proc_handler = proc_dointvec,
106 .strategy = &sysctl_intvec,
107 }, 103 },
108 { 104 {
109 .ctl_name = CTL_UNNUMBERED,
110 .procname = "rdma_max_inline_write", 105 .procname = "rdma_max_inline_write",
111 .data = &xprt_rdma_max_inline_write, 106 .data = &xprt_rdma_max_inline_write,
112 .maxlen = sizeof(unsigned int), 107 .maxlen = sizeof(unsigned int),
113 .mode = 0644, 108 .mode = 0644,
114 .proc_handler = &proc_dointvec, 109 .proc_handler = proc_dointvec,
115 .strategy = &sysctl_intvec,
116 }, 110 },
117 { 111 {
118 .ctl_name = CTL_UNNUMBERED,
119 .procname = "rdma_inline_write_padding", 112 .procname = "rdma_inline_write_padding",
120 .data = &xprt_rdma_inline_write_padding, 113 .data = &xprt_rdma_inline_write_padding,
121 .maxlen = sizeof(unsigned int), 114 .maxlen = sizeof(unsigned int),
122 .mode = 0644, 115 .mode = 0644,
123 .proc_handler = &proc_dointvec_minmax, 116 .proc_handler = proc_dointvec_minmax,
124 .strategy = &sysctl_intvec,
125 .extra1 = &zero, 117 .extra1 = &zero,
126 .extra2 = &max_padding, 118 .extra2 = &max_padding,
127 }, 119 },
128 { 120 {
129 .ctl_name = CTL_UNNUMBERED,
130 .procname = "rdma_memreg_strategy", 121 .procname = "rdma_memreg_strategy",
131 .data = &xprt_rdma_memreg_strategy, 122 .data = &xprt_rdma_memreg_strategy,
132 .maxlen = sizeof(unsigned int), 123 .maxlen = sizeof(unsigned int),
133 .mode = 0644, 124 .mode = 0644,
134 .proc_handler = &proc_dointvec_minmax, 125 .proc_handler = proc_dointvec_minmax,
135 .strategy = &sysctl_intvec,
136 .extra1 = &min_memreg, 126 .extra1 = &min_memreg,
137 .extra2 = &max_memreg, 127 .extra2 = &max_memreg,
138 }, 128 },
139 { 129 {
140 .ctl_name = CTL_UNNUMBERED,
141 .procname = "rdma_pad_optimize", 130 .procname = "rdma_pad_optimize",
142 .data = &xprt_rdma_pad_optimize, 131 .data = &xprt_rdma_pad_optimize,
143 .maxlen = sizeof(unsigned int), 132 .maxlen = sizeof(unsigned int),
144 .mode = 0644, 133 .mode = 0644,
145 .proc_handler = &proc_dointvec, 134 .proc_handler = proc_dointvec,
146 },
147 {
148 .ctl_name = 0,
149 }, 135 },
136 { },
150}; 137};
151 138
152static ctl_table sunrpc_table[] = { 139static ctl_table sunrpc_table[] = {
153 { 140 {
154 .ctl_name = CTL_SUNRPC,
155 .procname = "sunrpc", 141 .procname = "sunrpc",
156 .mode = 0555, 142 .mode = 0555,
157 .child = xr_tunables_table 143 .child = xr_tunables_table
158 }, 144 },
159 { 145 { },
160 .ctl_name = 0,
161 },
162}; 146};
163 147
164#endif 148#endif
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 37c5475ba258..04732d09013e 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -81,46 +81,38 @@ static struct ctl_table_header *sunrpc_table_header;
81 */ 81 */
82static ctl_table xs_tunables_table[] = { 82static ctl_table xs_tunables_table[] = {
83 { 83 {
84 .ctl_name = CTL_SLOTTABLE_UDP,
85 .procname = "udp_slot_table_entries", 84 .procname = "udp_slot_table_entries",
86 .data = &xprt_udp_slot_table_entries, 85 .data = &xprt_udp_slot_table_entries,
87 .maxlen = sizeof(unsigned int), 86 .maxlen = sizeof(unsigned int),
88 .mode = 0644, 87 .mode = 0644,
89 .proc_handler = &proc_dointvec_minmax, 88 .proc_handler = proc_dointvec_minmax,
90 .strategy = &sysctl_intvec,
91 .extra1 = &min_slot_table_size, 89 .extra1 = &min_slot_table_size,
92 .extra2 = &max_slot_table_size 90 .extra2 = &max_slot_table_size
93 }, 91 },
94 { 92 {
95 .ctl_name = CTL_SLOTTABLE_TCP,
96 .procname = "tcp_slot_table_entries", 93 .procname = "tcp_slot_table_entries",
97 .data = &xprt_tcp_slot_table_entries, 94 .data = &xprt_tcp_slot_table_entries,
98 .maxlen = sizeof(unsigned int), 95 .maxlen = sizeof(unsigned int),
99 .mode = 0644, 96 .mode = 0644,
100 .proc_handler = &proc_dointvec_minmax, 97 .proc_handler = proc_dointvec_minmax,
101 .strategy = &sysctl_intvec,
102 .extra1 = &min_slot_table_size, 98 .extra1 = &min_slot_table_size,
103 .extra2 = &max_slot_table_size 99 .extra2 = &max_slot_table_size
104 }, 100 },
105 { 101 {
106 .ctl_name = CTL_MIN_RESVPORT,
107 .procname = "min_resvport", 102 .procname = "min_resvport",
108 .data = &xprt_min_resvport, 103 .data = &xprt_min_resvport,
109 .maxlen = sizeof(unsigned int), 104 .maxlen = sizeof(unsigned int),
110 .mode = 0644, 105 .mode = 0644,
111 .proc_handler = &proc_dointvec_minmax, 106 .proc_handler = proc_dointvec_minmax,
112 .strategy = &sysctl_intvec,
113 .extra1 = &xprt_min_resvport_limit, 107 .extra1 = &xprt_min_resvport_limit,
114 .extra2 = &xprt_max_resvport_limit 108 .extra2 = &xprt_max_resvport_limit
115 }, 109 },
116 { 110 {
117 .ctl_name = CTL_MAX_RESVPORT,
118 .procname = "max_resvport", 111 .procname = "max_resvport",
119 .data = &xprt_max_resvport, 112 .data = &xprt_max_resvport,
120 .maxlen = sizeof(unsigned int), 113 .maxlen = sizeof(unsigned int),
121 .mode = 0644, 114 .mode = 0644,
122 .proc_handler = &proc_dointvec_minmax, 115 .proc_handler = proc_dointvec_minmax,
123 .strategy = &sysctl_intvec,
124 .extra1 = &xprt_min_resvport_limit, 116 .extra1 = &xprt_min_resvport_limit,
125 .extra2 = &xprt_max_resvport_limit 117 .extra2 = &xprt_max_resvport_limit
126 }, 118 },
@@ -129,24 +121,18 @@ static ctl_table xs_tunables_table[] = {
129 .data = &xs_tcp_fin_timeout, 121 .data = &xs_tcp_fin_timeout,
130 .maxlen = sizeof(xs_tcp_fin_timeout), 122 .maxlen = sizeof(xs_tcp_fin_timeout),
131 .mode = 0644, 123 .mode = 0644,
132 .proc_handler = &proc_dointvec_jiffies, 124 .proc_handler = proc_dointvec_jiffies,
133 .strategy = sysctl_jiffies
134 },
135 {
136 .ctl_name = 0,
137 }, 125 },
126 { },
138}; 127};
139 128
140static ctl_table sunrpc_table[] = { 129static ctl_table sunrpc_table[] = {
141 { 130 {
142 .ctl_name = CTL_SUNRPC,
143 .procname = "sunrpc", 131 .procname = "sunrpc",
144 .mode = 0555, 132 .mode = 0555,
145 .child = xs_tunables_table 133 .child = xs_tunables_table
146 }, 134 },
147 { 135 { },
148 .ctl_name = 0,
149 },
150}; 136};
151 137
152#endif 138#endif
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 83c093077ebc..708f5df6b7f0 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -16,19 +16,18 @@
16 16
17static ctl_table unix_table[] = { 17static ctl_table unix_table[] = {
18 { 18 {
19 .ctl_name = NET_UNIX_MAX_DGRAM_QLEN,
20 .procname = "max_dgram_qlen", 19 .procname = "max_dgram_qlen",
21 .data = &init_net.unx.sysctl_max_dgram_qlen, 20 .data = &init_net.unx.sysctl_max_dgram_qlen,
22 .maxlen = sizeof(int), 21 .maxlen = sizeof(int),
23 .mode = 0644, 22 .mode = 0644,
24 .proc_handler = proc_dointvec 23 .proc_handler = proc_dointvec
25 }, 24 },
26 { .ctl_name = 0 } 25 { }
27}; 26};
28 27
29static struct ctl_path unix_path[] = { 28static struct ctl_path unix_path[] = {
30 { .procname = "net", .ctl_name = CTL_NET, }, 29 { .procname = "net", },
31 { .procname = "unix", .ctl_name = NET_UNIX, }, 30 { .procname = "unix", },
32 { }, 31 { },
33}; 32};
34 33
diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c
index a5d3416522de..d2efd29f434e 100644
--- a/net/x25/sysctl_net_x25.c
+++ b/net/x25/sysctl_net_x25.c
@@ -19,62 +19,51 @@ static struct ctl_table_header *x25_table_header;
19 19
20static struct ctl_table x25_table[] = { 20static struct ctl_table x25_table[] = {
21 { 21 {
22 .ctl_name = NET_X25_RESTART_REQUEST_TIMEOUT,
23 .procname = "restart_request_timeout", 22 .procname = "restart_request_timeout",
24 .data = &sysctl_x25_restart_request_timeout, 23 .data = &sysctl_x25_restart_request_timeout,
25 .maxlen = sizeof(int), 24 .maxlen = sizeof(int),
26 .mode = 0644, 25 .mode = 0644,
27 .proc_handler = proc_dointvec_minmax, 26 .proc_handler = proc_dointvec_minmax,
28 .strategy = sysctl_intvec,
29 .extra1 = &min_timer, 27 .extra1 = &min_timer,
30 .extra2 = &max_timer, 28 .extra2 = &max_timer,
31 }, 29 },
32 { 30 {
33 .ctl_name = NET_X25_CALL_REQUEST_TIMEOUT,
34 .procname = "call_request_timeout", 31 .procname = "call_request_timeout",
35 .data = &sysctl_x25_call_request_timeout, 32 .data = &sysctl_x25_call_request_timeout,
36 .maxlen = sizeof(int), 33 .maxlen = sizeof(int),
37 .mode = 0644, 34 .mode = 0644,
38 .proc_handler = proc_dointvec_minmax, 35 .proc_handler = proc_dointvec_minmax,
39 .strategy = sysctl_intvec,
40 .extra1 = &min_timer, 36 .extra1 = &min_timer,
41 .extra2 = &max_timer, 37 .extra2 = &max_timer,
42 }, 38 },
43 { 39 {
44 .ctl_name = NET_X25_RESET_REQUEST_TIMEOUT,
45 .procname = "reset_request_timeout", 40 .procname = "reset_request_timeout",
46 .data = &sysctl_x25_reset_request_timeout, 41 .data = &sysctl_x25_reset_request_timeout,
47 .maxlen = sizeof(int), 42 .maxlen = sizeof(int),
48 .mode = 0644, 43 .mode = 0644,
49 .proc_handler = proc_dointvec_minmax, 44 .proc_handler = proc_dointvec_minmax,
50 .strategy = sysctl_intvec,
51 .extra1 = &min_timer, 45 .extra1 = &min_timer,
52 .extra2 = &max_timer, 46 .extra2 = &max_timer,
53 }, 47 },
54 { 48 {
55 .ctl_name = NET_X25_CLEAR_REQUEST_TIMEOUT,
56 .procname = "clear_request_timeout", 49 .procname = "clear_request_timeout",
57 .data = &sysctl_x25_clear_request_timeout, 50 .data = &sysctl_x25_clear_request_timeout,
58 .maxlen = sizeof(int), 51 .maxlen = sizeof(int),
59 .mode = 0644, 52 .mode = 0644,
60 .proc_handler = proc_dointvec_minmax, 53 .proc_handler = proc_dointvec_minmax,
61 .strategy = sysctl_intvec,
62 .extra1 = &min_timer, 54 .extra1 = &min_timer,
63 .extra2 = &max_timer, 55 .extra2 = &max_timer,
64 }, 56 },
65 { 57 {
66 .ctl_name = NET_X25_ACK_HOLD_BACK_TIMEOUT,
67 .procname = "acknowledgement_hold_back_timeout", 58 .procname = "acknowledgement_hold_back_timeout",
68 .data = &sysctl_x25_ack_holdback_timeout, 59 .data = &sysctl_x25_ack_holdback_timeout,
69 .maxlen = sizeof(int), 60 .maxlen = sizeof(int),
70 .mode = 0644, 61 .mode = 0644,
71 .proc_handler = proc_dointvec_minmax, 62 .proc_handler = proc_dointvec_minmax,
72 .strategy = sysctl_intvec,
73 .extra1 = &min_timer, 63 .extra1 = &min_timer,
74 .extra2 = &max_timer, 64 .extra2 = &max_timer,
75 }, 65 },
76 { 66 {
77 .ctl_name = NET_X25_FORWARD,
78 .procname = "x25_forward", 67 .procname = "x25_forward",
79 .data = &sysctl_x25_forward, 68 .data = &sysctl_x25_forward,
80 .maxlen = sizeof(int), 69 .maxlen = sizeof(int),
@@ -85,8 +74,8 @@ static struct ctl_table x25_table[] = {
85}; 74};
86 75
87static struct ctl_path x25_path[] = { 76static struct ctl_path x25_path[] = {
88 { .procname = "net", .ctl_name = CTL_NET, }, 77 { .procname = "net", },
89 { .procname = "x25", .ctl_name = NET_X25, }, 78 { .procname = "x25", },
90 { } 79 { }
91}; 80};
92 81
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 2e6ffb66f06f..2e221f2cad7e 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -13,28 +13,24 @@ static void __xfrm_sysctl_init(struct net *net)
13#ifdef CONFIG_SYSCTL 13#ifdef CONFIG_SYSCTL
14static struct ctl_table xfrm_table[] = { 14static struct ctl_table xfrm_table[] = {
15 { 15 {
16 .ctl_name = NET_CORE_AEVENT_ETIME,
17 .procname = "xfrm_aevent_etime", 16 .procname = "xfrm_aevent_etime",
18 .maxlen = sizeof(u32), 17 .maxlen = sizeof(u32),
19 .mode = 0644, 18 .mode = 0644,
20 .proc_handler = proc_dointvec 19 .proc_handler = proc_dointvec
21 }, 20 },
22 { 21 {
23 .ctl_name = NET_CORE_AEVENT_RSEQTH,
24 .procname = "xfrm_aevent_rseqth", 22 .procname = "xfrm_aevent_rseqth",
25 .maxlen = sizeof(u32), 23 .maxlen = sizeof(u32),
26 .mode = 0644, 24 .mode = 0644,
27 .proc_handler = proc_dointvec 25 .proc_handler = proc_dointvec
28 }, 26 },
29 { 27 {
30 .ctl_name = CTL_UNNUMBERED,
31 .procname = "xfrm_larval_drop", 28 .procname = "xfrm_larval_drop",
32 .maxlen = sizeof(int), 29 .maxlen = sizeof(int),
33 .mode = 0644, 30 .mode = 0644,
34 .proc_handler = proc_dointvec 31 .proc_handler = proc_dointvec
35 }, 32 },
36 { 33 {
37 .ctl_name = CTL_UNNUMBERED,
38 .procname = "xfrm_acq_expires", 34 .procname = "xfrm_acq_expires",
39 .maxlen = sizeof(int), 35 .maxlen = sizeof(int),
40 .mode = 0644, 36 .mode = 0644,
diff --git a/samples/Kconfig b/samples/Kconfig
index b92bde3c6a89..e4be84ac3d38 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -40,5 +40,11 @@ config SAMPLE_KRETPROBES
40 default m 40 default m
41 depends on SAMPLE_KPROBES && KRETPROBES 41 depends on SAMPLE_KPROBES && KRETPROBES
42 42
43config SAMPLE_HW_BREAKPOINT
44 tristate "Build kernel hardware breakpoint examples -- loadable module only"
45 depends on HAVE_HW_BREAKPOINT && m
46 help
47 This builds kernel hardware breakpoint example modules.
48
43endif # SAMPLES 49endif # SAMPLES
44 50
diff --git a/samples/Makefile b/samples/Makefile
index 43343a03b1f4..0f15e6d77fd6 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,3 +1,4 @@
1# Makefile for Linux samples code 1# Makefile for Linux samples code
2 2
3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ 3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \
4 hw_breakpoint/
diff --git a/samples/hw_breakpoint/Makefile b/samples/hw_breakpoint/Makefile
new file mode 100644
index 000000000000..0f5c31c2fc47
--- /dev/null
+++ b/samples/hw_breakpoint/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_SAMPLE_HW_BREAKPOINT) += data_breakpoint.o
diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
new file mode 100644
index 000000000000..29525500df00
--- /dev/null
+++ b/samples/hw_breakpoint/data_breakpoint.c
@@ -0,0 +1,87 @@
1/*
2 * data_breakpoint.c - Sample HW Breakpoint file to watch kernel data address
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * usage: insmod data_breakpoint.ko ksym=<ksym_name>
19 *
20 * This file is a kernel module that places a breakpoint over ksym_name kernel
21 * variable using Hardware Breakpoint register. The corresponding handler which
22 * prints a backtrace is invoked everytime a write operation is performed on
23 * that variable.
24 *
25 * Copyright (C) IBM Corporation, 2009
26 *
27 * Author: K.Prasad <prasad@linux.vnet.ibm.com>
28 */
29#include <linux/module.h> /* Needed by all modules */
30#include <linux/kernel.h> /* Needed for KERN_INFO */
31#include <linux/init.h> /* Needed for the macros */
32#include <linux/kallsyms.h>
33
34#include <linux/perf_event.h>
35#include <linux/hw_breakpoint.h>
36
37struct perf_event **sample_hbp;
38
39static char ksym_name[KSYM_NAME_LEN] = "pid_max";
40module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
41MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
42 " write operations on the kernel symbol");
43
44static void sample_hbp_handler(struct perf_event *temp, void *data)
45{
46 printk(KERN_INFO "%s value is changed\n", ksym_name);
47 dump_stack();
48 printk(KERN_INFO "Dump stack from sample_hbp_handler\n");
49}
50
51static int __init hw_break_module_init(void)
52{
53 int ret;
54 DEFINE_BREAKPOINT_ATTR(attr);
55
56 attr.bp_addr = kallsyms_lookup_name(ksym_name);
57 attr.bp_len = HW_BREAKPOINT_LEN_4;
58 attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
59
60 sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
61 if (IS_ERR(sample_hbp)) {
62 ret = PTR_ERR(sample_hbp);
63 goto fail;
64 }
65
66 printk(KERN_INFO "HW Breakpoint for %s write installed\n", ksym_name);
67
68 return 0;
69
70fail:
71 printk(KERN_INFO "Breakpoint registration failed\n");
72
73 return ret;
74}
75
76static void __exit hw_break_module_exit(void)
77{
78 unregister_wide_hw_breakpoint(sample_hbp);
79 printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
80}
81
82module_init(hw_break_module_init);
83module_exit(hw_break_module_exit);
84
85MODULE_LICENSE("GPL");
86MODULE_AUTHOR("K.Prasad");
87MODULE_DESCRIPTION("ksym breakpoint");
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index ea9f8a58678f..241310e59cd6 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1852,10 +1852,17 @@ sub tracepoint_munge($) {
1852 my $tracepointname = 0; 1852 my $tracepointname = 0;
1853 my $tracepointargs = 0; 1853 my $tracepointargs = 0;
1854 1854
1855 if($prototype =~ m/TRACE_EVENT\((.*?),/) { 1855 if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
1856 $tracepointname = $1; 1856 $tracepointname = $1;
1857 } 1857 }
1858 if($prototype =~ m/TP_PROTO\((.*?)\)/) { 1858 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
1859 $tracepointname = $1;
1860 }
1861 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
1862 $tracepointname = $2;
1863 }
1864 $tracepointname =~ s/^\s+//; #strip leading whitespace
1865 if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
1859 $tracepointargs = $1; 1866 $tracepointargs = $1;
1860 } 1867 }
1861 if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 1868 if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
@@ -1920,7 +1927,9 @@ sub process_state3_function($$) {
1920 if ($prototype =~ /SYSCALL_DEFINE/) { 1927 if ($prototype =~ /SYSCALL_DEFINE/) {
1921 syscall_munge(); 1928 syscall_munge();
1922 } 1929 }
1923 if ($prototype =~ /TRACE_EVENT/) { 1930 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
1931 $prototype =~ /DEFINE_SINGLE_EVENT/)
1932 {
1924 tracepoint_munge($file); 1933 tracepoint_munge($file);
1925 } 1934 }
1926 dump_function($prototype, $file); 1935 dump_function($prototype, $file);
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
index 5e05dc09e2db..ee32d181764a 100644
--- a/security/keys/sysctl.c
+++ b/security/keys/sysctl.c
@@ -17,54 +17,49 @@ static const int zero, one = 1, max = INT_MAX;
17 17
18ctl_table key_sysctls[] = { 18ctl_table key_sysctls[] = {
19 { 19 {
20 .ctl_name = CTL_UNNUMBERED,
21 .procname = "maxkeys", 20 .procname = "maxkeys",
22 .data = &key_quota_maxkeys, 21 .data = &key_quota_maxkeys,
23 .maxlen = sizeof(unsigned), 22 .maxlen = sizeof(unsigned),
24 .mode = 0644, 23 .mode = 0644,
25 .proc_handler = &proc_dointvec_minmax, 24 .proc_handler = proc_dointvec_minmax,
26 .extra1 = (void *) &one, 25 .extra1 = (void *) &one,
27 .extra2 = (void *) &max, 26 .extra2 = (void *) &max,
28 }, 27 },
29 { 28 {
30 .ctl_name = CTL_UNNUMBERED,
31 .procname = "maxbytes", 29 .procname = "maxbytes",
32 .data = &key_quota_maxbytes, 30 .data = &key_quota_maxbytes,
33 .maxlen = sizeof(unsigned), 31 .maxlen = sizeof(unsigned),
34 .mode = 0644, 32 .mode = 0644,
35 .proc_handler = &proc_dointvec_minmax, 33 .proc_handler = proc_dointvec_minmax,
36 .extra1 = (void *) &one, 34 .extra1 = (void *) &one,
37 .extra2 = (void *) &max, 35 .extra2 = (void *) &max,
38 }, 36 },
39 { 37 {
40 .ctl_name = CTL_UNNUMBERED,
41 .procname = "root_maxkeys", 38 .procname = "root_maxkeys",
42 .data = &key_quota_root_maxkeys, 39 .data = &key_quota_root_maxkeys,
43 .maxlen = sizeof(unsigned), 40 .maxlen = sizeof(unsigned),
44 .mode = 0644, 41 .mode = 0644,
45 .proc_handler = &proc_dointvec_minmax, 42 .proc_handler = proc_dointvec_minmax,
46 .extra1 = (void *) &one, 43 .extra1 = (void *) &one,
47 .extra2 = (void *) &max, 44 .extra2 = (void *) &max,
48 }, 45 },
49 { 46 {
50 .ctl_name = CTL_UNNUMBERED,
51 .procname = "root_maxbytes", 47 .procname = "root_maxbytes",
52 .data = &key_quota_root_maxbytes, 48 .data = &key_quota_root_maxbytes,
53 .maxlen = sizeof(unsigned), 49 .maxlen = sizeof(unsigned),
54 .mode = 0644, 50 .mode = 0644,
55 .proc_handler = &proc_dointvec_minmax, 51 .proc_handler = proc_dointvec_minmax,
56 .extra1 = (void *) &one, 52 .extra1 = (void *) &one,
57 .extra2 = (void *) &max, 53 .extra2 = (void *) &max,
58 }, 54 },
59 { 55 {
60 .ctl_name = CTL_UNNUMBERED,
61 .procname = "gc_delay", 56 .procname = "gc_delay",
62 .data = &key_gc_delay, 57 .data = &key_gc_delay,
63 .maxlen = sizeof(unsigned), 58 .maxlen = sizeof(unsigned),
64 .mode = 0644, 59 .mode = 0644,
65 .proc_handler = &proc_dointvec_minmax, 60 .proc_handler = proc_dointvec_minmax,
66 .extra1 = (void *) &zero, 61 .extra1 = (void *) &zero,
67 .extra2 = (void *) &max, 62 .extra2 = (void *) &max,
68 }, 63 },
69 { .ctl_name = 0 } 64 { }
70}; 65};
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 5ae3a571559f..8346938809b1 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1096,27 +1096,6 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1096} 1096}
1097 1097
1098/** 1098/**
1099 * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
1100 *
1101 * @domain: Pointer to "struct tomoyo_domain_info".
1102 * @filename: Filename to check.
1103 * @perm: Mode ("read" or "write" or "read/write").
1104 * Returns 0 on success, negative value otherwise.
1105 */
1106int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1107 const char *filename, const u8 perm)
1108{
1109 struct tomoyo_path_info name;
1110 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1111
1112 if (!mode)
1113 return 0;
1114 name.name = filename;
1115 tomoyo_fill_path_info(&name);
1116 return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1117}
1118
1119/**
1120 * tomoyo_check_exec_perm - Check permission for "execute". 1099 * tomoyo_check_exec_perm - Check permission for "execute".
1121 * 1100 *
1122 * @domain: Pointer to "struct tomoyo_domain_info". 1101 * @domain: Pointer to "struct tomoyo_domain_info".
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 917f564cdab1..18369d497eb8 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -110,6 +110,15 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
110 spin_unlock(&dcache_lock); 110 spin_unlock(&dcache_lock);
111 path_put(&root); 111 path_put(&root);
112 path_put(&ns_root); 112 path_put(&ns_root);
113 /* Prepend "/proc" prefix if using internal proc vfs mount. */
114 if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
115 (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
116 sp -= 5;
117 if (sp >= newname)
118 memcpy(sp, "/proc", 5);
119 else
120 sp = ERR_PTR(-ENOMEM);
121 }
113 } 122 }
114 if (IS_ERR(sp)) 123 if (IS_ERR(sp))
115 error = PTR_ERR(sp); 124 error = PTR_ERR(sp);
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 9548a0984cc4..8a00ade85166 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -85,83 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
85 return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); 85 return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
86} 86}
87 87
88#ifdef CONFIG_SYSCTL
89
90static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
91{
92 int namelen = strlen(str);
93
94 if (*buflen < namelen)
95 return -ENOMEM;
96 *buflen -= namelen;
97 *buffer -= namelen;
98 memcpy(*buffer, str, namelen);
99 return 0;
100}
101
102/**
103 * tomoyo_sysctl_path - return the realpath of a ctl_table.
104 * @table: pointer to "struct ctl_table".
105 *
106 * Returns realpath(3) of the @table on success.
107 * Returns NULL on failure.
108 *
109 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
110 * if this function didn't return NULL.
111 */
112static char *tomoyo_sysctl_path(struct ctl_table *table)
113{
114 int buflen = TOMOYO_MAX_PATHNAME_LEN;
115 char *buf = tomoyo_alloc(buflen);
116 char *end = buf + buflen;
117 int error = -ENOMEM;
118
119 if (!buf)
120 return NULL;
121
122 *--end = '\0';
123 buflen--;
124 while (table) {
125 char num[32];
126 const char *sp = table->procname;
127
128 if (!sp) {
129 memset(num, 0, sizeof(num));
130 snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name);
131 sp = num;
132 }
133 if (tomoyo_prepend(&end, &buflen, sp) ||
134 tomoyo_prepend(&end, &buflen, "/"))
135 goto out;
136 table = table->parent;
137 }
138 if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
139 goto out;
140 error = tomoyo_encode(buf, end - buf, end);
141 out:
142 if (!error)
143 return buf;
144 tomoyo_free(buf);
145 return NULL;
146}
147
148static int tomoyo_sysctl(struct ctl_table *table, int op)
149{
150 int error;
151 char *name;
152
153 op &= MAY_READ | MAY_WRITE;
154 if (!op)
155 return 0;
156 name = tomoyo_sysctl_path(table);
157 if (!name)
158 return -ENOMEM;
159 error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
160 tomoyo_free(name);
161 return error;
162}
163#endif
164
165static int tomoyo_path_truncate(struct path *path, loff_t length, 88static int tomoyo_path_truncate(struct path *path, loff_t length,
166 unsigned int time_attrs) 89 unsigned int time_attrs)
167{ 90{
@@ -282,9 +205,6 @@ static struct security_operations tomoyo_security_ops = {
282 .cred_transfer = tomoyo_cred_transfer, 205 .cred_transfer = tomoyo_cred_transfer,
283 .bprm_set_creds = tomoyo_bprm_set_creds, 206 .bprm_set_creds = tomoyo_bprm_set_creds,
284 .bprm_check_security = tomoyo_bprm_check_security, 207 .bprm_check_security = tomoyo_bprm_check_security,
285#ifdef CONFIG_SYSCTL
286 .sysctl = tomoyo_sysctl,
287#endif
288 .file_fcntl = tomoyo_file_fcntl, 208 .file_fcntl = tomoyo_file_fcntl,
289 .dentry_open = tomoyo_dentry_open, 209 .dentry_open = tomoyo_dentry_open,
290 .path_truncate = tomoyo_path_truncate, 210 .path_truncate = tomoyo_path_truncate,
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
index cd6ba0bf7069..ed758325b1ae 100644
--- a/security/tomoyo/tomoyo.h
+++ b/security/tomoyo/tomoyo.h
@@ -18,8 +18,6 @@ struct inode;
18struct linux_binprm; 18struct linux_binprm;
19struct pt_regs; 19struct pt_regs;
20 20
21int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
22 const char *filename, const u8 perm);
23int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 21int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
24 const struct tomoyo_path_info *filename); 22 const struct tomoyo_path_info *filename);
25int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 23int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
diff --git a/sound/Kconfig b/sound/Kconfig
index 439e15c8faa3..b3e53e616ec9 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -58,7 +58,7 @@ config SOUND_OSS_CORE_PRECLAIM
58 Please read Documentation/feature-removal-schedule.txt for 58 Please read Documentation/feature-removal-schedule.txt for
59 details. 59 details.
60 60
61 If unusre, say Y. 61 If unsure, say Y.
62 62
63source "sound/oss/dmasound/Kconfig" 63source "sound/oss/dmasound/Kconfig"
64 64
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index 5a549ed6c8aa..8c0c851d4641 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o 5obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
6snd-aaci-objs := aaci.o devdma.o 6snd-aaci-objs := aaci.o
7 7
8obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o 8obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
9snd-pxa2xx-pcm-objs := pxa2xx-pcm.o 9snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 6c160a038b23..1497dce1b04a 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -18,10 +18,7 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/amba/bus.h> 20#include <linux/amba/bus.h>
21 21#include <linux/io.h>
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/sizes.h>
25 22
26#include <sound/core.h> 23#include <sound/core.h>
27#include <sound/initval.h> 24#include <sound/initval.h>
@@ -30,7 +27,6 @@
30#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
31 28
32#include "aaci.h" 29#include "aaci.h"
33#include "devdma.h"
34 30
35#define DRIVER_NAME "aaci-pl041" 31#define DRIVER_NAME "aaci-pl041"
36 32
@@ -492,7 +488,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
492 /* 488 /*
493 * Clear out the DMA and any allocated buffers. 489 * Clear out the DMA and any allocated buffers.
494 */ 490 */
495 devdma_hw_free(NULL, substream); 491 snd_pcm_lib_free_pages(substream);
496 492
497 return 0; 493 return 0;
498} 494}
@@ -509,20 +505,14 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
509 aacirun->pcm_open = 0; 505 aacirun->pcm_open = 0;
510 } 506 }
511 507
512 err = devdma_hw_alloc(NULL, substream, 508 err = snd_pcm_lib_malloc_pages(substream,
513 params_buffer_bytes(params)); 509 params_buffer_bytes(params));
514 if (err < 0) 510 if (err < 0)
515 goto out; 511 goto out;
516 512
517 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 513 err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
518 err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), 514 params_channels(params),
519 params_channels(params), 515 aacirun->pcm->r[0].slots);
520 aacirun->pcm->r[0].slots);
521 else
522 err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
523 params_channels(params),
524 aacirun->pcm->r[0].slots);
525
526 if (err) 516 if (err)
527 goto out; 517 goto out;
528 518
@@ -538,7 +528,7 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
538 struct aaci_runtime *aacirun = runtime->private_data; 528 struct aaci_runtime *aacirun = runtime->private_data;
539 529
540 aacirun->start = (void *)runtime->dma_area; 530 aacirun->start = (void *)runtime->dma_area;
541 aacirun->end = aacirun->start + runtime->dma_bytes; 531 aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream);
542 aacirun->ptr = aacirun->start; 532 aacirun->ptr = aacirun->start;
543 aacirun->period = 533 aacirun->period =
544 aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); 534 aacirun->bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -555,11 +545,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
555 return bytes_to_frames(runtime, bytes); 545 return bytes_to_frames(runtime, bytes);
556} 546}
557 547
558static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
559{
560 return devdma_mmap(NULL, substream, vma);
561}
562
563 548
564/* 549/*
565 * Playback specific ALSA stuff 550 * Playback specific ALSA stuff
@@ -726,7 +711,6 @@ static struct snd_pcm_ops aaci_playback_ops = {
726 .prepare = aaci_pcm_prepare, 711 .prepare = aaci_pcm_prepare,
727 .trigger = aaci_pcm_playback_trigger, 712 .trigger = aaci_pcm_playback_trigger,
728 .pointer = aaci_pcm_pointer, 713 .pointer = aaci_pcm_pointer,
729 .mmap = aaci_pcm_mmap,
730}; 714};
731 715
732static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, 716static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
@@ -854,7 +838,6 @@ static struct snd_pcm_ops aaci_capture_ops = {
854 .prepare = aaci_pcm_capture_prepare, 838 .prepare = aaci_pcm_capture_prepare,
855 .trigger = aaci_pcm_capture_trigger, 839 .trigger = aaci_pcm_capture_trigger,
856 .pointer = aaci_pcm_pointer, 840 .pointer = aaci_pcm_pointer,
857 .mmap = aaci_pcm_mmap,
858}; 841};
859 842
860/* 843/*
@@ -1044,6 +1027,8 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
1044 1027
1045 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); 1028 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
1046 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); 1029 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
1030 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1031 NULL, 0, 64 * 104);
1047 } 1032 }
1048 1033
1049 return ret; 1034 return ret;
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c
deleted file mode 100644
index 9d1e6665b546..000000000000
--- a/sound/arm/devdma.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * linux/sound/arm/devdma.c
3 *
4 * Copyright (C) 2003-2004 Russell King, All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ARM DMA shim for ALSA.
11 */
12#include <linux/device.h>
13#include <linux/dma-mapping.h>
14
15#include <sound/core.h>
16#include <sound/pcm.h>
17
18#include "devdma.h"
19
20void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream)
21{
22 struct snd_pcm_runtime *runtime = substream->runtime;
23 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
24
25 if (runtime->dma_area == NULL)
26 return;
27
28 if (buf != &substream->dma_buffer) {
29 dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr);
30 kfree(runtime->dma_buffer_p);
31 }
32
33 snd_pcm_set_runtime_buffer(substream, NULL);
34}
35
36int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size)
37{
38 struct snd_pcm_runtime *runtime = substream->runtime;
39 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
40 int ret = 0;
41
42 if (buf) {
43 if (buf->bytes >= size)
44 goto out;
45 devdma_hw_free(dev, substream);
46 }
47
48 if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
49 buf = &substream->dma_buffer;
50 } else {
51 buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
52 if (!buf)
53 goto nomem;
54
55 buf->dev.type = SNDRV_DMA_TYPE_DEV;
56 buf->dev.dev = dev;
57 buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL);
58 buf->bytes = size;
59 buf->private_data = NULL;
60
61 if (!buf->area)
62 goto free;
63 }
64 snd_pcm_set_runtime_buffer(substream, buf);
65 ret = 1;
66 out:
67 runtime->dma_bytes = size;
68 return ret;
69
70 free:
71 kfree(buf);
72 nomem:
73 return -ENOMEM;
74}
75
76int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma)
77{
78 struct snd_pcm_runtime *runtime = substream->runtime;
79 return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
80}
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h
deleted file mode 100644
index d025329c8a0f..000000000000
--- a/sound/arm/devdma.h
+++ /dev/null
@@ -1,3 +0,0 @@
1void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream);
2int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size);
3int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma);
diff --git a/sound/core/control.c b/sound/core/control.c
index a8b7fabe645e..268ab7471224 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -75,7 +75,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
75 ctl->card = card; 75 ctl->card = card;
76 ctl->prefer_pcm_subdevice = -1; 76 ctl->prefer_pcm_subdevice = -1;
77 ctl->prefer_rawmidi_subdevice = -1; 77 ctl->prefer_rawmidi_subdevice = -1;
78 ctl->pid = current->pid; 78 ctl->pid = get_pid(task_pid(current));
79 file->private_data = ctl; 79 file->private_data = ctl;
80 write_lock_irqsave(&card->ctl_files_rwlock, flags); 80 write_lock_irqsave(&card->ctl_files_rwlock, flags);
81 list_add_tail(&ctl->list, &card->ctl_files); 81 list_add_tail(&ctl->list, &card->ctl_files);
@@ -125,6 +125,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
125 control->vd[idx].owner = NULL; 125 control->vd[idx].owner = NULL;
126 up_write(&card->controls_rwsem); 126 up_write(&card->controls_rwsem);
127 snd_ctl_empty_read_queue(ctl); 127 snd_ctl_empty_read_queue(ctl);
128 put_pid(ctl->pid);
128 kfree(ctl); 129 kfree(ctl);
129 module_put(card->module); 130 module_put(card->module);
130 snd_card_file_remove(card, file); 131 snd_card_file_remove(card, file);
@@ -672,7 +673,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
672 info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; 673 info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
673 if (vd->owner == ctl) 674 if (vd->owner == ctl)
674 info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; 675 info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
675 info->owner = vd->owner_pid; 676 info->owner = pid_vnr(vd->owner->pid);
676 } else { 677 } else {
677 info->owner = -1; 678 info->owner = -1;
678 } 679 }
@@ -827,7 +828,6 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
827 result = -EBUSY; 828 result = -EBUSY;
828 else { 829 else {
829 vd->owner = file; 830 vd->owner = file;
830 vd->owner_pid = current->pid;
831 result = 0; 831 result = 0;
832 } 832 }
833 } 833 }
@@ -858,7 +858,6 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
858 result = -EPERM; 858 result = -EPERM;
859 else { 859 else {
860 vd->owner = NULL; 860 vd->owner = NULL;
861 vd->owner_pid = 0;
862 result = 0; 861 result = 0;
863 } 862 }
864 } 863 }
@@ -1120,7 +1119,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
1120 goto __kctl_end; 1119 goto __kctl_end;
1121 } 1120 }
1122 if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 1121 if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1123 if (file && vd->owner != NULL && vd->owner != file) { 1122 if (vd->owner != NULL && vd->owner != file) {
1124 err = -EPERM; 1123 err = -EPERM;
1125 goto __kctl_end; 1124 goto __kctl_end;
1126 } 1125 }
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 79f0f16af339..950e19ba91fc 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -85,16 +85,24 @@ EXPORT_SYMBOL(snd_dma_disable);
85unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) 85unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
86{ 86{
87 unsigned long flags; 87 unsigned long flags;
88 unsigned int result; 88 unsigned int result, result1;
89 89
90 flags = claim_dma_lock(); 90 flags = claim_dma_lock();
91 clear_dma_ff(dma); 91 clear_dma_ff(dma);
92 if (!isa_dma_bridge_buggy) 92 if (!isa_dma_bridge_buggy)
93 disable_dma(dma); 93 disable_dma(dma);
94 result = get_dma_residue(dma); 94 result = get_dma_residue(dma);
95 /*
96 * HACK - read the counter again and choose higher value in order to
97 * avoid reading during counter lower byte roll over if the
98 * isa_dma_bridge_buggy is set.
99 */
100 result1 = get_dma_residue(dma);
95 if (!isa_dma_bridge_buggy) 101 if (!isa_dma_bridge_buggy)
96 enable_dma(dma); 102 enable_dma(dma);
97 release_dma_lock(flags); 103 release_dma_lock(flags);
104 if (unlikely(result < result1))
105 result = result1;
98#ifdef CONFIG_SND_DEBUG 106#ifdef CONFIG_SND_DEBUG
99 if (result > size) 107 if (result > size)
100 snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); 108 snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 772423889eb3..54e2eb56e4c2 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1251,7 +1251,9 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
1251 { SOUND_MIXER_SYNTH, "FM", 0 }, /* fallback */ 1251 { SOUND_MIXER_SYNTH, "FM", 0 }, /* fallback */
1252 { SOUND_MIXER_SYNTH, "Music", 0 }, /* fallback */ 1252 { SOUND_MIXER_SYNTH, "Music", 0 }, /* fallback */
1253 { SOUND_MIXER_PCM, "PCM", 0 }, 1253 { SOUND_MIXER_PCM, "PCM", 0 },
1254 { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, 1254 { SOUND_MIXER_SPEAKER, "Beep", 0 },
1255 { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, /* fallback */
1256 { SOUND_MIXER_SPEAKER, "Speaker", 0 }, /* fallback */
1255 { SOUND_MIXER_LINE, "Line", 0 }, 1257 { SOUND_MIXER_LINE, "Line", 0 },
1256 { SOUND_MIXER_MIC, "Mic", 0 }, 1258 { SOUND_MIXER_MIC, "Mic", 0 },
1257 { SOUND_MIXER_CD, "CD", 0 }, 1259 { SOUND_MIXER_CD, "CD", 0 },
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index c69c60b2a48a..6884ae031f6f 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -435,6 +435,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
435 return; 435 return;
436 } 436 }
437 snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); 437 snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
438 snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
438 snd_iprintf(buffer, "trigger_time: %ld.%09ld\n", 439 snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
439 status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec); 440 status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
440 snd_iprintf(buffer, "tstamp : %ld.%09ld\n", 441 snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
@@ -809,7 +810,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
809 card = pcm->card; 810 card = pcm->card;
810 read_lock(&card->ctl_files_rwlock); 811 read_lock(&card->ctl_files_rwlock);
811 list_for_each_entry(kctl, &card->ctl_files, list) { 812 list_for_each_entry(kctl, &card->ctl_files, list) {
812 if (kctl->pid == current->pid) { 813 if (kctl->pid == task_pid(current)) {
813 prefer_subdevice = kctl->prefer_pcm_subdevice; 814 prefer_subdevice = kctl->prefer_pcm_subdevice;
814 if (prefer_subdevice != -1) 815 if (prefer_subdevice != -1)
815 break; 816 break;
@@ -900,6 +901,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
900 substream->private_data = pcm->private_data; 901 substream->private_data = pcm->private_data;
901 substream->ref_count = 1; 902 substream->ref_count = 1;
902 substream->f_flags = file->f_flags; 903 substream->f_flags = file->f_flags;
904 substream->pid = get_pid(task_pid(current));
903 pstr->substream_opened++; 905 pstr->substream_opened++;
904 *rsubstream = substream; 906 *rsubstream = substream;
905 return 0; 907 return 0;
@@ -921,6 +923,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
921 kfree(runtime->hw_constraints.rules); 923 kfree(runtime->hw_constraints.rules);
922 kfree(runtime); 924 kfree(runtime);
923 substream->runtime = NULL; 925 substream->runtime = NULL;
926 put_pid(substream->pid);
927 substream->pid = NULL;
924 substream->pstr->substream_opened--; 928 substream->pstr->substream_opened--;
925} 929}
926 930
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index ab73edf2c89a..29ab46a12e11 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -26,6 +26,7 @@
26#include <linux/time.h> 26#include <linux/time.h>
27#include <linux/pm_qos_params.h> 27#include <linux/pm_qos_params.h>
28#include <linux/uio.h> 28#include <linux/uio.h>
29#include <linux/dma-mapping.h>
29#include <sound/core.h> 30#include <sound/core.h>
30#include <sound/control.h> 31#include <sound/control.h>
31#include <sound/info.h> 32#include <sound/info.h>
@@ -3061,6 +3062,27 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
3061} 3062}
3062#endif /* coherent mmap */ 3063#endif /* coherent mmap */
3063 3064
3065static inline struct page *
3066snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
3067{
3068 void *vaddr = substream->runtime->dma_area + ofs;
3069#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
3070 if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
3071 return virt_to_page(CAC_ADDR(vaddr));
3072#endif
3073#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE)
3074 if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
3075 dma_addr_t addr = substream->runtime->dma_addr + ofs;
3076 addr -= get_dma_offset(substream->dma_buffer.dev.dev);
3077 /* assume dma_handle set via pfn_to_phys() in
3078 * mm/dma-noncoherent.c
3079 */
3080 return pfn_to_page(addr >> PAGE_SHIFT);
3081 }
3082#endif
3083 return virt_to_page(vaddr);
3084}
3085
3064/* 3086/*
3065 * fault callback for mmapping a RAM page 3087 * fault callback for mmapping a RAM page
3066 */ 3088 */
@@ -3071,7 +3093,6 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
3071 struct snd_pcm_runtime *runtime; 3093 struct snd_pcm_runtime *runtime;
3072 unsigned long offset; 3094 unsigned long offset;
3073 struct page * page; 3095 struct page * page;
3074 void *vaddr;
3075 size_t dma_bytes; 3096 size_t dma_bytes;
3076 3097
3077 if (substream == NULL) 3098 if (substream == NULL)
@@ -3081,36 +3102,53 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
3081 dma_bytes = PAGE_ALIGN(runtime->dma_bytes); 3102 dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
3082 if (offset > dma_bytes - PAGE_SIZE) 3103 if (offset > dma_bytes - PAGE_SIZE)
3083 return VM_FAULT_SIGBUS; 3104 return VM_FAULT_SIGBUS;
3084 if (substream->ops->page) { 3105 if (substream->ops->page)
3085 page = substream->ops->page(substream, offset); 3106 page = substream->ops->page(substream, offset);
3086 if (!page) 3107 else
3087 return VM_FAULT_SIGBUS; 3108 page = snd_pcm_default_page_ops(substream, offset);
3088 } else { 3109 if (!page)
3089 vaddr = runtime->dma_area + offset; 3110 return VM_FAULT_SIGBUS;
3090 page = virt_to_page(vaddr);
3091 }
3092 get_page(page); 3111 get_page(page);
3093 vmf->page = page; 3112 vmf->page = page;
3094 return 0; 3113 return 0;
3095} 3114}
3096 3115
3097static const struct vm_operations_struct snd_pcm_vm_ops_data = 3116static const struct vm_operations_struct snd_pcm_vm_ops_data = {
3098{ 3117 .open = snd_pcm_mmap_data_open,
3118 .close = snd_pcm_mmap_data_close,
3119};
3120
3121static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
3099 .open = snd_pcm_mmap_data_open, 3122 .open = snd_pcm_mmap_data_open,
3100 .close = snd_pcm_mmap_data_close, 3123 .close = snd_pcm_mmap_data_close,
3101 .fault = snd_pcm_mmap_data_fault, 3124 .fault = snd_pcm_mmap_data_fault,
3102}; 3125};
3103 3126
3127#ifndef ARCH_HAS_DMA_MMAP_COHERENT
3128/* This should be defined / handled globally! */
3129#ifdef CONFIG_ARM
3130#define ARCH_HAS_DMA_MMAP_COHERENT
3131#endif
3132#endif
3133
3104/* 3134/*
3105 * mmap the DMA buffer on RAM 3135 * mmap the DMA buffer on RAM
3106 */ 3136 */
3107static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, 3137static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
3108 struct vm_area_struct *area) 3138 struct vm_area_struct *area)
3109{ 3139{
3110 area->vm_ops = &snd_pcm_vm_ops_data;
3111 area->vm_private_data = substream;
3112 area->vm_flags |= VM_RESERVED; 3140 area->vm_flags |= VM_RESERVED;
3113 atomic_inc(&substream->mmap_count); 3141#ifdef ARCH_HAS_DMA_MMAP_COHERENT
3142 if (!substream->ops->page &&
3143 substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
3144 return dma_mmap_coherent(substream->dma_buffer.dev.dev,
3145 area,
3146 substream->runtime->dma_area,
3147 substream->runtime->dma_addr,
3148 area->vm_end - area->vm_start);
3149#endif /* ARCH_HAS_DMA_MMAP_COHERENT */
3150 /* mmap with fault handler */
3151 area->vm_ops = &snd_pcm_vm_ops_data_fault;
3114 return 0; 3152 return 0;
3115} 3153}
3116 3154
@@ -3118,12 +3156,6 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
3118 * mmap the DMA buffer on I/O memory area 3156 * mmap the DMA buffer on I/O memory area
3119 */ 3157 */
3120#if SNDRV_PCM_INFO_MMAP_IOMEM 3158#if SNDRV_PCM_INFO_MMAP_IOMEM
3121static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
3122{
3123 .open = snd_pcm_mmap_data_open,
3124 .close = snd_pcm_mmap_data_close,
3125};
3126
3127int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, 3159int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3128 struct vm_area_struct *area) 3160 struct vm_area_struct *area)
3129{ 3161{
@@ -3133,8 +3165,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3133#ifdef pgprot_noncached 3165#ifdef pgprot_noncached
3134 area->vm_page_prot = pgprot_noncached(area->vm_page_prot); 3166 area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
3135#endif 3167#endif
3136 area->vm_ops = &snd_pcm_vm_ops_data_mmio;
3137 area->vm_private_data = substream;
3138 area->vm_flags |= VM_IO; 3168 area->vm_flags |= VM_IO;
3139 size = area->vm_end - area->vm_start; 3169 size = area->vm_end - area->vm_start;
3140 offset = area->vm_pgoff << PAGE_SHIFT; 3170 offset = area->vm_pgoff << PAGE_SHIFT;
@@ -3142,7 +3172,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3142 (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, 3172 (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
3143 size, area->vm_page_prot)) 3173 size, area->vm_page_prot))
3144 return -EAGAIN; 3174 return -EAGAIN;
3145 atomic_inc(&substream->mmap_count);
3146 return 0; 3175 return 0;
3147} 3176}
3148 3177
@@ -3159,6 +3188,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3159 long size; 3188 long size;
3160 unsigned long offset; 3189 unsigned long offset;
3161 size_t dma_bytes; 3190 size_t dma_bytes;
3191 int err;
3162 3192
3163 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 3193 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3164 if (!(area->vm_flags & (VM_WRITE|VM_READ))) 3194 if (!(area->vm_flags & (VM_WRITE|VM_READ)))
@@ -3183,10 +3213,15 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3183 if (offset > dma_bytes - size) 3213 if (offset > dma_bytes - size)
3184 return -EINVAL; 3214 return -EINVAL;
3185 3215
3216 area->vm_ops = &snd_pcm_vm_ops_data;
3217 area->vm_private_data = substream;
3186 if (substream->ops->mmap) 3218 if (substream->ops->mmap)
3187 return substream->ops->mmap(substream, area); 3219 err = substream->ops->mmap(substream, area);
3188 else 3220 else
3189 return snd_pcm_default_mmap(substream, area); 3221 err = snd_pcm_default_mmap(substream, area);
3222 if (!err)
3223 atomic_inc(&substream->mmap_count);
3224 return err;
3190} 3225}
3191 3226
3192EXPORT_SYMBOL(snd_pcm_mmap_data); 3227EXPORT_SYMBOL(snd_pcm_mmap_data);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 70d6f25ba526..2f766123b158 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -242,8 +242,6 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
242 return -ENXIO; 242 return -ENXIO;
243 if (subdevice >= 0 && subdevice >= s->substream_count) 243 if (subdevice >= 0 && subdevice >= s->substream_count)
244 return -ENODEV; 244 return -ENODEV;
245 if (s->substream_opened >= s->substream_count)
246 return -EAGAIN;
247 245
248 list_for_each_entry(substream, &s->substreams, list) { 246 list_for_each_entry(substream, &s->substreams, list) {
249 if (substream->opened) { 247 if (substream->opened) {
@@ -280,9 +278,10 @@ static int open_substream(struct snd_rawmidi *rmidi,
280 substream->active_sensing = 0; 278 substream->active_sensing = 0;
281 if (mode & SNDRV_RAWMIDI_LFLG_APPEND) 279 if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
282 substream->append = 1; 280 substream->append = 1;
281 substream->pid = get_pid(task_pid(current));
282 rmidi->streams[substream->stream].substream_opened++;
283 } 283 }
284 substream->use_count++; 284 substream->use_count++;
285 rmidi->streams[substream->stream].substream_opened++;
286 return 0; 285 return 0;
287} 286}
288 287
@@ -413,7 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
413 subdevice = -1; 412 subdevice = -1;
414 read_lock(&card->ctl_files_rwlock); 413 read_lock(&card->ctl_files_rwlock);
415 list_for_each_entry(kctl, &card->ctl_files, list) { 414 list_for_each_entry(kctl, &card->ctl_files, list) {
416 if (kctl->pid == current->pid) { 415 if (kctl->pid == task_pid(current)) {
417 subdevice = kctl->prefer_rawmidi_subdevice; 416 subdevice = kctl->prefer_rawmidi_subdevice;
418 if (subdevice != -1) 417 if (subdevice != -1)
419 break; 418 break;
@@ -466,7 +465,6 @@ static void close_substream(struct snd_rawmidi *rmidi,
466 struct snd_rawmidi_substream *substream, 465 struct snd_rawmidi_substream *substream,
467 int cleanup) 466 int cleanup)
468{ 467{
469 rmidi->streams[substream->stream].substream_opened--;
470 if (--substream->use_count) 468 if (--substream->use_count)
471 return; 469 return;
472 470
@@ -491,6 +489,9 @@ static void close_substream(struct snd_rawmidi *rmidi,
491 snd_rawmidi_runtime_free(substream); 489 snd_rawmidi_runtime_free(substream);
492 substream->opened = 0; 490 substream->opened = 0;
493 substream->append = 0; 491 substream->append = 0;
492 put_pid(substream->pid);
493 substream->pid = NULL;
494 rmidi->streams[substream->stream].substream_opened--;
494} 495}
495 496
496static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) 497static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)
@@ -1338,6 +1339,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
1338 substream->number, 1339 substream->number,
1339 (unsigned long) substream->bytes); 1340 (unsigned long) substream->bytes);
1340 if (substream->opened) { 1341 if (substream->opened) {
1342 snd_iprintf(buffer,
1343 " Owner PID : %d\n",
1344 pid_vnr(substream->pid));
1341 runtime = substream->runtime; 1345 runtime = substream->runtime;
1342 snd_iprintf(buffer, 1346 snd_iprintf(buffer,
1343 " Mode : %s\n" 1347 " Mode : %s\n"
@@ -1359,6 +1363,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
1359 substream->number, 1363 substream->number,
1360 (unsigned long) substream->bytes); 1364 (unsigned long) substream->bytes);
1361 if (substream->opened) { 1365 if (substream->opened) {
1366 snd_iprintf(buffer,
1367 " Owner PID : %d\n",
1368 pid_vnr(substream->pid));
1362 runtime = substream->runtime; 1369 runtime = substream->runtime;
1363 snd_iprintf(buffer, 1370 snd_iprintf(buffer,
1364 " Buffer size : %lu\n" 1371 " Buffer size : %lu\n"
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index b60cef257b58..f165c77d6273 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -26,6 +26,7 @@ MODULE_ALIAS("platform:pcspkr");
26static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 26static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
27static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 27static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
28static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ 28static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
29static int nopcm; /* Disable PCM capability of the driver */
29 30
30module_param(index, int, 0444); 31module_param(index, int, 0444);
31MODULE_PARM_DESC(index, "Index value for pcsp soundcard."); 32MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
@@ -33,6 +34,8 @@ module_param(id, charp, 0444);
33MODULE_PARM_DESC(id, "ID string for pcsp soundcard."); 34MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
34module_param(enable, bool, 0444); 35module_param(enable, bool, 0444);
35MODULE_PARM_DESC(enable, "Enable PC-Speaker sound."); 36MODULE_PARM_DESC(enable, "Enable PC-Speaker sound.");
37module_param(nopcm, bool, 0444);
38MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain.");
36 39
37struct snd_pcsp pcsp_chip; 40struct snd_pcsp pcsp_chip;
38 41
@@ -43,13 +46,16 @@ static int __devinit snd_pcsp_create(struct snd_card *card)
43 int err; 46 int err;
44 int div, min_div, order; 47 int div, min_div, order;
45 48
46 hrtimer_get_res(CLOCK_MONOTONIC, &tp); 49 if (!nopcm) {
47 if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { 50 hrtimer_get_res(CLOCK_MONOTONIC, &tp);
48 printk(KERN_ERR "PCSP: Timer resolution is not sufficient " 51 if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
49 "(%linS)\n", tp.tv_nsec); 52 printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
50 printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " 53 "(%linS)\n", tp.tv_nsec);
51 "enabled.\n"); 54 printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI "
52 return -EIO; 55 "enabled.\n");
56 printk(KERN_ERR "PCSP: Turned into nopcm mode.\n");
57 nopcm = 1;
58 }
53 } 59 }
54 60
55 if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) 61 if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS)
@@ -107,12 +113,14 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
107 snd_card_free(card); 113 snd_card_free(card);
108 return err; 114 return err;
109 } 115 }
110 err = snd_pcsp_new_pcm(&pcsp_chip); 116 if (!nopcm) {
111 if (err < 0) { 117 err = snd_pcsp_new_pcm(&pcsp_chip);
112 snd_card_free(card); 118 if (err < 0) {
113 return err; 119 snd_card_free(card);
120 return err;
121 }
114 } 122 }
115 err = snd_pcsp_new_mixer(&pcsp_chip); 123 err = snd_pcsp_new_mixer(&pcsp_chip, nopcm);
116 if (err < 0) { 124 if (err < 0) {
117 snd_card_free(card); 125 snd_card_free(card);
118 return err; 126 return err;
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index 174dd2ff0f22..1e123077923d 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -83,6 +83,6 @@ extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
83extern void pcsp_sync_stop(struct snd_pcsp *chip); 83extern void pcsp_sync_stop(struct snd_pcsp *chip);
84 84
85extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); 85extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
86extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); 86extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm);
87 87
88#endif 88#endif
diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
index 903bc846763f..6f633f4f3b96 100644
--- a/sound/drivers/pcsp/pcsp_mixer.c
+++ b/sound/drivers/pcsp/pcsp_mixer.c
@@ -119,24 +119,43 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
119 .put = pcsp_##ctl_type##_put, \ 119 .put = pcsp_##ctl_type##_put, \
120} 120}
121 121
122static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = { 122static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = {
123 PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), 123 PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
124 PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), 124 PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
125 PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"),
126}; 125};
127 126
128int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip) 127static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = {
128 PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
129};
130
131static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
132 struct snd_kcontrol_new *ctls, int num)
129{ 133{
130 struct snd_card *card = chip->card;
131 int i, err; 134 int i, err;
135 struct snd_card *card = chip->card;
136 for (i = 0; i < num; i++) {
137 err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip));
138 if (err < 0)
139 return err;
140 }
141 return 0;
142}
143
144int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
145{
146 int err;
147 struct snd_card *card = chip->card;
132 148
133 for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) { 149 if (!nopcm) {
134 err = snd_ctl_add(card, 150 err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm,
135 snd_ctl_new1(snd_pcsp_controls + i, 151 ARRAY_SIZE(snd_pcsp_controls_pcm));
136 chip));
137 if (err < 0) 152 if (err < 0)
138 return err; 153 return err;
139 } 154 }
155 err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr,
156 ARRAY_SIZE(snd_pcsp_controls_spkr));
157 if (err < 0)
158 return err;
140 159
141 strcpy(card->mixername, "PC-Speaker"); 160 strcpy(card->mixername, "PC-Speaker");
142 161
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 020a5d512472..04ae8704cdcd 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -23,6 +23,7 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/bitrev.h>
26#include <asm/unaligned.h> 27#include <asm/unaligned.h>
27#include <sound/core.h> 28#include <sound/core.h>
28#include <sound/control.h> 29#include <sound/control.h>
@@ -55,18 +56,6 @@ struct cs8427 {
55 struct cs8427_stream capture; 56 struct cs8427_stream capture;
56}; 57};
57 58
58static unsigned char swapbits(unsigned char val)
59{
60 int bit;
61 unsigned char res = 0;
62 for (bit = 0; bit < 8; bit++) {
63 res <<= 1;
64 res |= val & 1;
65 val >>= 1;
66 }
67 return res;
68}
69
70int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg, 59int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
71 unsigned char val) 60 unsigned char val)
72{ 61{
@@ -149,7 +138,7 @@ static int snd_cs8427_send_corudata(struct snd_i2c_device *device,
149 } 138 }
150 data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF; 139 data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF;
151 for (idx = 0; idx < count; idx++) 140 for (idx = 0; idx < count; idx++)
152 data[idx + 1] = swapbits(ndata[idx]); 141 data[idx + 1] = bitrev8(ndata[idx]);
153 if (snd_i2c_sendbytes(device, data, count + 1) != count + 1) 142 if (snd_i2c_sendbytes(device, data, count + 1) != count + 1)
154 return -EIO; 143 return -EIO;
155 return 1; 144 return 1;
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 703d954238f4..2dad40f3f622 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -5,6 +5,7 @@
5 5
6snd-ak4114-objs := ak4114.o 6snd-ak4114-objs := ak4114.o
7snd-ak4117-objs := ak4117.o 7snd-ak4117-objs := ak4117.o
8snd-ak4113-objs := ak4113.o
8snd-ak4xxx-adda-objs := ak4xxx-adda.o 9snd-ak4xxx-adda-objs := ak4xxx-adda.o
9snd-pt2258-objs := pt2258.o 10snd-pt2258-objs := pt2258.o
10snd-tea575x-tuner-objs := tea575x-tuner.o 11snd-tea575x-tuner-objs := tea575x-tuner.o
@@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
12# Module Dependency 13# Module Dependency
13obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o 14obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
14obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o 15obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
15obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o 16obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
16obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o 17obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
new file mode 100644
index 000000000000..fff62cc8607c
--- /dev/null
+++ b/sound/i2c/other/ak4113.c
@@ -0,0 +1,639 @@
1/*
2 * Routines for control of the AK4113 via I2C/4-wire serial interface
3 * IEC958 (S/PDIF) receiver by Asahi Kasei
4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
5 * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/slab.h>
25#include <linux/delay.h>
26#include <sound/core.h>
27#include <sound/control.h>
28#include <sound/pcm.h>
29#include <sound/ak4113.h>
30#include <sound/asoundef.h>
31#include <sound/info.h>
32
33MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>");
34MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei");
35MODULE_LICENSE("GPL");
36
37#define AK4113_ADDR 0x00 /* fixed address */
38
39static void ak4113_stats(struct work_struct *work);
40static void ak4113_init_regs(struct ak4113 *chip);
41
42
43static void reg_write(struct ak4113 *ak4113, unsigned char reg,
44 unsigned char val)
45{
46 ak4113->write(ak4113->private_data, reg, val);
47 if (reg < sizeof(ak4113->regmap))
48 ak4113->regmap[reg] = val;
49}
50
51static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg)
52{
53 return ak4113->read(ak4113->private_data, reg);
54}
55
56static void snd_ak4113_free(struct ak4113 *chip)
57{
58 chip->init = 1; /* don't schedule new work */
59 mb();
60 cancel_delayed_work(&chip->work);
61 flush_scheduled_work();
62 kfree(chip);
63}
64
65static int snd_ak4113_dev_free(struct snd_device *device)
66{
67 struct ak4113 *chip = device->device_data;
68 snd_ak4113_free(chip);
69 return 0;
70}
71
72int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
73 ak4113_write_t *write, const unsigned char pgm[5],
74 void *private_data, struct ak4113 **r_ak4113)
75{
76 struct ak4113 *chip;
77 int err = 0;
78 unsigned char reg;
79 static struct snd_device_ops ops = {
80 .dev_free = snd_ak4113_dev_free,
81 };
82
83 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
84 if (chip == NULL)
85 return -ENOMEM;
86 spin_lock_init(&chip->lock);
87 chip->card = card;
88 chip->read = read;
89 chip->write = write;
90 chip->private_data = private_data;
91 INIT_DELAYED_WORK(&chip->work, ak4113_stats);
92
93 for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
94 chip->regmap[reg] = pgm[reg];
95 ak4113_init_regs(chip);
96
97 chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT |
98 AK4113_CINT | AK4113_STC);
99 chip->rcs1 = reg_read(chip, AK4113_REG_RCS1);
100 chip->rcs2 = reg_read(chip, AK4113_REG_RCS2);
101 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
102 if (err < 0)
103 goto __fail;
104
105 if (r_ak4113)
106 *r_ak4113 = chip;
107 return 0;
108
109__fail:
110 snd_ak4113_free(chip);
111 return err < 0 ? err : -EIO;
112}
113EXPORT_SYMBOL_GPL(snd_ak4113_create);
114
115void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg,
116 unsigned char mask, unsigned char val)
117{
118 if (reg >= AK4113_WRITABLE_REGS)
119 return;
120 reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
121}
122EXPORT_SYMBOL_GPL(snd_ak4113_reg_write);
123
124static void ak4113_init_regs(struct ak4113 *chip)
125{
126 unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg;
127
128 /* bring the chip to reset state and powerdown state */
129 reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN));
130 udelay(200);
131 /* release reset, but leave powerdown */
132 reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN);
133 udelay(200);
134 for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++)
135 reg_write(chip, reg, chip->regmap[reg]);
136 /* release powerdown, everything is initialized now */
137 reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN);
138}
139
140void snd_ak4113_reinit(struct ak4113 *chip)
141{
142 chip->init = 1;
143 mb();
144 flush_scheduled_work();
145 ak4113_init_regs(chip);
146 /* bring up statistics / event queing */
147 chip->init = 0;
148 if (chip->kctls[0])
149 schedule_delayed_work(&chip->work, HZ / 10);
150}
151EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
152
153static unsigned int external_rate(unsigned char rcs1)
154{
155 switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) {
156 case AK4113_FS_8000HZ:
157 return 8000;
158 case AK4113_FS_11025HZ:
159 return 11025;
160 case AK4113_FS_16000HZ:
161 return 16000;
162 case AK4113_FS_22050HZ:
163 return 22050;
164 case AK4113_FS_24000HZ:
165 return 24000;
166 case AK4113_FS_32000HZ:
167 return 32000;
168 case AK4113_FS_44100HZ:
169 return 44100;
170 case AK4113_FS_48000HZ:
171 return 48000;
172 case AK4113_FS_64000HZ:
173 return 64000;
174 case AK4113_FS_88200HZ:
175 return 88200;
176 case AK4113_FS_96000HZ:
177 return 96000;
178 case AK4113_FS_176400HZ:
179 return 176400;
180 case AK4113_FS_192000HZ:
181 return 192000;
182 default:
183 return 0;
184 }
185}
186
187static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_info *uinfo)
189{
190 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
191 uinfo->count = 1;
192 uinfo->value.integer.min = 0;
193 uinfo->value.integer.max = LONG_MAX;
194 return 0;
195}
196
197static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol,
198 struct snd_ctl_elem_value *ucontrol)
199{
200 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
201 long *ptr;
202
203 spin_lock_irq(&chip->lock);
204 ptr = (long *)(((char *)chip) + kcontrol->private_value);
205 ucontrol->value.integer.value[0] = *ptr;
206 *ptr = 0;
207 spin_unlock_irq(&chip->lock);
208 return 0;
209}
210
211#define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info
212
213static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol,
214 struct snd_ctl_elem_value *ucontrol)
215{
216 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
217 unsigned char reg = kcontrol->private_value & 0xff;
218 unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
219 unsigned char inv = (kcontrol->private_value >> 31) & 1;
220
221 ucontrol->value.integer.value[0] =
222 ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv;
223 return 0;
224}
225
226static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol,
227 struct snd_ctl_elem_info *uinfo)
228{
229 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
230 uinfo->count = 1;
231 uinfo->value.integer.min = 0;
232 uinfo->value.integer.max = 5;
233 return 0;
234}
235
236static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol,
237 struct snd_ctl_elem_value *ucontrol)
238{
239 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
240
241 ucontrol->value.integer.value[0] =
242 (AK4113_IPS(chip->regmap[AK4113_REG_IO1]));
243 return 0;
244}
245
246static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol,
247 struct snd_ctl_elem_value *ucontrol)
248{
249 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
250 int change;
251 u8 old_val;
252
253 spin_lock_irq(&chip->lock);
254 old_val = chip->regmap[AK4113_REG_IO1];
255 change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val);
256 if (change)
257 reg_write(chip, AK4113_REG_IO1,
258 (old_val & (~AK4113_IPS(0xff))) |
259 (AK4113_IPS(ucontrol->value.integer.value[0])));
260 spin_unlock_irq(&chip->lock);
261 return change;
262}
263
264static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_info *uinfo)
266{
267 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
268 uinfo->count = 1;
269 uinfo->value.integer.min = 0;
270 uinfo->value.integer.max = 192000;
271 return 0;
272}
273
274static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol,
275 struct snd_ctl_elem_value *ucontrol)
276{
277 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
278
279 ucontrol->value.integer.value[0] = external_rate(reg_read(chip,
280 AK4113_REG_RCS1));
281 return 0;
282}
283
284static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_info *uinfo)
286{
287 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
288 uinfo->count = 1;
289 return 0;
290}
291
292static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol,
293 struct snd_ctl_elem_value *ucontrol)
294{
295 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
296 unsigned i;
297
298 for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++)
299 ucontrol->value.iec958.status[i] = reg_read(chip,
300 AK4113_REG_RXCSB0 + i);
301 return 0;
302}
303
304static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol,
305 struct snd_ctl_elem_info *uinfo)
306{
307 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
308 uinfo->count = 1;
309 return 0;
310}
311
312static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
314{
315 memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE);
316 return 0;
317}
318
319static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol,
320 struct snd_ctl_elem_info *uinfo)
321{
322 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
323 uinfo->value.integer.min = 0;
324 uinfo->value.integer.max = 0xffff;
325 uinfo->count = 4;
326 return 0;
327}
328
329static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
331{
332 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
333 unsigned short tmp;
334
335 ucontrol->value.integer.value[0] = 0xf8f2;
336 ucontrol->value.integer.value[1] = 0x4e1f;
337 tmp = reg_read(chip, AK4113_REG_Pc0) |
338 (reg_read(chip, AK4113_REG_Pc1) << 8);
339 ucontrol->value.integer.value[2] = tmp;
340 tmp = reg_read(chip, AK4113_REG_Pd0) |
341 (reg_read(chip, AK4113_REG_Pd1) << 8);
342 ucontrol->value.integer.value[3] = tmp;
343 return 0;
344}
345
346static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol,
347 struct snd_ctl_elem_info *uinfo)
348{
349 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
350 uinfo->count = AK4113_REG_QSUB_SIZE;
351 return 0;
352}
353
354static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
358 unsigned i;
359
360 for (i = 0; i < AK4113_REG_QSUB_SIZE; i++)
361 ucontrol->value.bytes.data[i] = reg_read(chip,
362 AK4113_REG_QSUB_ADDR + i);
363 return 0;
364}
365
366/* Don't forget to change AK4113_CONTROLS define!!! */
367static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
368{
369 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
370 .name = "IEC958 Parity Errors",
371 .access = SNDRV_CTL_ELEM_ACCESS_READ |
372 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
373 .info = snd_ak4113_in_error_info,
374 .get = snd_ak4113_in_error_get,
375 .private_value = offsetof(struct ak4113, parity_errors),
376},
377{
378 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
379 .name = "IEC958 V-Bit Errors",
380 .access = SNDRV_CTL_ELEM_ACCESS_READ |
381 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
382 .info = snd_ak4113_in_error_info,
383 .get = snd_ak4113_in_error_get,
384 .private_value = offsetof(struct ak4113, v_bit_errors),
385},
386{
387 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
388 .name = "IEC958 C-CRC Errors",
389 .access = SNDRV_CTL_ELEM_ACCESS_READ |
390 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
391 .info = snd_ak4113_in_error_info,
392 .get = snd_ak4113_in_error_get,
393 .private_value = offsetof(struct ak4113, ccrc_errors),
394},
395{
396 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
397 .name = "IEC958 Q-CRC Errors",
398 .access = SNDRV_CTL_ELEM_ACCESS_READ |
399 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
400 .info = snd_ak4113_in_error_info,
401 .get = snd_ak4113_in_error_get,
402 .private_value = offsetof(struct ak4113, qcrc_errors),
403},
404{
405 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
406 .name = "IEC958 External Rate",
407 .access = SNDRV_CTL_ELEM_ACCESS_READ |
408 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
409 .info = snd_ak4113_rate_info,
410 .get = snd_ak4113_rate_get,
411},
412{
413 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
414 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
415 .access = SNDRV_CTL_ELEM_ACCESS_READ,
416 .info = snd_ak4113_spdif_mask_info,
417 .get = snd_ak4113_spdif_mask_get,
418},
419{
420 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
421 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
422 .access = SNDRV_CTL_ELEM_ACCESS_READ |
423 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
424 .info = snd_ak4113_spdif_info,
425 .get = snd_ak4113_spdif_get,
426},
427{
428 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
429 .name = "IEC958 Preample Capture Default",
430 .access = SNDRV_CTL_ELEM_ACCESS_READ |
431 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
432 .info = snd_ak4113_spdif_pinfo,
433 .get = snd_ak4113_spdif_pget,
434},
435{
436 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
437 .name = "IEC958 Q-subcode Capture Default",
438 .access = SNDRV_CTL_ELEM_ACCESS_READ |
439 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
440 .info = snd_ak4113_spdif_qinfo,
441 .get = snd_ak4113_spdif_qget,
442},
443{
444 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
445 .name = "IEC958 Audio",
446 .access = SNDRV_CTL_ELEM_ACCESS_READ |
447 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
448 .info = snd_ak4113_in_bit_info,
449 .get = snd_ak4113_in_bit_get,
450 .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0,
451},
452{
453 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
454 .name = "IEC958 Non-PCM Bitstream",
455 .access = SNDRV_CTL_ELEM_ACCESS_READ |
456 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
457 .info = snd_ak4113_in_bit_info,
458 .get = snd_ak4113_in_bit_get,
459 .private_value = (0<<8) | AK4113_REG_RCS1,
460},
461{
462 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
463 .name = "IEC958 DTS Bitstream",
464 .access = SNDRV_CTL_ELEM_ACCESS_READ |
465 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
466 .info = snd_ak4113_in_bit_info,
467 .get = snd_ak4113_in_bit_get,
468 .private_value = (1<<8) | AK4113_REG_RCS1,
469},
470{
471 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
472 .name = "AK4113 Input Select",
473 .access = SNDRV_CTL_ELEM_ACCESS_READ |
474 SNDRV_CTL_ELEM_ACCESS_WRITE,
475 .info = snd_ak4113_rx_info,
476 .get = snd_ak4113_rx_get,
477 .put = snd_ak4113_rx_put,
478}
479};
480
481static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry,
482 struct snd_info_buffer *buffer)
483{
484 struct ak4113 *ak4113 = entry->private_data;
485 int reg, val;
486 /* all ak4113 registers 0x00 - 0x1c */
487 for (reg = 0; reg < 0x1d; reg++) {
488 val = reg_read(ak4113, reg);
489 snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
490 }
491}
492
493static void snd_ak4113_proc_init(struct ak4113 *ak4113)
494{
495 struct snd_info_entry *entry;
496 if (!snd_card_proc_new(ak4113->card, "ak4113", &entry))
497 snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read);
498}
499
500int snd_ak4113_build(struct ak4113 *ak4113,
501 struct snd_pcm_substream *cap_substream)
502{
503 struct snd_kcontrol *kctl;
504 unsigned int idx;
505 int err;
506
507 if (snd_BUG_ON(!cap_substream))
508 return -EINVAL;
509 ak4113->substream = cap_substream;
510 for (idx = 0; idx < AK4113_CONTROLS; idx++) {
511 kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113);
512 if (kctl == NULL)
513 return -ENOMEM;
514 kctl->id.device = cap_substream->pcm->device;
515 kctl->id.subdevice = cap_substream->number;
516 err = snd_ctl_add(ak4113->card, kctl);
517 if (err < 0)
518 return err;
519 ak4113->kctls[idx] = kctl;
520 }
521 snd_ak4113_proc_init(ak4113);
522 /* trigger workq */
523 schedule_delayed_work(&ak4113->work, HZ / 10);
524 return 0;
525}
526EXPORT_SYMBOL_GPL(snd_ak4113_build);
527
528int snd_ak4113_external_rate(struct ak4113 *ak4113)
529{
530 unsigned char rcs1;
531
532 rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
533 return external_rate(rcs1);
534}
535EXPORT_SYMBOL_GPL(snd_ak4113_external_rate);
536
537int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags)
538{
539 struct snd_pcm_runtime *runtime =
540 ak4113->substream ? ak4113->substream->runtime : NULL;
541 unsigned long _flags;
542 int res = 0;
543 unsigned char rcs0, rcs1, rcs2;
544 unsigned char c0, c1;
545
546 rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
547 if (flags & AK4113_CHECK_NO_STAT)
548 goto __rate;
549 rcs0 = reg_read(ak4113, AK4113_REG_RCS0);
550 rcs2 = reg_read(ak4113, AK4113_REG_RCS2);
551 spin_lock_irqsave(&ak4113->lock, _flags);
552 if (rcs0 & AK4113_PAR)
553 ak4113->parity_errors++;
554 if (rcs0 & AK4113_V)
555 ak4113->v_bit_errors++;
556 if (rcs2 & AK4113_CCRC)
557 ak4113->ccrc_errors++;
558 if (rcs2 & AK4113_QCRC)
559 ak4113->qcrc_errors++;
560 c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
561 AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^
562 (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
563 AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK));
564 c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
565 AK4113_DAT | 0xf0)) ^
566 (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
567 AK4113_DAT | 0xf0));
568 ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC);
569 ak4113->rcs1 = rcs1;
570 ak4113->rcs2 = rcs2;
571 spin_unlock_irqrestore(&ak4113->lock, _flags);
572
573 if (rcs0 & AK4113_PAR)
574 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
575 &ak4113->kctls[0]->id);
576 if (rcs0 & AK4113_V)
577 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
578 &ak4113->kctls[1]->id);
579 if (rcs2 & AK4113_CCRC)
580 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
581 &ak4113->kctls[2]->id);
582 if (rcs2 & AK4113_QCRC)
583 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
584 &ak4113->kctls[3]->id);
585
586 /* rate change */
587 if (c1 & 0xf0)
588 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
589 &ak4113->kctls[4]->id);
590
591 if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT))
592 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
593 &ak4113->kctls[6]->id);
594 if (c0 & AK4113_QINT)
595 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
596 &ak4113->kctls[8]->id);
597
598 if (c0 & AK4113_AUDION)
599 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
600 &ak4113->kctls[9]->id);
601 if (c1 & AK4113_NPCM)
602 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
603 &ak4113->kctls[10]->id);
604 if (c1 & AK4113_DTSCD)
605 snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
606 &ak4113->kctls[11]->id);
607
608 if (ak4113->change_callback && (c0 | c1) != 0)
609 ak4113->change_callback(ak4113, c0, c1);
610
611__rate:
612 /* compare rate */
613 res = external_rate(rcs1);
614 if (!(flags & AK4113_CHECK_NO_RATE) && runtime &&
615 (runtime->rate != res)) {
616 snd_pcm_stream_lock_irqsave(ak4113->substream, _flags);
617 if (snd_pcm_running(ak4113->substream)) {
618 /*printk(KERN_DEBUG "rate changed (%i <- %i)\n",
619 * runtime->rate, res); */
620 snd_pcm_stop(ak4113->substream,
621 SNDRV_PCM_STATE_DRAINING);
622 wake_up(&runtime->sleep);
623 res = 1;
624 }
625 snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags);
626 }
627 return res;
628}
629EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors);
630
631static void ak4113_stats(struct work_struct *work)
632{
633 struct ak4113 *chip = container_of(work, struct ak4113, work.work);
634
635 if (!chip->init)
636 snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
637
638 schedule_delayed_work(&chip->work, HZ / 10);
639}
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index ee47abab764e..1adb8a3c2b62 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -19,7 +19,7 @@
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * 21 *
22 */ 22 */
23 23
24#include <asm/io.h> 24#include <asm/io.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
@@ -29,6 +29,7 @@
29#include <sound/control.h> 29#include <sound/control.h>
30#include <sound/tlv.h> 30#include <sound/tlv.h>
31#include <sound/ak4xxx-adda.h> 31#include <sound/ak4xxx-adda.h>
32#include <sound/info.h>
32 33
33MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); 34MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
34MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); 35MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write);
52static void ak4524_reset(struct snd_akm4xxx *ak, int state) 53static void ak4524_reset(struct snd_akm4xxx *ak, int state)
53{ 54{
54 unsigned int chip; 55 unsigned int chip;
55 unsigned char reg, maxreg; 56 unsigned char reg;
56 57
57 if (ak->type == SND_AK4528)
58 maxreg = 0x06;
59 else
60 maxreg = 0x08;
61 for (chip = 0; chip < ak->num_dacs/2; chip++) { 58 for (chip = 0; chip < ak->num_dacs/2; chip++) {
62 snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); 59 snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03);
63 if (state) 60 if (state)
64 continue; 61 continue;
65 /* DAC volumes */ 62 /* DAC volumes */
66 for (reg = 0x04; reg < maxreg; reg++) 63 for (reg = 0x04; reg < ak->total_regs; reg++)
67 snd_akm4xxx_write(ak, chip, reg, 64 snd_akm4xxx_write(ak, chip, reg,
68 snd_akm4xxx_get(ak, chip, reg)); 65 snd_akm4xxx_get(ak, chip, reg));
69 } 66 }
70} 67}
71 68
72/* reset procedure for AK4355 and AK4358 */ 69/* reset procedure for AK4355 and AK4358 */
73static void ak435X_reset(struct snd_akm4xxx *ak, int state, 70static void ak435X_reset(struct snd_akm4xxx *ak, int state)
74 unsigned char total_regs)
75{ 71{
76 unsigned char reg; 72 unsigned char reg;
77 73
@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state,
79 snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ 75 snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
80 return; 76 return;
81 } 77 }
82 for (reg = 0x00; reg < total_regs; reg++) 78 for (reg = 0x00; reg < ak->total_regs; reg++)
83 if (reg != 0x01) 79 if (reg != 0x01)
84 snd_akm4xxx_write(ak, 0, reg, 80 snd_akm4xxx_write(ak, 0, reg,
85 snd_akm4xxx_get(ak, 0, reg)); 81 snd_akm4xxx_get(ak, 0, reg));
@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state)
91{ 87{
92 unsigned int chip; 88 unsigned int chip;
93 unsigned char reg; 89 unsigned char reg;
94
95 for (chip = 0; chip < ak->num_dacs/2; chip++) { 90 for (chip = 0; chip < ak->num_dacs/2; chip++) {
96 snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); 91 snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f);
97 if (state) 92 if (state)
98 continue; 93 continue;
99 for (reg = 0x01; reg < 0x05; reg++) 94 for (reg = 0x01; reg < ak->total_regs; reg++)
100 snd_akm4xxx_write(ak, chip, reg, 95 snd_akm4xxx_write(ak, chip, reg,
101 snd_akm4xxx_get(ak, chip, reg)); 96 snd_akm4xxx_get(ak, chip, reg));
102 } 97 }
@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
113 switch (ak->type) { 108 switch (ak->type) {
114 case SND_AK4524: 109 case SND_AK4524:
115 case SND_AK4528: 110 case SND_AK4528:
111 case SND_AK4620:
116 ak4524_reset(ak, state); 112 ak4524_reset(ak, state);
117 break; 113 break;
118 case SND_AK4529: 114 case SND_AK4529:
119 /* FIXME: needed for ak4529? */ 115 /* FIXME: needed for ak4529? */
120 break; 116 break;
121 case SND_AK4355: 117 case SND_AK4355:
122 ak435X_reset(ak, state, 0x0b); 118 ak435X_reset(ak, state);
123 break; 119 break;
124 case SND_AK4358: 120 case SND_AK4358:
125 ak435X_reset(ak, state, 0x10); 121 ak435X_reset(ak, state);
126 break; 122 break;
127 case SND_AK4381: 123 case SND_AK4381:
128 ak4381_reset(ak, state); 124 ak4381_reset(ak, state);
@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
139 * Volume conversion table for non-linear volumes 135 * Volume conversion table for non-linear volumes
140 * from -63.5dB (mute) to 0dB step 0.5dB 136 * from -63.5dB (mute) to 0dB step 0.5dB
141 * 137 *
142 * Used for AK4524 input/ouput attenuation, AK4528, and 138 * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and
143 * AK5365 input attenuation 139 * AK5365 input attenuation
144 */ 140 */
145static const unsigned char vol_cvt_datt[128] = { 141static const unsigned char vol_cvt_datt[128] = {
@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
259 0x00, 0x0f, /* 0: power-up, un-reset */ 255 0x00, 0x0f, /* 0: power-up, un-reset */
260 0xff, 0xff 256 0xff, 0xff
261 }; 257 };
258 static const unsigned char inits_ak4620[] = {
259 0x00, 0x07, /* 0: normal */
260 0x01, 0x00, /* 0: reset */
261 0x01, 0x02, /* 1: RSTAD */
262 0x01, 0x03, /* 1: RSTDA */
263 0x01, 0x0f, /* 1: normal */
264 0x02, 0x60, /* 2: 24bit I2S */
265 0x03, 0x01, /* 3: deemphasis off */
266 0x04, 0x00, /* 4: LIN muted */
267 0x05, 0x00, /* 5: RIN muted */
268 0x06, 0x00, /* 6: LOUT muted */
269 0x07, 0x00, /* 7: ROUT muted */
270 0xff, 0xff
271 };
262 272
263 int chip, num_chips; 273 int chip;
264 const unsigned char *ptr, *inits; 274 const unsigned char *ptr, *inits;
265 unsigned char reg, data; 275 unsigned char reg, data;
266 276
@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
270 switch (ak->type) { 280 switch (ak->type) {
271 case SND_AK4524: 281 case SND_AK4524:
272 inits = inits_ak4524; 282 inits = inits_ak4524;
273 num_chips = ak->num_dacs / 2; 283 ak->num_chips = ak->num_dacs / 2;
284 ak->name = "ak4524";
285 ak->total_regs = 0x08;
274 break; 286 break;
275 case SND_AK4528: 287 case SND_AK4528:
276 inits = inits_ak4528; 288 inits = inits_ak4528;
277 num_chips = ak->num_dacs / 2; 289 ak->num_chips = ak->num_dacs / 2;
290 ak->name = "ak4528";
291 ak->total_regs = 0x06;
278 break; 292 break;
279 case SND_AK4529: 293 case SND_AK4529:
280 inits = inits_ak4529; 294 inits = inits_ak4529;
281 num_chips = 1; 295 ak->num_chips = 1;
296 ak->name = "ak4529";
297 ak->total_regs = 0x0d;
282 break; 298 break;
283 case SND_AK4355: 299 case SND_AK4355:
284 inits = inits_ak4355; 300 inits = inits_ak4355;
285 num_chips = 1; 301 ak->num_chips = 1;
302 ak->name = "ak4355";
303 ak->total_regs = 0x0b;
286 break; 304 break;
287 case SND_AK4358: 305 case SND_AK4358:
288 inits = inits_ak4358; 306 inits = inits_ak4358;
289 num_chips = 1; 307 ak->num_chips = 1;
308 ak->name = "ak4358";
309 ak->total_regs = 0x10;
290 break; 310 break;
291 case SND_AK4381: 311 case SND_AK4381:
292 inits = inits_ak4381; 312 inits = inits_ak4381;
293 num_chips = ak->num_dacs / 2; 313 ak->num_chips = ak->num_dacs / 2;
314 ak->name = "ak4381";
315 ak->total_regs = 0x05;
294 break; 316 break;
295 case SND_AK5365: 317 case SND_AK5365:
296 /* FIXME: any init sequence? */ 318 /* FIXME: any init sequence? */
319 ak->num_chips = 1;
320 ak->name = "ak5365";
321 ak->total_regs = 0x08;
297 return; 322 return;
323 case SND_AK4620:
324 inits = inits_ak4620;
325 ak->num_chips = ak->num_dacs / 2;
326 ak->name = "ak4620";
327 ak->total_regs = 0x08;
328 break;
298 default: 329 default:
299 snd_BUG(); 330 snd_BUG();
300 return; 331 return;
301 } 332 }
302 333
303 for (chip = 0; chip < num_chips; chip++) { 334 for (chip = 0; chip < ak->num_chips; chip++) {
304 ptr = inits; 335 ptr = inits;
305 while (*ptr != 0xff) { 336 while (*ptr != 0xff) {
306 reg = *ptr++; 337 reg = *ptr++;
307 data = *ptr++; 338 data = *ptr++;
308 snd_akm4xxx_write(ak, chip, reg, data); 339 snd_akm4xxx_write(ak, chip, reg, data);
340 udelay(10);
309 } 341 }
310 } 342 }
311} 343}
@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
688 AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); 720 AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);
689 knew.tlv.p = db_scale_linear; 721 knew.tlv.p = db_scale_linear;
690 break; 722 break;
723 case SND_AK4620:
724 /* register 6 & 7 */
725 knew.private_value =
726 AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255);
727 knew.tlv.p = db_scale_linear;
728 break;
691 default: 729 default:
692 return -EINVAL; 730 return -EINVAL;
693 } 731 }
@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
704 742
705static int build_adc_controls(struct snd_akm4xxx *ak) 743static int build_adc_controls(struct snd_akm4xxx *ak)
706{ 744{
707 int idx, err, mixer_ch, num_stereo; 745 int idx, err, mixer_ch, num_stereo, max_steps;
708 struct snd_kcontrol_new knew; 746 struct snd_kcontrol_new knew;
709 747
710 mixer_ch = 0; 748 mixer_ch = 0;
749 if (ak->type == SND_AK4528)
750 return 0; /* no controls */
711 for (idx = 0; idx < ak->num_adcs;) { 751 for (idx = 0; idx < ak->num_adcs;) {
712 memset(&knew, 0, sizeof(knew)); 752 memset(&knew, 0, sizeof(knew));
713 if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { 753 if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) {
@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
733 } 773 }
734 /* register 4 & 5 */ 774 /* register 4 & 5 */
735 if (ak->type == SND_AK5365) 775 if (ak->type == SND_AK5365)
736 knew.private_value = 776 max_steps = 152;
737 AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) |
738 AK_VOL_CVT | AK_IPGA;
739 else 777 else
740 knew.private_value = 778 max_steps = 164;
741 AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | 779 knew.private_value =
742 AK_VOL_CVT | AK_IPGA; 780 AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) |
781 AK_VOL_CVT | AK_IPGA;
743 knew.tlv.p = db_scale_vol_datt; 782 knew.tlv.p = db_scale_vol_datt;
744 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); 783 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
745 if (err < 0) 784 if (err < 0)
@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
808 switch (ak->type) { 847 switch (ak->type) {
809 case SND_AK4524: 848 case SND_AK4524:
810 case SND_AK4528: 849 case SND_AK4528:
850 case SND_AK4620:
811 /* register 3 */ 851 /* register 3 */
812 knew.private_value = AK_COMPOSE(idx, 3, 0, 0); 852 knew.private_value = AK_COMPOSE(idx, 3, 0, 0);
813 break; 853 break;
@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
834 return 0; 874 return 0;
835} 875}
836 876
877#ifdef CONFIG_PROC_FS
878static void proc_regs_read(struct snd_info_entry *entry,
879 struct snd_info_buffer *buffer)
880{
881 struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data;
882 int reg, val, chip;
883 for (chip = 0; chip < ak->num_chips; chip++) {
884 for (reg = 0; reg < ak->total_regs; reg++) {
885 val = snd_akm4xxx_get(ak, chip, reg);
886 snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip,
887 reg, val);
888 }
889 }
890}
891
892static int proc_init(struct snd_akm4xxx *ak)
893{
894 struct snd_info_entry *entry;
895 int err;
896 err = snd_card_proc_new(ak->card, ak->name, &entry);
897 if (err < 0)
898 return err;
899 snd_info_set_text_ops(entry, ak, proc_regs_read);
900 return 0;
901}
902#else /* !CONFIG_PROC_FS */
903static int proc_init(struct snd_akm4xxx *ak) {}
904#endif
905
837int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) 906int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
838{ 907{
839 int err, num_emphs; 908 int err, num_emphs;
@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
845 err = build_adc_controls(ak); 914 err = build_adc_controls(ak);
846 if (err < 0) 915 if (err < 0)
847 return err; 916 return err;
848
849 if (ak->type == SND_AK4355 || ak->type == SND_AK4358) 917 if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
850 num_emphs = 1; 918 num_emphs = 1;
919 else if (ak->type == SND_AK4620)
920 num_emphs = 0;
851 else 921 else
852 num_emphs = ak->num_dacs / 2; 922 num_emphs = ak->num_dacs / 2;
853 err = build_deemphasis(ak, num_emphs); 923 err = build_deemphasis(ak, num_emphs);
854 if (err < 0) 924 if (err < 0)
855 return err; 925 return err;
926 err = proc_init(ak);
927 if (err < 0)
928 return err;
856 929
857 return 0; 930 return 0;
858} 931}
859
860EXPORT_SYMBOL(snd_akm4xxx_build_controls); 932EXPORT_SYMBOL(snd_akm4xxx_build_controls);
861 933
862static int __init alsa_akm4xxx_module_init(void) 934static int __init alsa_akm4xxx_module_init(void)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index d31c373e076d..c4c6ef73f9bf 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -225,7 +225,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
225 case V4L2_CID_AUDIO_MUTE: 225 case V4L2_CID_AUDIO_MUTE:
226 if (tea->ops->mute) { 226 if (tea->ops->mute) {
227 tea->ops->mute(tea, ctrl->value); 227 tea->ops->mute(tea, ctrl->value);
228 tea->mute = 1; 228 tea->mute = ctrl->value;
229 return 0; 229 return 0;
230 } 230 }
231 } 231 }
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 51a7e3777e17..02fe81ca88fd 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -372,15 +372,21 @@ config SND_SGALAXY
372 372
373config SND_SSCAPE 373config SND_SSCAPE
374 tristate "Ensoniq SoundScape driver" 374 tristate "Ensoniq SoundScape driver"
375 select SND_HWDEP
376 select SND_MPU401_UART 375 select SND_MPU401_UART
377 select SND_WSS_LIB 376 select SND_WSS_LIB
377 select FW_LOADER
378 help 378 help
379 Say Y here to include support for Ensoniq SoundScape 379 Say Y here to include support for Ensoniq SoundScape
380 soundcards. 380 and Ensoniq OEM soundcards.
381 381
382 The PCM audio is supported on SoundScape Classic, Elite, PnP 382 The PCM audio is supported on SoundScape Classic, Elite, PnP
383 and VIVO cards. The MIDI support is very experimental. 383 and VIVO cards. The supported OEM cards are SPEA Media FX and
384 Reveal SC-600.
385 The MIDI support is very experimental and requires binary
386 firmware files called "scope.cod" and "sndscape.co?" where the
387 ? is digit 0, 1, 2, 3 or 4. The firmware files can be found
388 in DOS or Windows driver packages. One has to put the firmware
389 files into the /lib/firmware directory.
384 390
385 To compile this driver as a module, choose M here: the module 391 To compile this driver as a module, choose M here: the module
386 will be called snd-sscape. 392 will be called snd-sscape.
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 02f79d252718..8246aae32ab4 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -237,7 +237,7 @@ WSS_DOUBLE("Wavetable Capture Volume", 0,
237 CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), 237 CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
238WSS_SINGLE("3D Control - Switch", 0, 238WSS_SINGLE("3D Control - Switch", 0,
239 CMI8330_RMUX3D, 5, 1, 1), 239 CMI8330_RMUX3D, 5, 1, 1),
240WSS_SINGLE("PC Speaker Playback Volume", 0, 240WSS_SINGLE("Beep Playback Volume", 0,
241 CMI8330_OUTPUTVOL, 3, 3, 0), 241 CMI8330_OUTPUTVOL, 3, 3, 0),
242WSS_DOUBLE("FM Playback Switch", 0, 242WSS_DOUBLE("FM Playback Switch", 0,
243 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 243 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
@@ -262,7 +262,7 @@ SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3,
262SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), 262SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
263SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), 263SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
264SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), 264SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
265SB_SINGLE("SB PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3), 265SB_SINGLE("SB Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
266SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), 266SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
267SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), 267SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
268SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), 268SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index a076a6ce8071..93fa6720d197 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -394,21 +394,15 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
394 return -EBUSY; 394 return -EBUSY;
395 } 395 }
396 396
397 err = snd_wss_create(card, port[dev], cport[dev], 397 err = snd_cs4236_create(card, port[dev], cport[dev],
398 irq[dev], 398 irq[dev],
399 dma1[dev], dma2[dev], 399 dma1[dev], dma2[dev],
400 WSS_HW_DETECT3, 0, &chip); 400 WSS_HW_DETECT3, 0, &chip);
401 if (err < 0) 401 if (err < 0)
402 return err; 402 return err;
403
404 acard->chip = chip;
403 if (chip->hardware & WSS_HW_CS4236B_MASK) { 405 if (chip->hardware & WSS_HW_CS4236B_MASK) {
404 snd_wss_free(chip);
405 err = snd_cs4236_create(card,
406 port[dev], cport[dev],
407 irq[dev], dma1[dev], dma2[dev],
408 WSS_HW_DETECT, 0, &chip);
409 if (err < 0)
410 return err;
411 acard->chip = chip;
412 406
413 err = snd_cs4236_pcm(chip, 0, &pcm); 407 err = snd_cs4236_pcm(chip, 0, &pcm);
414 if (err < 0) 408 if (err < 0)
@@ -418,7 +412,6 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
418 if (err < 0) 412 if (err < 0)
419 return err; 413 return err;
420 } else { 414 } else {
421 acard->chip = chip;
422 err = snd_wss_pcm(chip, 0, &pcm); 415 err = snd_wss_pcm(chip, 0, &pcm);
423 if (err < 0) 416 if (err < 0)
424 return err; 417 return err;
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 38835f31298b..c5adca300632 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -87,6 +87,8 @@
87#include <sound/core.h> 87#include <sound/core.h>
88#include <sound/wss.h> 88#include <sound/wss.h>
89#include <sound/asoundef.h> 89#include <sound/asoundef.h>
90#include <sound/initval.h>
91#include <sound/tlv.h>
90 92
91/* 93/*
92 * 94 *
@@ -264,7 +266,10 @@ static void snd_cs4236_resume(struct snd_wss *chip)
264} 266}
265 267
266#endif /* CONFIG_PM */ 268#endif /* CONFIG_PM */
267 269/*
270 * This function does no fail if the chip is not CS4236B or compatible.
271 * It just an equivalent to the snd_wss_create() then.
272 */
268int snd_cs4236_create(struct snd_card *card, 273int snd_cs4236_create(struct snd_card *card,
269 unsigned long port, 274 unsigned long port,
270 unsigned long cport, 275 unsigned long cport,
@@ -281,21 +286,17 @@ int snd_cs4236_create(struct snd_card *card,
281 *rchip = NULL; 286 *rchip = NULL;
282 if (hardware == WSS_HW_DETECT) 287 if (hardware == WSS_HW_DETECT)
283 hardware = WSS_HW_DETECT3; 288 hardware = WSS_HW_DETECT3;
284 if (cport < 0x100) { 289
285 snd_printk(KERN_ERR "please, specify control port "
286 "for CS4236+ chips\n");
287 return -ENODEV;
288 }
289 err = snd_wss_create(card, port, cport, 290 err = snd_wss_create(card, port, cport,
290 irq, dma1, dma2, hardware, hwshare, &chip); 291 irq, dma1, dma2, hardware, hwshare, &chip);
291 if (err < 0) 292 if (err < 0)
292 return err; 293 return err;
293 294
294 if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { 295 if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) {
295 snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers " 296 snd_printd("chip is not CS4236+, hardware=0x%x\n",
296 "not available, hardware=0x%x\n", chip->hardware); 297 chip->hardware);
297 snd_device_free(card, chip); 298 *rchip = chip;
298 return -ENODEV; 299 return 0;
299 } 300 }
300#if 0 301#if 0
301 { 302 {
@@ -308,9 +309,16 @@ int snd_cs4236_create(struct snd_card *card,
308 idx, snd_cs4236_ctrl_in(chip, idx)); 309 idx, snd_cs4236_ctrl_in(chip, idx));
309 } 310 }
310#endif 311#endif
312 if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
313 snd_printk(KERN_ERR "please, specify control port "
314 "for CS4236+ chips\n");
315 snd_device_free(card, chip);
316 return -ENODEV;
317 }
311 ver1 = snd_cs4236_ctrl_in(chip, 1); 318 ver1 = snd_cs4236_ctrl_in(chip, 1);
312 ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); 319 ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
313 snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2); 320 snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n",
321 cport, ver1, ver2);
314 if (ver1 != ver2) { 322 if (ver1 != ver2) {
315 snd_printk(KERN_ERR "CS4236+ chip detected, but " 323 snd_printk(KERN_ERR "CS4236+ chip detected, but "
316 "control port 0x%lx is not valid\n", cport); 324 "control port 0x%lx is not valid\n", cport);
@@ -321,13 +329,17 @@ int snd_cs4236_create(struct snd_card *card,
321 snd_cs4236_ctrl_out(chip, 2, 0xff); 329 snd_cs4236_ctrl_out(chip, 2, 0xff);
322 snd_cs4236_ctrl_out(chip, 3, 0x00); 330 snd_cs4236_ctrl_out(chip, 3, 0x00);
323 snd_cs4236_ctrl_out(chip, 4, 0x80); 331 snd_cs4236_ctrl_out(chip, 4, 0x80);
324 snd_cs4236_ctrl_out(chip, 5, ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | IEC958_AES0_CON_EMPHASIS_NONE); 332 reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) |
333 IEC958_AES0_CON_EMPHASIS_NONE;
334 snd_cs4236_ctrl_out(chip, 5, reg);
325 snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2); 335 snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
326 snd_cs4236_ctrl_out(chip, 7, 0x00); 336 snd_cs4236_ctrl_out(chip, 7, 0x00);
327 /* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 output */ 337 /*
328 /* is working with this setup, other hardware should have */ 338 * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958
329 /* different signal paths and this value should be selectable */ 339 * output is working with this setup, other hardware should
330 /* in the future */ 340 * have different signal paths and this value should be
341 * selectable in the future
342 */
331 snd_cs4236_ctrl_out(chip, 8, 0x8c); 343 snd_cs4236_ctrl_out(chip, 8, 0x8c);
332 chip->rate_constraint = snd_cs4236_xrate; 344 chip->rate_constraint = snd_cs4236_xrate;
333 chip->set_playback_format = snd_cs4236_playback_format; 345 chip->set_playback_format = snd_cs4236_playback_format;
@@ -339,9 +351,10 @@ int snd_cs4236_create(struct snd_card *card,
339 351
340 /* initialize extended registers */ 352 /* initialize extended registers */
341 for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++) 353 for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
342 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]); 354 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg),
355 snd_cs4236_ext_map[reg]);
343 356
344 /* initialize compatible but more featured registers */ 357 /* initialize compatible but more featured registers */
345 snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40); 358 snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
346 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40); 359 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
347 snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); 360 snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
@@ -387,6 +400,14 @@ int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
387 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ 400 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
388 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 401 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
389 402
403#define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
404{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
405 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
406 .info = snd_cs4236_info_single, \
407 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
408 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
409 .tlv = { .p = (xtlv) } }
410
390static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 411static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
391{ 412{
392 int mask = (kcontrol->private_value >> 16) & 0xff; 413 int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -490,6 +511,16 @@ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_
490 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ 511 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
491 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 512 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
492 513
514#define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
515 shift_right, mask, invert, xtlv) \
516{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
517 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
518 .info = snd_cs4236_info_double, \
519 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
520 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
521 (shift_right << 19) | (mask << 24) | (invert << 22), \
522 .tlv = { .p = (xtlv) } }
523
493static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 524static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
494{ 525{
495 int mask = (kcontrol->private_value >> 24) & 0xff; 526 int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -560,12 +591,23 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
560 return change; 591 return change;
561} 592}
562 593
563#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ 594#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
595 shift_right, mask, invert) \
564{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 596{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
565 .info = snd_cs4236_info_double, \ 597 .info = snd_cs4236_info_double, \
566 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ 598 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
567 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 599 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
568 600
601#define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
602 shift_right, mask, invert, xtlv) \
603{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
604 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
605 .info = snd_cs4236_info_double, \
606 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
607 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
608 (shift_right << 19) | (mask << 24) | (invert << 22), \
609 .tlv = { .p = (xtlv) } }
610
569static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 611static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
570{ 612{
571 struct snd_wss *chip = snd_kcontrol_chip(kcontrol); 613 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
@@ -619,16 +661,18 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_
619 return change; 661 return change;
620} 662}
621 663
622#define CS4236_MASTER_DIGITAL(xname, xindex) \ 664#define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
623{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 665{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
666 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
624 .info = snd_cs4236_info_double, \ 667 .info = snd_cs4236_info_double, \
625 .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \ 668 .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
626 .private_value = 71 << 24 } 669 .private_value = 71 << 24, \
670 .tlv = { .p = (xtlv) } }
627 671
628static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) 672static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
629{ 673{
630 return (vol < 64) ? 63 - vol : 64 + (71 - vol); 674 return (vol < 64) ? 63 - vol : 64 + (71 - vol);
631} 675}
632 676
633static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 677static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
634{ 678{
@@ -661,11 +705,13 @@ static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct s
661 return change; 705 return change;
662} 706}
663 707
664#define CS4235_OUTPUT_ACCU(xname, xindex) \ 708#define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
665{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 709{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
710 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
666 .info = snd_cs4236_info_double, \ 711 .info = snd_cs4236_info_double, \
667 .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \ 712 .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
668 .private_value = 3 << 24 } 713 .private_value = 3 << 24, \
714 .tlv = { .p = (xtlv) } }
669 715
670static inline int snd_cs4235_mixer_output_accu_get_volume(int vol) 716static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
671{ 717{
@@ -720,41 +766,56 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_
720 return change; 766 return change;
721} 767}
722 768
769static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
770static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
771static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
772static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
773static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
774static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
775static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
776static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
777
723static struct snd_kcontrol_new snd_cs4236_controls[] = { 778static struct snd_kcontrol_new snd_cs4236_controls[] = {
724 779
725CS4236_DOUBLE("Master Digital Playback Switch", 0, 780CS4236_DOUBLE("Master Digital Playback Switch", 0,
726 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), 781 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
727CS4236_DOUBLE("Master Digital Capture Switch", 0, 782CS4236_DOUBLE("Master Digital Capture Switch", 0,
728 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), 783 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
729CS4236_MASTER_DIGITAL("Master Digital Volume", 0), 784CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
730 785
731CS4236_DOUBLE("Capture Boost Volume", 0, 786CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
732 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 787 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
788 db_scale_2bit),
733 789
734WSS_DOUBLE("PCM Playback Switch", 0, 790WSS_DOUBLE("PCM Playback Switch", 0,
735 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 791 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
736WSS_DOUBLE("PCM Playback Volume", 0, 792WSS_DOUBLE_TLV("PCM Playback Volume", 0,
737 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 793 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
794 db_scale_6bit),
738 795
739CS4236_DOUBLE("DSP Playback Switch", 0, 796CS4236_DOUBLE("DSP Playback Switch", 0,
740 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 797 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
741CS4236_DOUBLE("DSP Playback Volume", 0, 798CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
742 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1), 799 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
800 db_scale_6bit),
743 801
744CS4236_DOUBLE("FM Playback Switch", 0, 802CS4236_DOUBLE("FM Playback Switch", 0,
745 CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), 803 CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
746CS4236_DOUBLE("FM Playback Volume", 0, 804CS4236_DOUBLE_TLV("FM Playback Volume", 0,
747 CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1), 805 CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
806 db_scale_6bit),
748 807
749CS4236_DOUBLE("Wavetable Playback Switch", 0, 808CS4236_DOUBLE("Wavetable Playback Switch", 0,
750 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), 809 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
751CS4236_DOUBLE("Wavetable Playback Volume", 0, 810CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
752 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), 811 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
812 db_scale_6bit_12db_max),
753 813
754WSS_DOUBLE("Synth Playback Switch", 0, 814WSS_DOUBLE("Synth Playback Switch", 0,
755 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 815 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
756WSS_DOUBLE("Synth Volume", 0, 816WSS_DOUBLE_TLV("Synth Volume", 0,
757 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 817 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
818 db_scale_5bit_12db_max),
758WSS_DOUBLE("Synth Capture Switch", 0, 819WSS_DOUBLE("Synth Capture Switch", 0,
759 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 820 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
760WSS_DOUBLE("Synth Capture Bypass", 0, 821WSS_DOUBLE("Synth Capture Bypass", 0,
@@ -764,14 +825,16 @@ CS4236_DOUBLE("Mic Playback Switch", 0,
764 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 825 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
765CS4236_DOUBLE("Mic Capture Switch", 0, 826CS4236_DOUBLE("Mic Capture Switch", 0,
766 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 827 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
767CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), 828CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
768CS4236_DOUBLE("Mic Playback Boost", 0, 829 0, 0, 31, 1, db_scale_5bit_22db_max),
830CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
769 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), 831 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
770 832
771WSS_DOUBLE("Line Playback Switch", 0, 833WSS_DOUBLE("Line Playback Switch", 0,
772 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 834 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
773WSS_DOUBLE("Line Volume", 0, 835WSS_DOUBLE_TLV("Line Volume", 0,
774 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 836 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
837 db_scale_5bit_12db_max),
775WSS_DOUBLE("Line Capture Switch", 0, 838WSS_DOUBLE("Line Capture Switch", 0,
776 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 839 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
777WSS_DOUBLE("Line Capture Bypass", 0, 840WSS_DOUBLE("Line Capture Bypass", 0,
@@ -779,57 +842,63 @@ WSS_DOUBLE("Line Capture Bypass", 0,
779 842
780WSS_DOUBLE("CD Playback Switch", 0, 843WSS_DOUBLE("CD Playback Switch", 0,
781 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 844 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
782WSS_DOUBLE("CD Volume", 0, 845WSS_DOUBLE_TLV("CD Volume", 0,
783 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 846 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
847 db_scale_5bit_12db_max),
784WSS_DOUBLE("CD Capture Switch", 0, 848WSS_DOUBLE("CD Capture Switch", 0,
785 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 849 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
786 850
787CS4236_DOUBLE1("Mono Output Playback Switch", 0, 851CS4236_DOUBLE1("Mono Output Playback Switch", 0,
788 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), 852 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
789CS4236_DOUBLE1("Mono Playback Switch", 0, 853CS4236_DOUBLE1("Beep Playback Switch", 0,
790 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 854 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
791WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 855WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
792WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), 856 db_scale_4bit),
857WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
793 858
794WSS_DOUBLE("Capture Volume", 0, 859WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
795 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), 860 0, 0, 15, 0, db_scale_rec_gain),
796WSS_DOUBLE("Analog Loopback Capture Switch", 0, 861WSS_DOUBLE("Analog Loopback Capture Switch", 0,
797 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 862 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
798 863
799WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), 864WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
800CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, 865CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
801 CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) 866 CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
867 db_scale_6bit),
802}; 868};
803 869
870static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
871static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
872
804static struct snd_kcontrol_new snd_cs4235_controls[] = { 873static struct snd_kcontrol_new snd_cs4235_controls[] = {
805 874
806WSS_DOUBLE("Master Switch", 0, 875WSS_DOUBLE("Master Playback Switch", 0,
807 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), 876 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
808WSS_DOUBLE("Master Volume", 0, 877WSS_DOUBLE_TLV("Master Playback Volume", 0,
809 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), 878 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
810 879 db_scale_5bit_6db_max),
811CS4235_OUTPUT_ACCU("Playback Volume", 0),
812 880
813CS4236_DOUBLE("Master Digital Playback Switch", 0, 881CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
814 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
815CS4236_DOUBLE("Master Digital Capture Switch", 0,
816 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
817CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
818 882
819WSS_DOUBLE("Master Digital Playback Switch", 1, 883WSS_DOUBLE("Synth Playback Switch", 1,
820 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 884 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
821WSS_DOUBLE("Master Digital Capture Switch", 1, 885WSS_DOUBLE("Synth Capture Switch", 1,
822 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 886 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
823WSS_DOUBLE("Master Digital Volume", 1, 887WSS_DOUBLE_TLV("Synth Volume", 1,
824 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 888 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
889 db_scale_5bit_12db_max),
825 890
826CS4236_DOUBLE("Capture Volume", 0, 891CS4236_DOUBLE_TLV("Capture Volume", 0,
827 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 892 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
893 db_scale_2bit),
828 894
829WSS_DOUBLE("PCM Switch", 0, 895WSS_DOUBLE("PCM Playback Switch", 0,
830 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 896 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
831WSS_DOUBLE("PCM Volume", 0, 897WSS_DOUBLE("PCM Capture Switch", 0,
832 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 898 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
899WSS_DOUBLE_TLV("PCM Volume", 0,
900 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
901 db_scale_6bit),
833 902
834CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 903CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
835 904
@@ -842,29 +911,29 @@ CS4236_DOUBLE("Mic Capture Switch", 0,
842 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 911 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
843CS4236_DOUBLE("Mic Playback Switch", 0, 912CS4236_DOUBLE("Mic Playback Switch", 0,
844 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 913 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
845CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), 914CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
846CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), 915 db_scale_5bit_22db_max),
916CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
847 917
848WSS_DOUBLE("Aux Playback Switch", 0, 918WSS_DOUBLE("Line Playback Switch", 0,
849 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 919 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
850WSS_DOUBLE("Aux Capture Switch", 0, 920WSS_DOUBLE("Line Capture Switch", 0,
851 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 921 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
852WSS_DOUBLE("Aux Volume", 0, 922WSS_DOUBLE_TLV("Line Volume", 0,
853 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 923 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
924 db_scale_5bit_12db_max),
854 925
855WSS_DOUBLE("Aux Playback Switch", 1, 926WSS_DOUBLE("CD Playback Switch", 1,
856 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 927 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
857WSS_DOUBLE("Aux Capture Switch", 1, 928WSS_DOUBLE("CD Capture Switch", 1,
858 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 929 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
859WSS_DOUBLE("Aux Volume", 1, 930WSS_DOUBLE_TLV("CD Volume", 1,
860 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 931 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
861 932 db_scale_5bit_12db_max),
862CS4236_DOUBLE1("Master Mono Switch", 0,
863 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
864 933
865CS4236_DOUBLE1("Mono Switch", 0, 934CS4236_DOUBLE1("Beep Playback Switch", 0,
866 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 935 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
867WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 936WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
868 937
869WSS_DOUBLE("Analog Loopback Switch", 0, 938WSS_DOUBLE("Analog Loopback Switch", 0,
870 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 939 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 4c6e14f87f2d..c76bb00c9d15 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -982,7 +982,7 @@ ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0
982ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0), 982ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
983ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0), 983ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
984ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0), 984ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
985ES1688_SINGLE("PC Speaker Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0), 985ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
986ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0), 986ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
987ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1), 987ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
988{ 988{
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 8cfbff73a835..9a43baae7250 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -102,8 +102,6 @@
102 102
103struct snd_es18xx { 103struct snd_es18xx {
104 unsigned long port; /* port of ESS chip */ 104 unsigned long port; /* port of ESS chip */
105 unsigned long mpu_port; /* MPU-401 port of ESS chip */
106 unsigned long fm_port; /* FM port */
107 unsigned long ctrl_port; /* Control port of ESS chip */ 105 unsigned long ctrl_port; /* Control port of ESS chip */
108 struct resource *res_port; 106 struct resource *res_port;
109 struct resource *res_mpu_port; 107 struct resource *res_mpu_port;
@@ -116,12 +114,9 @@ struct snd_es18xx {
116 unsigned short audio2_vol; /* volume level of audio2 */ 114 unsigned short audio2_vol; /* volume level of audio2 */
117 115
118 unsigned short active; /* active channel mask */ 116 unsigned short active; /* active channel mask */
119 unsigned int dma1_size;
120 unsigned int dma2_size;
121 unsigned int dma1_shift; 117 unsigned int dma1_shift;
122 unsigned int dma2_shift; 118 unsigned int dma2_shift;
123 119
124 struct snd_card *card;
125 struct snd_pcm *pcm; 120 struct snd_pcm *pcm;
126 struct snd_pcm_substream *playback_a_substream; 121 struct snd_pcm_substream *playback_a_substream;
127 struct snd_pcm_substream *capture_a_substream; 122 struct snd_pcm_substream *capture_a_substream;
@@ -136,14 +131,9 @@ struct snd_es18xx {
136 131
137 spinlock_t reg_lock; 132 spinlock_t reg_lock;
138 spinlock_t mixer_lock; 133 spinlock_t mixer_lock;
139 spinlock_t ctrl_lock;
140#ifdef CONFIG_PM 134#ifdef CONFIG_PM
141 unsigned char pm_reg; 135 unsigned char pm_reg;
142#endif 136#endif
143};
144
145struct snd_audiodrive {
146 struct snd_es18xx *chip;
147#ifdef CONFIG_PNP 137#ifdef CONFIG_PNP
148 struct pnp_dev *dev; 138 struct pnp_dev *dev;
149 struct pnp_dev *devc; 139 struct pnp_dev *devc;
@@ -359,7 +349,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
359} 349}
360 350
361 351
362static int snd_es18xx_reset(struct snd_es18xx *chip) 352static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
363{ 353{
364 int i; 354 int i;
365 outb(0x03, chip->port + 0x06); 355 outb(0x03, chip->port + 0x06);
@@ -495,8 +485,6 @@ static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip,
495 unsigned int size = snd_pcm_lib_buffer_bytes(substream); 485 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
496 unsigned int count = snd_pcm_lib_period_bytes(substream); 486 unsigned int count = snd_pcm_lib_period_bytes(substream);
497 487
498 chip->dma2_size = size;
499
500 snd_es18xx_rate_set(chip, substream, DAC2); 488 snd_es18xx_rate_set(chip, substream, DAC2);
501 489
502 /* Transfer Count Reload */ 490 /* Transfer Count Reload */
@@ -596,8 +584,6 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
596 unsigned int size = snd_pcm_lib_buffer_bytes(substream); 584 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
597 unsigned int count = snd_pcm_lib_period_bytes(substream); 585 unsigned int count = snd_pcm_lib_period_bytes(substream);
598 586
599 chip->dma1_size = size;
600
601 snd_es18xx_reset_fifo(chip); 587 snd_es18xx_reset_fifo(chip);
602 588
603 /* Set stereo/mono */ 589 /* Set stereo/mono */
@@ -664,8 +650,6 @@ static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
664 unsigned int size = snd_pcm_lib_buffer_bytes(substream); 650 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
665 unsigned int count = snd_pcm_lib_period_bytes(substream); 651 unsigned int count = snd_pcm_lib_period_bytes(substream);
666 652
667 chip->dma1_size = size;
668
669 snd_es18xx_reset_fifo(chip); 653 snd_es18xx_reset_fifo(chip);
670 654
671 /* Set stereo/mono */ 655 /* Set stereo/mono */
@@ -755,7 +739,8 @@ static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream,
755 739
756static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id) 740static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
757{ 741{
758 struct snd_es18xx *chip = dev_id; 742 struct snd_card *card = dev_id;
743 struct snd_es18xx *chip = card->private_data;
759 unsigned char status; 744 unsigned char status;
760 745
761 if (chip->caps & ES18XX_CONTROL) { 746 if (chip->caps & ES18XX_CONTROL) {
@@ -805,12 +790,16 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
805 int split = 0; 790 int split = 0;
806 if (chip->caps & ES18XX_HWV) { 791 if (chip->caps & ES18XX_HWV) {
807 split = snd_es18xx_mixer_read(chip, 0x64) & 0x80; 792 split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
808 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id); 793 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
809 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id); 794 &chip->hw_switch->id);
795 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
796 &chip->hw_volume->id);
810 } 797 }
811 if (!split) { 798 if (!split) {
812 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id); 799 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
813 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id); 800 &chip->master_switch->id);
801 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
802 &chip->master_volume->id);
814 } 803 }
815 /* ack interrupt */ 804 /* ack interrupt */
816 snd_es18xx_mixer_write(chip, 0x66, 0x00); 805 snd_es18xx_mixer_write(chip, 0x66, 0x00);
@@ -821,17 +810,18 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
821static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream) 810static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream)
822{ 811{
823 struct snd_es18xx *chip = snd_pcm_substream_chip(substream); 812 struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
813 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
824 int pos; 814 int pos;
825 815
826 if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { 816 if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
827 if (!(chip->active & DAC2)) 817 if (!(chip->active & DAC2))
828 return 0; 818 return 0;
829 pos = snd_dma_pointer(chip->dma2, chip->dma2_size); 819 pos = snd_dma_pointer(chip->dma2, size);
830 return pos >> chip->dma2_shift; 820 return pos >> chip->dma2_shift;
831 } else { 821 } else {
832 if (!(chip->active & DAC1)) 822 if (!(chip->active & DAC1))
833 return 0; 823 return 0;
834 pos = snd_dma_pointer(chip->dma1, chip->dma1_size); 824 pos = snd_dma_pointer(chip->dma1, size);
835 return pos >> chip->dma1_shift; 825 return pos >> chip->dma1_shift;
836 } 826 }
837} 827}
@@ -839,11 +829,12 @@ static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *s
839static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream) 829static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream)
840{ 830{
841 struct snd_es18xx *chip = snd_pcm_substream_chip(substream); 831 struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
832 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
842 int pos; 833 int pos;
843 834
844 if (!(chip->active & ADC1)) 835 if (!(chip->active & ADC1))
845 return 0; 836 return 0;
846 pos = snd_dma_pointer(chip->dma1, chip->dma1_size); 837 pos = snd_dma_pointer(chip->dma1, size);
847 return pos >> chip->dma1_shift; 838 return pos >> chip->dma1_shift;
848} 839}
849 840
@@ -974,9 +965,6 @@ static int snd_es18xx_capture_close(struct snd_pcm_substream *substream)
974 965
975static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 966static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
976{ 967{
977 static char *texts4Source[4] = {
978 "Mic", "CD", "Line", "Master"
979 };
980 static char *texts5Source[5] = { 968 static char *texts5Source[5] = {
981 "Mic", "CD", "Line", "Master", "Mix" 969 "Mic", "CD", "Line", "Master", "Mix"
982 }; 970 };
@@ -994,7 +982,8 @@ static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
994 uinfo->value.enumerated.items = 4; 982 uinfo->value.enumerated.items = 4;
995 if (uinfo->value.enumerated.item > 3) 983 if (uinfo->value.enumerated.item > 3)
996 uinfo->value.enumerated.item = 3; 984 uinfo->value.enumerated.item = 3;
997 strcpy(uinfo->value.enumerated.name, texts4Source[uinfo->value.enumerated.item]); 985 strcpy(uinfo->value.enumerated.name,
986 texts5Source[uinfo->value.enumerated.item]);
998 break; 987 break;
999 case 0x1887: 988 case 0x1887:
1000 case 0x1888: 989 case 0x1888:
@@ -1313,7 +1302,7 @@ ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
1313 * The chipset specific mixer controls 1302 * The chipset specific mixer controls
1314 */ 1303 */
1315static struct snd_kcontrol_new snd_es18xx_opt_speaker = 1304static struct snd_kcontrol_new snd_es18xx_opt_speaker =
1316 ES18XX_SINGLE("PC Speaker Playback Volume", 0, 0x3c, 0, 7, 0); 1305 ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
1317 1306
1318static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { 1307static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
1319ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), 1308ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
@@ -1378,11 +1367,9 @@ ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
1378static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) 1367static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
1379{ 1368{
1380 int data; 1369 int data;
1381 unsigned long flags; 1370
1382 spin_lock_irqsave(&chip->ctrl_lock, flags);
1383 outb(reg, chip->ctrl_port); 1371 outb(reg, chip->ctrl_port);
1384 data = inb(chip->ctrl_port + 1); 1372 data = inb(chip->ctrl_port + 1);
1385 spin_unlock_irqrestore(&chip->ctrl_lock, flags);
1386 return data; 1373 return data;
1387} 1374}
1388 1375
@@ -1398,7 +1385,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
1398#endif 1385#endif
1399} 1386}
1400 1387
1401static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip) 1388static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
1389 unsigned long mpu_port,
1390 unsigned long fm_port)
1402{ 1391{
1403 int mask = 0; 1392 int mask = 0;
1404 1393
@@ -1412,15 +1401,15 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
1412 if (chip->caps & ES18XX_CONTROL) { 1401 if (chip->caps & ES18XX_CONTROL) {
1413 /* Hardware volume IRQ */ 1402 /* Hardware volume IRQ */
1414 snd_es18xx_config_write(chip, 0x27, chip->irq); 1403 snd_es18xx_config_write(chip, 0x27, chip->irq);
1415 if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) { 1404 if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
1416 /* FM I/O */ 1405 /* FM I/O */
1417 snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8); 1406 snd_es18xx_config_write(chip, 0x62, fm_port >> 8);
1418 snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff); 1407 snd_es18xx_config_write(chip, 0x63, fm_port & 0xff);
1419 } 1408 }
1420 if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { 1409 if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
1421 /* MPU-401 I/O */ 1410 /* MPU-401 I/O */
1422 snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8); 1411 snd_es18xx_config_write(chip, 0x64, mpu_port >> 8);
1423 snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff); 1412 snd_es18xx_config_write(chip, 0x65, mpu_port & 0xff);
1424 /* MPU-401 IRQ */ 1413 /* MPU-401 IRQ */
1425 snd_es18xx_config_write(chip, 0x28, chip->irq); 1414 snd_es18xx_config_write(chip, 0x28, chip->irq);
1426 } 1415 }
@@ -1507,11 +1496,12 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
1507 snd_es18xx_mixer_write(chip, 0x7A, 0x68); 1496 snd_es18xx_mixer_write(chip, 0x7A, 0x68);
1508 /* Enable and set hardware volume interrupt */ 1497 /* Enable and set hardware volume interrupt */
1509 snd_es18xx_mixer_write(chip, 0x64, 0x06); 1498 snd_es18xx_mixer_write(chip, 0x64, 0x06);
1510 if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { 1499 if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
1511 /* MPU401 share irq with audio 1500 /* MPU401 share irq with audio
1512 Joystick enabled 1501 Joystick enabled
1513 FM enabled */ 1502 FM enabled */
1514 snd_es18xx_mixer_write(chip, 0x40, 0x43 | (chip->mpu_port & 0xf0) >> 1); 1503 snd_es18xx_mixer_write(chip, 0x40,
1504 0x43 | (mpu_port & 0xf0) >> 1);
1515 } 1505 }
1516 snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01); 1506 snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01);
1517 } 1507 }
@@ -1629,7 +1619,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
1629 return 0; 1619 return 0;
1630} 1620}
1631 1621
1632static int __devinit snd_es18xx_probe(struct snd_es18xx *chip) 1622static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
1623 unsigned long mpu_port,
1624 unsigned long fm_port)
1633{ 1625{
1634 if (snd_es18xx_identify(chip) < 0) { 1626 if (snd_es18xx_identify(chip) < 0) {
1635 snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port); 1627 snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1650,8 +1642,6 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
1650 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV; 1642 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
1651 break; 1643 break;
1652 case 0x1887: 1644 case 0x1887:
1653 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
1654 break;
1655 case 0x1888: 1645 case 0x1888:
1656 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME; 1646 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
1657 break; 1647 break;
@@ -1666,7 +1656,7 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
1666 if (chip->dma1 == chip->dma2) 1656 if (chip->dma1 == chip->dma2)
1667 chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME); 1657 chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME);
1668 1658
1669 return snd_es18xx_initialize(chip); 1659 return snd_es18xx_initialize(chip, mpu_port, fm_port);
1670} 1660}
1671 1661
1672static struct snd_pcm_ops snd_es18xx_playback_ops = { 1662static struct snd_pcm_ops snd_es18xx_playback_ops = {
@@ -1691,8 +1681,10 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
1691 .pointer = snd_es18xx_capture_pointer, 1681 .pointer = snd_es18xx_capture_pointer,
1692}; 1682};
1693 1683
1694static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct snd_pcm ** rpcm) 1684static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
1685 struct snd_pcm **rpcm)
1695{ 1686{
1687 struct snd_es18xx *chip = card->private_data;
1696 struct snd_pcm *pcm; 1688 struct snd_pcm *pcm;
1697 char str[16]; 1689 char str[16];
1698 int err; 1690 int err;
@@ -1701,9 +1693,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
1701 *rpcm = NULL; 1693 *rpcm = NULL;
1702 sprintf(str, "ES%x", chip->version); 1694 sprintf(str, "ES%x", chip->version);
1703 if (chip->caps & ES18XX_PCM2) 1695 if (chip->caps & ES18XX_PCM2)
1704 err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm); 1696 err = snd_pcm_new(card, str, device, 2, 1, &pcm);
1705 else 1697 else
1706 err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm); 1698 err = snd_pcm_new(card, str, device, 1, 1, &pcm);
1707 if (err < 0) 1699 if (err < 0)
1708 return err; 1700 return err;
1709 1701
@@ -1734,10 +1726,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
1734#ifdef CONFIG_PM 1726#ifdef CONFIG_PM
1735static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state) 1727static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
1736{ 1728{
1737 struct snd_audiodrive *acard = card->private_data; 1729 struct snd_es18xx *chip = card->private_data;
1738 struct snd_es18xx *chip = acard->chip;
1739 1730
1740 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); 1731 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1741 1732
1742 snd_pcm_suspend_all(chip->pcm); 1733 snd_pcm_suspend_all(chip->pcm);
1743 1734
@@ -1752,24 +1743,25 @@ static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
1752 1743
1753static int snd_es18xx_resume(struct snd_card *card) 1744static int snd_es18xx_resume(struct snd_card *card)
1754{ 1745{
1755 struct snd_audiodrive *acard = card->private_data; 1746 struct snd_es18xx *chip = card->private_data;
1756 struct snd_es18xx *chip = acard->chip;
1757 1747
1758 /* restore PM register, we won't wake till (not 0x07) i/o activity though */ 1748 /* restore PM register, we won't wake till (not 0x07) i/o activity though */
1759 snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM); 1749 snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
1760 1750
1761 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); 1751 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1762 return 0; 1752 return 0;
1763} 1753}
1764#endif /* CONFIG_PM */ 1754#endif /* CONFIG_PM */
1765 1755
1766static int snd_es18xx_free(struct snd_es18xx *chip) 1756static int snd_es18xx_free(struct snd_card *card)
1767{ 1757{
1758 struct snd_es18xx *chip = card->private_data;
1759
1768 release_and_free_resource(chip->res_port); 1760 release_and_free_resource(chip->res_port);
1769 release_and_free_resource(chip->res_ctrl_port); 1761 release_and_free_resource(chip->res_ctrl_port);
1770 release_and_free_resource(chip->res_mpu_port); 1762 release_and_free_resource(chip->res_mpu_port);
1771 if (chip->irq >= 0) 1763 if (chip->irq >= 0)
1772 free_irq(chip->irq, (void *) chip); 1764 free_irq(chip->irq, (void *) card);
1773 if (chip->dma1 >= 0) { 1765 if (chip->dma1 >= 0) {
1774 disable_dma(chip->dma1); 1766 disable_dma(chip->dma1);
1775 free_dma(chip->dma1); 1767 free_dma(chip->dma1);
@@ -1778,93 +1770,82 @@ static int snd_es18xx_free(struct snd_es18xx *chip)
1778 disable_dma(chip->dma2); 1770 disable_dma(chip->dma2);
1779 free_dma(chip->dma2); 1771 free_dma(chip->dma2);
1780 } 1772 }
1781 kfree(chip);
1782 return 0; 1773 return 0;
1783} 1774}
1784 1775
1785static int snd_es18xx_dev_free(struct snd_device *device) 1776static int snd_es18xx_dev_free(struct snd_device *device)
1786{ 1777{
1787 struct snd_es18xx *chip = device->device_data; 1778 return snd_es18xx_free(device->card);
1788 return snd_es18xx_free(chip);
1789} 1779}
1790 1780
1791static int __devinit snd_es18xx_new_device(struct snd_card *card, 1781static int __devinit snd_es18xx_new_device(struct snd_card *card,
1792 unsigned long port, 1782 unsigned long port,
1793 unsigned long mpu_port, 1783 unsigned long mpu_port,
1794 unsigned long fm_port, 1784 unsigned long fm_port,
1795 int irq, int dma1, int dma2, 1785 int irq, int dma1, int dma2)
1796 struct snd_es18xx ** rchip)
1797{ 1786{
1798 struct snd_es18xx *chip; 1787 struct snd_es18xx *chip = card->private_data;
1799 static struct snd_device_ops ops = { 1788 static struct snd_device_ops ops = {
1800 .dev_free = snd_es18xx_dev_free, 1789 .dev_free = snd_es18xx_dev_free,
1801 }; 1790 };
1802 int err; 1791 int err;
1803 1792
1804 *rchip = NULL;
1805 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1806 if (chip == NULL)
1807 return -ENOMEM;
1808 spin_lock_init(&chip->reg_lock); 1793 spin_lock_init(&chip->reg_lock);
1809 spin_lock_init(&chip->mixer_lock); 1794 spin_lock_init(&chip->mixer_lock);
1810 spin_lock_init(&chip->ctrl_lock);
1811 chip->card = card;
1812 chip->port = port; 1795 chip->port = port;
1813 chip->mpu_port = mpu_port;
1814 chip->fm_port = fm_port;
1815 chip->irq = -1; 1796 chip->irq = -1;
1816 chip->dma1 = -1; 1797 chip->dma1 = -1;
1817 chip->dma2 = -1; 1798 chip->dma2 = -1;
1818 chip->audio2_vol = 0x00; 1799 chip->audio2_vol = 0x00;
1819 chip->active = 0; 1800 chip->active = 0;
1820 1801
1821 if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) { 1802 chip->res_port = request_region(port, 16, "ES18xx");
1822 snd_es18xx_free(chip); 1803 if (chip->res_port == NULL) {
1804 snd_es18xx_free(card);
1823 snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1); 1805 snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
1824 return -EBUSY; 1806 return -EBUSY;
1825 } 1807 }
1826 1808
1827 if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", (void *) chip)) { 1809 if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
1828 snd_es18xx_free(chip); 1810 (void *) card)) {
1811 snd_es18xx_free(card);
1829 snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); 1812 snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
1830 return -EBUSY; 1813 return -EBUSY;
1831 } 1814 }
1832 chip->irq = irq; 1815 chip->irq = irq;
1833 1816
1834 if (request_dma(dma1, "ES18xx DMA 1")) { 1817 if (request_dma(dma1, "ES18xx DMA 1")) {
1835 snd_es18xx_free(chip); 1818 snd_es18xx_free(card);
1836 snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1); 1819 snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
1837 return -EBUSY; 1820 return -EBUSY;
1838 } 1821 }
1839 chip->dma1 = dma1; 1822 chip->dma1 = dma1;
1840 1823
1841 if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) { 1824 if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
1842 snd_es18xx_free(chip); 1825 snd_es18xx_free(card);
1843 snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2); 1826 snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
1844 return -EBUSY; 1827 return -EBUSY;
1845 } 1828 }
1846 chip->dma2 = dma2; 1829 chip->dma2 = dma2;
1847 1830
1848 if (snd_es18xx_probe(chip) < 0) { 1831 if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
1849 snd_es18xx_free(chip); 1832 snd_es18xx_free(card);
1850 return -ENODEV; 1833 return -ENODEV;
1851 } 1834 }
1852 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 1835 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1853 snd_es18xx_free(chip); 1836 if (err < 0) {
1837 snd_es18xx_free(card);
1854 return err; 1838 return err;
1855 } 1839 }
1856 *rchip = chip;
1857 return 0; 1840 return 0;
1858} 1841}
1859 1842
1860static int __devinit snd_es18xx_mixer(struct snd_es18xx *chip) 1843static int __devinit snd_es18xx_mixer(struct snd_card *card)
1861{ 1844{
1862 struct snd_card *card; 1845 struct snd_es18xx *chip = card->private_data;
1863 int err; 1846 int err;
1864 unsigned int idx; 1847 unsigned int idx;
1865 1848
1866 card = chip->card;
1867
1868 strcpy(card->mixername, chip->pcm->name); 1849 strcpy(card->mixername, chip->pcm->name);
1869 1850
1870 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) { 1851 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
@@ -1986,7 +1967,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
1986static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 1967static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
1987static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ 1968static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
1988#ifdef CONFIG_PNP 1969#ifdef CONFIG_PNP
1989static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; 1970static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
1990#endif 1971#endif
1991static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ 1972static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
1992#ifndef CONFIG_PNP 1973#ifndef CONFIG_PNP
@@ -2063,11 +2044,11 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
2063 return 0; 2044 return 0;
2064} 2045}
2065 2046
2066static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, 2047static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
2067 struct pnp_dev *pdev) 2048 struct pnp_dev *pdev)
2068{ 2049{
2069 acard->dev = pdev; 2050 chip->dev = pdev;
2070 if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0) 2051 if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
2071 return -EBUSY; 2052 return -EBUSY;
2072 return 0; 2053 return 0;
2073} 2054}
@@ -2093,26 +2074,26 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
2093 2074
2094MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); 2075MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
2095 2076
2096static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, 2077static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
2097 struct pnp_card_link *card, 2078 struct pnp_card_link *card,
2098 const struct pnp_card_device_id *id) 2079 const struct pnp_card_device_id *id)
2099{ 2080{
2100 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); 2081 chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
2101 if (acard->dev == NULL) 2082 if (chip->dev == NULL)
2102 return -EBUSY; 2083 return -EBUSY;
2103 2084
2104 acard->devc = pnp_request_card_device(card, id->devs[1].id, NULL); 2085 chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
2105 if (acard->devc == NULL) 2086 if (chip->devc == NULL)
2106 return -EBUSY; 2087 return -EBUSY;
2107 2088
2108 /* Control port initialization */ 2089 /* Control port initialization */
2109 if (pnp_activate_dev(acard->devc) < 0) { 2090 if (pnp_activate_dev(chip->devc) < 0) {
2110 snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); 2091 snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
2111 return -EAGAIN; 2092 return -EAGAIN;
2112 } 2093 }
2113 snd_printdd("pnp: port=0x%llx\n", 2094 snd_printdd("pnp: port=0x%llx\n",
2114 (unsigned long long)pnp_port_start(acard->devc, 0)); 2095 (unsigned long long)pnp_port_start(chip->devc, 0));
2115 if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0) 2096 if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
2116 return -EBUSY; 2097 return -EBUSY;
2117 2098
2118 return 0; 2099 return 0;
@@ -2128,24 +2109,20 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
2128static int snd_es18xx_card_new(int dev, struct snd_card **cardp) 2109static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
2129{ 2110{
2130 return snd_card_create(index[dev], id[dev], THIS_MODULE, 2111 return snd_card_create(index[dev], id[dev], THIS_MODULE,
2131 sizeof(struct snd_audiodrive), cardp); 2112 sizeof(struct snd_es18xx), cardp);
2132} 2113}
2133 2114
2134static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) 2115static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
2135{ 2116{
2136 struct snd_audiodrive *acard = card->private_data; 2117 struct snd_es18xx *chip = card->private_data;
2137 struct snd_es18xx *chip;
2138 struct snd_opl3 *opl3; 2118 struct snd_opl3 *opl3;
2139 int err; 2119 int err;
2140 2120
2141 if ((err = snd_es18xx_new_device(card, 2121 err = snd_es18xx_new_device(card,
2142 port[dev], 2122 port[dev], mpu_port[dev], fm_port[dev],
2143 mpu_port[dev], 2123 irq[dev], dma1[dev], dma2[dev]);
2144 fm_port[dev], 2124 if (err < 0)
2145 irq[dev], dma1[dev], dma2[dev],
2146 &chip)) < 0)
2147 return err; 2125 return err;
2148 acard->chip = chip;
2149 2126
2150 sprintf(card->driver, "ES%x", chip->version); 2127 sprintf(card->driver, "ES%x", chip->version);
2151 2128
@@ -2161,26 +2138,32 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
2161 chip->port, 2138 chip->port,
2162 irq[dev], dma1[dev]); 2139 irq[dev], dma1[dev]);
2163 2140
2164 if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) 2141 err = snd_es18xx_pcm(card, 0, NULL);
2142 if (err < 0)
2165 return err; 2143 return err;
2166 2144
2167 if ((err = snd_es18xx_mixer(chip)) < 0) 2145 err = snd_es18xx_mixer(card);
2146 if (err < 0)
2168 return err; 2147 return err;
2169 2148
2170 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { 2149 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
2171 if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) { 2150 if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
2172 snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port); 2151 OPL3_HW_OPL3, 0, &opl3) < 0) {
2152 snd_printk(KERN_WARNING PFX
2153 "opl3 not detected at 0x%lx\n",
2154 fm_port[dev]);
2173 } else { 2155 } else {
2174 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) 2156 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
2157 if (err < 0)
2175 return err; 2158 return err;
2176 } 2159 }
2177 } 2160 }
2178 2161
2179 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { 2162 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
2180 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX, 2163 err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
2181 chip->mpu_port, 0, 2164 mpu_port[dev], 0,
2182 irq[dev], 0, 2165 irq[dev], 0, &chip->rmidi);
2183 &chip->rmidi)) < 0) 2166 if (err < 0)
2184 return err; 2167 return err;
2185 } 2168 }
2186 2169
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 02e30d7c6a93..6123c7531110 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -25,6 +25,7 @@
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/isa.h> 27#include <linux/isa.h>
28#include <linux/pnp.h>
28#include <linux/delay.h> 29#include <linux/delay.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/ioport.h> 31#include <linux/ioport.h>
@@ -40,7 +41,7 @@
40#define SNDRV_LEGACY_FIND_FREE_IRQ 41#define SNDRV_LEGACY_FIND_FREE_IRQ
41#define SNDRV_LEGACY_FIND_FREE_DMA 42#define SNDRV_LEGACY_FIND_FREE_DMA
42#include <sound/initval.h> 43#include <sound/initval.h>
43#include "miro.h" 44#include <sound/aci.h>
44 45
45MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>"); 46MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
46MODULE_LICENSE("GPL"); 47MODULE_LICENSE("GPL");
@@ -60,6 +61,9 @@ static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
60static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ 61static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
61static int wss; 62static int wss;
62static int ide; 63static int ide;
64#ifdef CONFIG_PNP
65static int isapnp = 1; /* Enable ISA PnP detection */
66#endif
63 67
64module_param(index, int, 0444); 68module_param(index, int, 0444);
65MODULE_PARM_DESC(index, "Index value for miro soundcard."); 69MODULE_PARM_DESC(index, "Index value for miro soundcard.");
@@ -83,6 +87,10 @@ module_param(wss, int, 0444);
83MODULE_PARM_DESC(wss, "wss mode"); 87MODULE_PARM_DESC(wss, "wss mode");
84module_param(ide, int, 0444); 88module_param(ide, int, 0444);
85MODULE_PARM_DESC(ide, "enable ide port"); 89MODULE_PARM_DESC(ide, "enable ide port");
90#ifdef CONFIG_PNP
91module_param(isapnp, bool, 0444);
92MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
93#endif
86 94
87#define OPTi9XX_HW_DETECT 0 95#define OPTi9XX_HW_DETECT 0
88#define OPTi9XX_HW_82C928 1 96#define OPTi9XX_HW_82C928 1
@@ -96,7 +104,6 @@ MODULE_PARM_DESC(ide, "enable ide port");
96 104
97#define OPTi9XX_MC_REG(n) n 105#define OPTi9XX_MC_REG(n) n
98 106
99
100struct snd_miro { 107struct snd_miro {
101 unsigned short hardware; 108 unsigned short hardware;
102 unsigned char password; 109 unsigned char password;
@@ -110,7 +117,6 @@ struct snd_miro {
110 unsigned long pwd_reg; 117 unsigned long pwd_reg;
111 118
112 spinlock_t lock; 119 spinlock_t lock;
113 struct snd_card *card;
114 struct snd_pcm *pcm; 120 struct snd_pcm *pcm;
115 121
116 long wss_base; 122 long wss_base;
@@ -118,23 +124,13 @@ struct snd_miro {
118 int dma1; 124 int dma1;
119 int dma2; 125 int dma2;
120 126
121 long fm_port;
122
123 long mpu_port; 127 long mpu_port;
124 int mpu_irq; 128 int mpu_irq;
125 129
126 unsigned long aci_port; 130 struct snd_miro_aci *aci;
127 int aci_vendor;
128 int aci_product;
129 int aci_version;
130 int aci_amp;
131 int aci_preamp;
132 int aci_solomode;
133
134 struct mutex aci_mutex;
135}; 131};
136 132
137static void snd_miro_proc_init(struct snd_miro * miro); 133static struct snd_miro_aci aci_device;
138 134
139static char * snd_opti9xx_names[] = { 135static char * snd_opti9xx_names[] = {
140 "unkown", 136 "unkown",
@@ -143,17 +139,33 @@ static char * snd_opti9xx_names[] = {
143 "82C930", "82C931", "82C933" 139 "82C930", "82C931", "82C933"
144}; 140};
145 141
142static int snd_miro_pnp_is_probed;
143
144#ifdef CONFIG_PNP
145
146static struct pnp_card_device_id snd_miro_pnpids[] = {
147 /* PCM20 and PCM12 in PnP mode */
148 { .id = "MIR0924",
149 .devs = { { "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, },
150 { .id = "" }
151};
152
153MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids);
154
155#endif /* CONFIG_PNP */
156
146/* 157/*
147 * ACI control 158 * ACI control
148 */ 159 */
149 160
150static int aci_busy_wait(struct snd_miro * miro) 161static int aci_busy_wait(struct snd_miro_aci *aci)
151{ 162{
152 long timeout; 163 long timeout;
153 unsigned char byte; 164 unsigned char byte;
154 165
155 for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) { 166 for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) {
156 if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) { 167 byte = inb(aci->aci_port + ACI_REG_BUSY);
168 if ((byte & 1) == 0) {
157 if (timeout >= ACI_MINTIME) 169 if (timeout >= ACI_MINTIME)
158 snd_printd("aci ready in round %ld.\n", 170 snd_printd("aci ready in round %ld.\n",
159 timeout-ACI_MINTIME); 171 timeout-ACI_MINTIME);
@@ -179,10 +191,10 @@ static int aci_busy_wait(struct snd_miro * miro)
179 return -EBUSY; 191 return -EBUSY;
180} 192}
181 193
182static inline int aci_write(struct snd_miro * miro, unsigned char byte) 194static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte)
183{ 195{
184 if (aci_busy_wait(miro) >= 0) { 196 if (aci_busy_wait(aci) >= 0) {
185 outb(byte, miro->aci_port + ACI_REG_COMMAND); 197 outb(byte, aci->aci_port + ACI_REG_COMMAND);
186 return 0; 198 return 0;
187 } else { 199 } else {
188 snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); 200 snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
@@ -190,12 +202,12 @@ static inline int aci_write(struct snd_miro * miro, unsigned char byte)
190 } 202 }
191} 203}
192 204
193static inline int aci_read(struct snd_miro * miro) 205static inline int aci_read(struct snd_miro_aci *aci)
194{ 206{
195 unsigned char byte; 207 unsigned char byte;
196 208
197 if (aci_busy_wait(miro) >= 0) { 209 if (aci_busy_wait(aci) >= 0) {
198 byte=inb(miro->aci_port + ACI_REG_STATUS); 210 byte = inb(aci->aci_port + ACI_REG_STATUS);
199 return byte; 211 return byte;
200 } else { 212 } else {
201 snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); 213 snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
@@ -203,39 +215,49 @@ static inline int aci_read(struct snd_miro * miro)
203 } 215 }
204} 216}
205 217
206static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3) 218int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3)
207{ 219{
208 int write[] = {write1, write2, write3}; 220 int write[] = {write1, write2, write3};
209 int value, i; 221 int value, i;
210 222
211 if (mutex_lock_interruptible(&miro->aci_mutex)) 223 if (mutex_lock_interruptible(&aci->aci_mutex))
212 return -EINTR; 224 return -EINTR;
213 225
214 for (i=0; i<3; i++) { 226 for (i=0; i<3; i++) {
215 if (write[i]< 0 || write[i] > 255) 227 if (write[i]< 0 || write[i] > 255)
216 break; 228 break;
217 else { 229 else {
218 value = aci_write(miro, write[i]); 230 value = aci_write(aci, write[i]);
219 if (value < 0) 231 if (value < 0)
220 goto out; 232 goto out;
221 } 233 }
222 } 234 }
223 235
224 value = aci_read(miro); 236 value = aci_read(aci);
225 237
226out: mutex_unlock(&miro->aci_mutex); 238out: mutex_unlock(&aci->aci_mutex);
227 return value; 239 return value;
228} 240}
241EXPORT_SYMBOL(snd_aci_cmd);
242
243static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index)
244{
245 return snd_aci_cmd(aci, ACI_STATUS, index, -1);
246}
229 247
230static int aci_getvalue(struct snd_miro * miro, unsigned char index) 248static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index,
249 int value)
231{ 250{
232 return aci_cmd(miro, ACI_STATUS, index, -1); 251 return snd_aci_cmd(aci, index, value, -1);
233} 252}
234 253
235static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) 254struct snd_miro_aci *snd_aci_get_aci(void)
236{ 255{
237 return aci_cmd(miro, index, value, -1); 256 if (aci_device.aci_port == 0)
257 return NULL;
258 return &aci_device;
238} 259}
260EXPORT_SYMBOL(snd_aci_get_aci);
239 261
240/* 262/*
241 * MIXER part 263 * MIXER part
@@ -249,8 +271,10 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
249 struct snd_miro *miro = snd_kcontrol_chip(kcontrol); 271 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
250 int value; 272 int value;
251 273
252 if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) { 274 value = aci_getvalue(miro->aci, ACI_S_GENERAL);
253 snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value); 275 if (value < 0) {
276 snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n",
277 value);
254 return value; 278 return value;
255 } 279 }
256 280
@@ -267,13 +291,15 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
267 291
268 value = !(ucontrol->value.integer.value[0]); 292 value = !(ucontrol->value.integer.value[0]);
269 293
270 if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) { 294 error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value);
271 snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error); 295 if (error < 0) {
296 snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n",
297 error);
272 return error; 298 return error;
273 } 299 }
274 300
275 change = (value != miro->aci_solomode); 301 change = (value != miro->aci->aci_solomode);
276 miro->aci_solomode = value; 302 miro->aci->aci_solomode = value;
277 303
278 return change; 304 return change;
279} 305}
@@ -295,7 +321,7 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
295 struct snd_miro *miro = snd_kcontrol_chip(kcontrol); 321 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
296 int value; 322 int value;
297 323
298 if (miro->aci_version <= 176) { 324 if (miro->aci->aci_version <= 176) {
299 325
300 /* 326 /*
301 OSS says it's not readable with versions < 176. 327 OSS says it's not readable with versions < 176.
@@ -303,12 +329,14 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
303 which is a PCM12 with aci_version = 176. 329 which is a PCM12 with aci_version = 176.
304 */ 330 */
305 331
306 ucontrol->value.integer.value[0] = miro->aci_preamp; 332 ucontrol->value.integer.value[0] = miro->aci->aci_preamp;
307 return 0; 333 return 0;
308 } 334 }
309 335
310 if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) { 336 value = aci_getvalue(miro->aci, ACI_GET_PREAMP);
311 snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value); 337 if (value < 0) {
338 snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n",
339 value);
312 return value; 340 return value;
313 } 341 }
314 342
@@ -325,13 +353,15 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
325 353
326 value = ucontrol->value.integer.value[0]; 354 value = ucontrol->value.integer.value[0];
327 355
328 if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) { 356 error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value);
329 snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error); 357 if (error < 0) {
358 snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n",
359 error);
330 return error; 360 return error;
331 } 361 }
332 362
333 change = (value != miro->aci_preamp); 363 change = (value != miro->aci->aci_preamp);
334 miro->aci_preamp = value; 364 miro->aci->aci_preamp = value;
335 365
336 return change; 366 return change;
337} 367}
@@ -342,7 +372,7 @@ static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
342 struct snd_ctl_elem_value *ucontrol) 372 struct snd_ctl_elem_value *ucontrol)
343{ 373{
344 struct snd_miro *miro = snd_kcontrol_chip(kcontrol); 374 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
345 ucontrol->value.integer.value[0] = miro->aci_amp; 375 ucontrol->value.integer.value[0] = miro->aci->aci_amp;
346 376
347 return 0; 377 return 0;
348} 378}
@@ -355,13 +385,14 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
355 385
356 value = ucontrol->value.integer.value[0]; 386 value = ucontrol->value.integer.value[0];
357 387
358 if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) { 388 error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value);
389 if (error < 0) {
359 snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); 390 snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
360 return error; 391 return error;
361 } 392 }
362 393
363 change = (value != miro->aci_amp); 394 change = (value != miro->aci->aci_amp);
364 miro->aci_amp = value; 395 miro->aci->aci_amp = value;
365 396
366 return change; 397 return change;
367} 398}
@@ -410,12 +441,14 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
410 int right_reg = kcontrol->private_value & 0xff; 441 int right_reg = kcontrol->private_value & 0xff;
411 int left_reg = right_reg + 1; 442 int left_reg = right_reg + 1;
412 443
413 if ((right_val = aci_getvalue(miro, right_reg)) < 0) { 444 right_val = aci_getvalue(miro->aci, right_reg);
445 if (right_val < 0) {
414 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); 446 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
415 return right_val; 447 return right_val;
416 } 448 }
417 449
418 if ((left_val = aci_getvalue(miro, left_reg)) < 0) { 450 left_val = aci_getvalue(miro->aci, left_reg);
451 if (left_val < 0) {
419 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); 452 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
420 return left_val; 453 return left_val;
421 } 454 }
@@ -451,6 +484,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_value *ucontrol) 484 struct snd_ctl_elem_value *ucontrol)
452{ 485{
453 struct snd_miro *miro = snd_kcontrol_chip(kcontrol); 486 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
487 struct snd_miro_aci *aci = miro->aci;
454 int left, right, left_old, right_old; 488 int left, right, left_old, right_old;
455 int setreg_left, setreg_right, getreg_left, getreg_right; 489 int setreg_left, setreg_right, getreg_left, getreg_right;
456 int change, error; 490 int change, error;
@@ -459,21 +493,21 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
459 right = ucontrol->value.integer.value[1]; 493 right = ucontrol->value.integer.value[1];
460 494
461 setreg_right = (kcontrol->private_value >> 8) & 0xff; 495 setreg_right = (kcontrol->private_value >> 8) & 0xff;
462 if (setreg_right == ACI_SET_MASTER) { 496 setreg_left = setreg_right + 8;
463 setreg_left = setreg_right + 1; 497 if (setreg_right == ACI_SET_MASTER)
464 } else { 498 setreg_left -= 7;
465 setreg_left = setreg_right + 8;
466 }
467 499
468 getreg_right = kcontrol->private_value & 0xff; 500 getreg_right = kcontrol->private_value & 0xff;
469 getreg_left = getreg_right + 1; 501 getreg_left = getreg_right + 1;
470 502
471 if ((left_old = aci_getvalue(miro, getreg_left)) < 0) { 503 left_old = aci_getvalue(aci, getreg_left);
504 if (left_old < 0) {
472 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); 505 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
473 return left_old; 506 return left_old;
474 } 507 }
475 508
476 if ((right_old = aci_getvalue(miro, getreg_right)) < 0) { 509 right_old = aci_getvalue(aci, getreg_right);
510 if (right_old < 0) {
477 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); 511 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
478 return right_old; 512 return right_old;
479 } 513 }
@@ -492,13 +526,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
492 right_old = 0x80 - right_old; 526 right_old = 0x80 - right_old;
493 527
494 if (left >= 0) { 528 if (left >= 0) {
495 if ((error = aci_setvalue(miro, setreg_left, left)) < 0) { 529 error = aci_setvalue(aci, setreg_left, left);
530 if (error < 0) {
496 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 531 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
497 left, error); 532 left, error);
498 return error; 533 return error;
499 } 534 }
500 } else { 535 } else {
501 if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) { 536 error = aci_setvalue(aci, setreg_left, 0x80 - left);
537 if (error < 0) {
502 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 538 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
503 0x80 - left, error); 539 0x80 - left, error);
504 return error; 540 return error;
@@ -506,13 +542,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
506 } 542 }
507 543
508 if (right >= 0) { 544 if (right >= 0) {
509 if ((error = aci_setvalue(miro, setreg_right, right)) < 0) { 545 error = aci_setvalue(aci, setreg_right, right);
546 if (error < 0) {
510 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 547 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
511 right, error); 548 right, error);
512 return error; 549 return error;
513 } 550 }
514 } else { 551 } else {
515 if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) { 552 error = aci_setvalue(aci, setreg_right, 0x80 - right);
553 if (error < 0) {
516 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 554 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
517 0x80 - right, error); 555 0x80 - right, error);
518 return error; 556 return error;
@@ -530,12 +568,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
530 left_old = 0x20 - left_old; 568 left_old = 0x20 - left_old;
531 right_old = 0x20 - right_old; 569 right_old = 0x20 - right_old;
532 570
533 if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) { 571 error = aci_setvalue(aci, setreg_left, 0x20 - left);
572 if (error < 0) {
534 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 573 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
535 0x20 - left, error); 574 0x20 - left, error);
536 return error; 575 return error;
537 } 576 }
538 if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) { 577 error = aci_setvalue(aci, setreg_right, 0x20 - right);
578 if (error < 0) {
539 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 579 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
540 0x20 - right, error); 580 0x20 - right, error);
541 return error; 581 return error;
@@ -633,11 +673,13 @@ static unsigned char aci_init_values[][2] __devinitdata = {
633static int __devinit snd_set_aci_init_values(struct snd_miro *miro) 673static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
634{ 674{
635 int idx, error; 675 int idx, error;
676 struct snd_miro_aci *aci = miro->aci;
636 677
637 /* enable WSS on PCM1 */ 678 /* enable WSS on PCM1 */
638 679
639 if ((miro->aci_product == 'A') && wss) { 680 if ((aci->aci_product == 'A') && wss) {
640 if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) { 681 error = aci_setvalue(aci, ACI_SET_WSS, wss);
682 if (error < 0) {
641 snd_printk(KERN_ERR "enabling WSS mode failed\n"); 683 snd_printk(KERN_ERR "enabling WSS mode failed\n");
642 return error; 684 return error;
643 } 685 }
@@ -646,7 +688,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
646 /* enable IDE port */ 688 /* enable IDE port */
647 689
648 if (ide) { 690 if (ide) {
649 if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) { 691 error = aci_setvalue(aci, ACI_SET_IDE, ide);
692 if (error < 0) {
650 snd_printk(KERN_ERR "enabling IDE port failed\n"); 693 snd_printk(KERN_ERR "enabling IDE port failed\n");
651 return error; 694 return error;
652 } 695 }
@@ -654,32 +697,31 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
654 697
655 /* set common aci values */ 698 /* set common aci values */
656 699
657 for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) 700 for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) {
658 if ((error = aci_setvalue(miro, aci_init_values[idx][0], 701 error = aci_setvalue(aci, aci_init_values[idx][0],
659 aci_init_values[idx][1])) < 0) { 702 aci_init_values[idx][1]);
703 if (error < 0) {
660 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 704 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
661 aci_init_values[idx][0], error); 705 aci_init_values[idx][0], error);
662 return error; 706 return error;
663 } 707 }
664 708 }
665 miro->aci_amp = 0; 709 aci->aci_amp = 0;
666 miro->aci_preamp = 0; 710 aci->aci_preamp = 0;
667 miro->aci_solomode = 1; 711 aci->aci_solomode = 1;
668 712
669 return 0; 713 return 0;
670} 714}
671 715
672static int __devinit snd_miro_mixer(struct snd_miro *miro) 716static int __devinit snd_miro_mixer(struct snd_card *card,
717 struct snd_miro *miro)
673{ 718{
674 struct snd_card *card;
675 unsigned int idx; 719 unsigned int idx;
676 int err; 720 int err;
677 721
678 if (snd_BUG_ON(!miro || !miro->card)) 722 if (snd_BUG_ON(!miro || !card))
679 return -EINVAL; 723 return -EINVAL;
680 724
681 card = miro->card;
682
683 switch (miro->hardware) { 725 switch (miro->hardware) {
684 case OPTi9XX_HW_82C924: 726 case OPTi9XX_HW_82C924:
685 strcpy(card->mixername, "ACI & OPTi924"); 727 strcpy(card->mixername, "ACI & OPTi924");
@@ -697,7 +739,8 @@ static int __devinit snd_miro_mixer(struct snd_miro *miro)
697 return err; 739 return err;
698 } 740 }
699 741
700 if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) { 742 if ((miro->aci->aci_product == 'A') ||
743 (miro->aci->aci_product == 'B')) {
701 /* PCM1/PCM12 with power-amp and Line 2 */ 744 /* PCM1/PCM12 with power-amp and Line 2 */
702 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) 745 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
703 return err; 746 return err;
@@ -705,16 +748,17 @@ static int __devinit snd_miro_mixer(struct snd_miro *miro)
705 return err; 748 return err;
706 } 749 }
707 750
708 if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) { 751 if ((miro->aci->aci_product == 'B') ||
752 (miro->aci->aci_product == 'C')) {
709 /* PCM12/PCM20 with mic-preamp */ 753 /* PCM12/PCM20 with mic-preamp */
710 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) 754 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
711 return err; 755 return err;
712 if (miro->aci_version >= 176) 756 if (miro->aci->aci_version >= 176)
713 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) 757 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
714 return err; 758 return err;
715 } 759 }
716 760
717 if (miro->aci_product == 'C') { 761 if (miro->aci->aci_product == 'C') {
718 /* PCM20 with radio and 7 band equalizer */ 762 /* PCM20 with radio and 7 band equalizer */
719 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) 763 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
720 return err; 764 return err;
@@ -757,21 +801,26 @@ static int __devinit snd_miro_init(struct snd_miro *chip,
757 chip->irq = -1; 801 chip->irq = -1;
758 chip->dma1 = -1; 802 chip->dma1 = -1;
759 chip->dma2 = -1; 803 chip->dma2 = -1;
760 chip->fm_port = -1;
761 chip->mpu_port = -1; 804 chip->mpu_port = -1;
762 chip->mpu_irq = -1; 805 chip->mpu_irq = -1;
763 806
807 chip->pwd_reg = 3;
808
809#ifdef CONFIG_PNP
810 if (isapnp && chip->mc_base)
811 /* PnP resource gives the least 10 bits */
812 chip->mc_base |= 0xc00;
813 else
814#endif
815 chip->mc_base = 0xf8c;
816
764 switch (hardware) { 817 switch (hardware) {
765 case OPTi9XX_HW_82C929: 818 case OPTi9XX_HW_82C929:
766 chip->mc_base = 0xf8c;
767 chip->password = 0xe3; 819 chip->password = 0xe3;
768 chip->pwd_reg = 3;
769 break; 820 break;
770 821
771 case OPTi9XX_HW_82C924: 822 case OPTi9XX_HW_82C924:
772 chip->mc_base = 0xf8c;
773 chip->password = 0xe5; 823 chip->password = 0xe5;
774 chip->pwd_reg = 3;
775 break; 824 break;
776 825
777 default: 826 default:
@@ -853,14 +902,15 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
853 struct snd_info_buffer *buffer) 902 struct snd_info_buffer *buffer)
854{ 903{
855 struct snd_miro *miro = (struct snd_miro *) entry->private_data; 904 struct snd_miro *miro = (struct snd_miro *) entry->private_data;
905 struct snd_miro_aci *aci = miro->aci;
856 char* model = "unknown"; 906 char* model = "unknown";
857 907
858 /* miroSOUND PCM1 pro, early PCM12 */ 908 /* miroSOUND PCM1 pro, early PCM12 */
859 909
860 if ((miro->hardware == OPTi9XX_HW_82C929) && 910 if ((miro->hardware == OPTi9XX_HW_82C929) &&
861 (miro->aci_vendor == 'm') && 911 (aci->aci_vendor == 'm') &&
862 (miro->aci_product == 'A')) { 912 (aci->aci_product == 'A')) {
863 switch(miro->aci_version) { 913 switch (aci->aci_version) {
864 case 3: 914 case 3:
865 model = "miroSOUND PCM1 pro"; 915 model = "miroSOUND PCM1 pro";
866 break; 916 break;
@@ -873,9 +923,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
873 /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ 923 /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
874 924
875 if ((miro->hardware == OPTi9XX_HW_82C924) && 925 if ((miro->hardware == OPTi9XX_HW_82C924) &&
876 (miro->aci_vendor == 'm') && 926 (aci->aci_vendor == 'm') &&
877 (miro->aci_product == 'B')) { 927 (aci->aci_product == 'B')) {
878 switch(miro->aci_version) { 928 switch (aci->aci_version) {
879 case 4: 929 case 4:
880 model = "miroSOUND PCM12"; 930 model = "miroSOUND PCM12";
881 break; 931 break;
@@ -891,9 +941,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
891 /* miroSOUND PCM20 radio */ 941 /* miroSOUND PCM20 radio */
892 942
893 if ((miro->hardware == OPTi9XX_HW_82C924) && 943 if ((miro->hardware == OPTi9XX_HW_82C924) &&
894 (miro->aci_vendor == 'm') && 944 (aci->aci_vendor == 'm') &&
895 (miro->aci_product == 'C')) { 945 (aci->aci_product == 'C')) {
896 switch(miro->aci_version) { 946 switch (aci->aci_version) {
897 case 7: 947 case 7:
898 model = "miroSOUND PCM20 radio (Rev. E)"; 948 model = "miroSOUND PCM20 radio (Rev. E)";
899 break; 949 break;
@@ -917,17 +967,17 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
917 967
918 snd_iprintf(buffer, "ACI information:\n"); 968 snd_iprintf(buffer, "ACI information:\n");
919 snd_iprintf(buffer, " vendor : "); 969 snd_iprintf(buffer, " vendor : ");
920 switch(miro->aci_vendor) { 970 switch (aci->aci_vendor) {
921 case 'm': 971 case 'm':
922 snd_iprintf(buffer, "Miro\n"); 972 snd_iprintf(buffer, "Miro\n");
923 break; 973 break;
924 default: 974 default:
925 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor); 975 snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_vendor);
926 break; 976 break;
927 } 977 }
928 978
929 snd_iprintf(buffer, " product : "); 979 snd_iprintf(buffer, " product : ");
930 switch(miro->aci_product) { 980 switch (aci->aci_product) {
931 case 'A': 981 case 'A':
932 snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); 982 snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
933 break; 983 break;
@@ -938,26 +988,27 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
938 snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); 988 snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
939 break; 989 break;
940 default: 990 default:
941 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product); 991 snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_product);
942 break; 992 break;
943 } 993 }
944 994
945 snd_iprintf(buffer, " firmware: %d (0x%x)\n", 995 snd_iprintf(buffer, " firmware: %d (0x%x)\n",
946 miro->aci_version, miro->aci_version); 996 aci->aci_version, aci->aci_version);
947 snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", 997 snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
948 miro->aci_port, miro->aci_port+2); 998 aci->aci_port, aci->aci_port+2);
949 snd_iprintf(buffer, " wss : 0x%x\n", wss); 999 snd_iprintf(buffer, " wss : 0x%x\n", wss);
950 snd_iprintf(buffer, " ide : 0x%x\n", ide); 1000 snd_iprintf(buffer, " ide : 0x%x\n", ide);
951 snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode); 1001 snd_iprintf(buffer, " solomode: 0x%x\n", aci->aci_solomode);
952 snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp); 1002 snd_iprintf(buffer, " amp : 0x%x\n", aci->aci_amp);
953 snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); 1003 snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp);
954} 1004}
955 1005
956static void __devinit snd_miro_proc_init(struct snd_miro * miro) 1006static void __devinit snd_miro_proc_init(struct snd_card *card,
1007 struct snd_miro *miro)
957{ 1008{
958 struct snd_info_entry *entry; 1009 struct snd_info_entry *entry;
959 1010
960 if (! snd_card_proc_new(miro->card, "miro", &entry)) 1011 if (!snd_card_proc_new(card, "miro", &entry))
961 snd_info_set_text_ops(entry, miro, snd_miro_proc_read); 1012 snd_info_set_text_ops(entry, miro, snd_miro_proc_read);
962} 1013}
963 1014
@@ -974,37 +1025,40 @@ static int __devinit snd_miro_configure(struct snd_miro *chip)
974 unsigned char mpu_irq_bits; 1025 unsigned char mpu_irq_bits;
975 unsigned long flags; 1026 unsigned long flags;
976 1027
1028 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
1029 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
1030 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
1031
977 switch (chip->hardware) { 1032 switch (chip->hardware) {
978 case OPTi9XX_HW_82C924: 1033 case OPTi9XX_HW_82C924:
979 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); 1034 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
980 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
981 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
982 snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); 1035 snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
983 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
984 break; 1036 break;
985 case OPTi9XX_HW_82C929: 1037 case OPTi9XX_HW_82C929:
986 /* untested init commands for OPTi929 */ 1038 /* untested init commands for OPTi929 */
987 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
988 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
989 snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); 1039 snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
990 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
991 break; 1040 break;
992 default: 1041 default:
993 snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); 1042 snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
994 return -EINVAL; 1043 return -EINVAL;
995 } 1044 }
996 1045
997 switch (chip->wss_base) { 1046 /* PnP resource says it decodes only 10 bits of address */
998 case 0x530: 1047 switch (chip->wss_base & 0x3ff) {
1048 case 0x130:
1049 chip->wss_base = 0x530;
999 wss_base_bits = 0x00; 1050 wss_base_bits = 0x00;
1000 break; 1051 break;
1001 case 0x604: 1052 case 0x204:
1053 chip->wss_base = 0x604;
1002 wss_base_bits = 0x03; 1054 wss_base_bits = 0x03;
1003 break; 1055 break;
1004 case 0xe80: 1056 case 0x280:
1057 chip->wss_base = 0xe80;
1005 wss_base_bits = 0x01; 1058 wss_base_bits = 0x01;
1006 break; 1059 break;
1007 case 0xf40: 1060 case 0x340:
1061 chip->wss_base = 0xf40;
1008 wss_base_bits = 0x02; 1062 wss_base_bits = 0x02;
1009 break; 1063 break;
1010 default: 1064 default:
@@ -1122,75 +1176,92 @@ __skip_mpu:
1122 return 0; 1176 return 0;
1123} 1177}
1124 1178
1179static int __devinit snd_miro_opti_check(struct snd_miro *chip)
1180{
1181 unsigned char value;
1182
1183 chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
1184 "OPTi9xx MC");
1185 if (chip->res_mc_base == NULL)
1186 return -ENOMEM;
1187
1188 value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
1189 if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1)))
1190 if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
1191 return 0;
1192
1193 release_and_free_resource(chip->res_mc_base);
1194 chip->res_mc_base = NULL;
1195
1196 return -ENODEV;
1197}
1198
1125static int __devinit snd_card_miro_detect(struct snd_card *card, 1199static int __devinit snd_card_miro_detect(struct snd_card *card,
1126 struct snd_miro *chip) 1200 struct snd_miro *chip)
1127{ 1201{
1128 int i, err; 1202 int i, err;
1129 unsigned char value;
1130 1203
1131 for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { 1204 for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
1132 1205
1133 if ((err = snd_miro_init(chip, i)) < 0) 1206 if ((err = snd_miro_init(chip, i)) < 0)
1134 return err; 1207 return err;
1135 1208
1136 if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) 1209 err = snd_miro_opti_check(chip);
1137 continue; 1210 if (err == 0)
1138 1211 return 1;
1139 value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
1140 if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
1141 if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
1142 return 1;
1143
1144 release_and_free_resource(chip->res_mc_base);
1145 chip->res_mc_base = NULL;
1146
1147 } 1212 }
1148 1213
1149 return -ENODEV; 1214 return -ENODEV;
1150} 1215}
1151 1216
1152static int __devinit snd_card_miro_aci_detect(struct snd_card *card, 1217static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
1153 struct snd_miro * miro) 1218 struct snd_miro *miro)
1154{ 1219{
1155 unsigned char regval; 1220 unsigned char regval;
1156 int i; 1221 int i;
1222 struct snd_miro_aci *aci = &aci_device;
1223
1224 miro->aci = aci;
1157 1225
1158 mutex_init(&miro->aci_mutex); 1226 mutex_init(&aci->aci_mutex);
1159 1227
1160 /* get ACI port from OPTi9xx MC 4 */ 1228 /* get ACI port from OPTi9xx MC 4 */
1161 1229
1162 miro->mc_base = 0xf8c;
1163 regval=inb(miro->mc_base + 4); 1230 regval=inb(miro->mc_base + 4);
1164 miro->aci_port = (regval & 0x10) ? 0x344: 0x354; 1231 aci->aci_port = (regval & 0x10) ? 0x344 : 0x354;
1165 1232
1166 if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) { 1233 miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci");
1234 if (miro->res_aci_port == NULL) {
1167 snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", 1235 snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
1168 miro->aci_port, miro->aci_port+2); 1236 aci->aci_port, aci->aci_port+2);
1169 return -ENOMEM; 1237 return -ENOMEM;
1170 } 1238 }
1171 1239
1172 /* force ACI into a known state */ 1240 /* force ACI into a known state */
1173 for (i = 0; i < 3; i++) 1241 for (i = 0; i < 3; i++)
1174 if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) { 1242 if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) {
1175 snd_printk(KERN_ERR "can't force aci into known state.\n"); 1243 snd_printk(KERN_ERR "can't force aci into known state.\n");
1176 return -ENXIO; 1244 return -ENXIO;
1177 } 1245 }
1178 1246
1179 if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 || 1247 aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
1180 (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) { 1248 aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
1181 snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port); 1249 if (aci->aci_vendor < 0 || aci->aci_product < 0) {
1250 snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n",
1251 aci->aci_port);
1182 return -ENXIO; 1252 return -ENXIO;
1183 } 1253 }
1184 1254
1185 if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) { 1255 aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1);
1256 if (aci->aci_version < 0) {
1186 snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", 1257 snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
1187 miro->aci_port); 1258 aci->aci_port);
1188 return -ENXIO; 1259 return -ENXIO;
1189 } 1260 }
1190 1261
1191 if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 || 1262 if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 ||
1192 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || 1263 snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
1193 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { 1264 snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
1194 snd_printk(KERN_ERR "can't initialize aci.\n"); 1265 snd_printk(KERN_ERR "can't initialize aci.\n");
1195 return -ENXIO; 1266 return -ENXIO;
1196 } 1267 }
@@ -1201,157 +1272,80 @@ static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
1201static void snd_card_miro_free(struct snd_card *card) 1272static void snd_card_miro_free(struct snd_card *card)
1202{ 1273{
1203 struct snd_miro *miro = card->private_data; 1274 struct snd_miro *miro = card->private_data;
1204 1275
1205 release_and_free_resource(miro->res_aci_port); 1276 release_and_free_resource(miro->res_aci_port);
1277 if (miro->aci)
1278 miro->aci->aci_port = 0;
1206 release_and_free_resource(miro->res_mc_base); 1279 release_and_free_resource(miro->res_mc_base);
1207} 1280}
1208 1281
1209static int __devinit snd_miro_match(struct device *devptr, unsigned int n) 1282static int __devinit snd_miro_probe(struct snd_card *card)
1210{
1211 return 1;
1212}
1213
1214static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
1215{ 1283{
1216 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
1217 static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
1218 static int possible_irqs[] = {11, 9, 10, 7, -1};
1219 static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
1220 static int possible_dma1s[] = {3, 1, 0, -1};
1221 static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
1222
1223 int error; 1284 int error;
1224 struct snd_miro *miro; 1285 struct snd_miro *miro = card->private_data;
1225 struct snd_wss *codec; 1286 struct snd_wss *codec;
1226 struct snd_timer *timer; 1287 struct snd_timer *timer;
1227 struct snd_card *card;
1228 struct snd_pcm *pcm; 1288 struct snd_pcm *pcm;
1229 struct snd_rawmidi *rmidi; 1289 struct snd_rawmidi *rmidi;
1230 1290
1231 error = snd_card_create(index, id, THIS_MODULE, 1291 if (!miro->res_mc_base) {
1232 sizeof(struct snd_miro), &card); 1292 miro->res_mc_base = request_region(miro->mc_base,
1233 if (error < 0) 1293 miro->mc_base_size,
1234 return error; 1294 "miro (OPTi9xx MC)");
1235 1295 if (miro->res_mc_base == NULL) {
1236 card->private_free = snd_card_miro_free; 1296 snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
1237 miro = card->private_data; 1297 return -ENOMEM;
1238 miro->card = card; 1298 }
1239
1240 if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
1241 snd_card_free(card);
1242 snd_printk(KERN_ERR "unable to detect aci chip\n");
1243 return -ENODEV;
1244 } 1299 }
1245 1300
1246 /* init proc interface */ 1301 error = snd_card_miro_aci_detect(card, miro);
1247 snd_miro_proc_init(miro); 1302 if (error < 0) {
1248
1249 if ((error = snd_card_miro_detect(card, miro)) < 0) {
1250 snd_card_free(card); 1303 snd_card_free(card);
1251 snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); 1304 snd_printk(KERN_ERR "unable to detect aci chip\n");
1252 return -ENODEV; 1305 return -ENODEV;
1253 } 1306 }
1254 1307
1255 if (! miro->res_mc_base &&
1256 (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
1257 "miro (OPTi9xx MC)")) == NULL) {
1258 snd_card_free(card);
1259 snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
1260 return -ENOMEM;
1261 }
1262
1263 miro->wss_base = port; 1308 miro->wss_base = port;
1264 miro->fm_port = fm_port;
1265 miro->mpu_port = mpu_port; 1309 miro->mpu_port = mpu_port;
1266 miro->irq = irq; 1310 miro->irq = irq;
1267 miro->mpu_irq = mpu_irq; 1311 miro->mpu_irq = mpu_irq;
1268 miro->dma1 = dma1; 1312 miro->dma1 = dma1;
1269 miro->dma2 = dma2; 1313 miro->dma2 = dma2;
1270 1314
1271 if (miro->wss_base == SNDRV_AUTO_PORT) { 1315 /* init proc interface */
1272 if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { 1316 snd_miro_proc_init(card, miro);
1273 snd_card_free(card);
1274 snd_printk(KERN_ERR "unable to find a free WSS port\n");
1275 return -EBUSY;
1276 }
1277 }
1278
1279 if (miro->mpu_port == SNDRV_AUTO_PORT) {
1280 if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
1281 snd_card_free(card);
1282 snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
1283 return -EBUSY;
1284 }
1285 }
1286 if (miro->irq == SNDRV_AUTO_IRQ) {
1287 if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
1288 snd_card_free(card);
1289 snd_printk(KERN_ERR "unable to find a free IRQ\n");
1290 return -EBUSY;
1291 }
1292 }
1293 if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
1294 if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
1295 snd_card_free(card);
1296 snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
1297 return -EBUSY;
1298 }
1299 }
1300 if (miro->dma1 == SNDRV_AUTO_DMA) {
1301 if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
1302 snd_card_free(card);
1303 snd_printk(KERN_ERR "unable to find a free DMA1\n");
1304 return -EBUSY;
1305 }
1306 }
1307 if (miro->dma2 == SNDRV_AUTO_DMA) {
1308 if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
1309 snd_card_free(card);
1310 snd_printk(KERN_ERR "unable to find a free DMA2\n");
1311 return -EBUSY;
1312 }
1313 }
1314 1317
1315 error = snd_miro_configure(miro); 1318 error = snd_miro_configure(miro);
1316 if (error) { 1319 if (error)
1317 snd_card_free(card);
1318 return error; 1320 return error;
1319 }
1320 1321
1321 error = snd_wss_create(card, miro->wss_base + 4, -1, 1322 error = snd_wss_create(card, miro->wss_base + 4, -1,
1322 miro->irq, miro->dma1, miro->dma2, 1323 miro->irq, miro->dma1, miro->dma2,
1323 WSS_HW_AD1845, 0, &codec); 1324 WSS_HW_DETECT, 0, &codec);
1324 if (error < 0) { 1325 if (error < 0)
1325 snd_card_free(card);
1326 return error; 1326 return error;
1327 }
1328 1327
1329 error = snd_wss_pcm(codec, 0, &pcm); 1328 error = snd_wss_pcm(codec, 0, &pcm);
1330 if (error < 0) { 1329 if (error < 0)
1331 snd_card_free(card);
1332 return error; 1330 return error;
1333 } 1331
1334 error = snd_wss_mixer(codec); 1332 error = snd_wss_mixer(codec);
1335 if (error < 0) { 1333 if (error < 0)
1336 snd_card_free(card);
1337 return error; 1334 return error;
1338 } 1335
1339 error = snd_wss_timer(codec, 0, &timer); 1336 error = snd_wss_timer(codec, 0, &timer);
1340 if (error < 0) { 1337 if (error < 0)
1341 snd_card_free(card);
1342 return error; 1338 return error;
1343 }
1344 1339
1345 miro->pcm = pcm; 1340 miro->pcm = pcm;
1346 1341
1347 if ((error = snd_miro_mixer(miro)) < 0) { 1342 error = snd_miro_mixer(card, miro);
1348 snd_card_free(card); 1343 if (error < 0)
1349 return error; 1344 return error;
1350 }
1351 1345
1352 if (miro->aci_vendor == 'm') { 1346 if (miro->aci->aci_vendor == 'm') {
1353 /* It looks like a miro sound card. */ 1347 /* It looks like a miro sound card. */
1354 switch (miro->aci_product) { 1348 switch (miro->aci->aci_product) {
1355 case 'A': 1349 case 'A':
1356 sprintf(card->shortname, 1350 sprintf(card->shortname,
1357 "miroSOUND PCM1 pro / PCM12"); 1351 "miroSOUND PCM1 pro / PCM12");
@@ -1380,30 +1374,131 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
1380 card->shortname, miro->name, pcm->name, miro->wss_base + 4, 1374 card->shortname, miro->name, pcm->name, miro->wss_base + 4,
1381 miro->irq, miro->dma1, miro->dma2); 1375 miro->irq, miro->dma1, miro->dma2);
1382 1376
1383 if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT) 1377 if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
1384 rmidi = NULL; 1378 rmidi = NULL;
1385 else 1379 else {
1386 if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, 1380 error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
1387 miro->mpu_port, 0, miro->mpu_irq, IRQF_DISABLED, 1381 mpu_port, 0, miro->mpu_irq, IRQF_DISABLED,
1388 &rmidi))) 1382 &rmidi);
1389 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port); 1383 if (error < 0)
1384 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
1385 mpu_port);
1386 }
1390 1387
1391 if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) { 1388 if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
1392 struct snd_opl3 *opl3 = NULL; 1389 struct snd_opl3 *opl3 = NULL;
1393 struct snd_opl4 *opl4; 1390 struct snd_opl4 *opl4;
1394 if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8, 1391
1392 if (snd_opl4_create(card, fm_port, fm_port - 8,
1395 2, &opl3, &opl4) < 0) 1393 2, &opl3, &opl4) < 0)
1396 snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port); 1394 snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n",
1395 fm_port);
1397 } 1396 }
1398 1397
1399 if ((error = snd_set_aci_init_values(miro)) < 0) { 1398 error = snd_set_aci_init_values(miro);
1400 snd_card_free(card); 1399 if (error < 0)
1401 return error; 1400 return error;
1401
1402 return snd_card_register(card);
1403}
1404
1405static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
1406{
1407#ifdef CONFIG_PNP
1408 if (snd_miro_pnp_is_probed)
1409 return 0;
1410 if (isapnp)
1411 return 0;
1412#endif
1413 return 1;
1414}
1415
1416static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
1417{
1418 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
1419 static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
1420 static int possible_irqs[] = {11, 9, 10, 7, -1};
1421 static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
1422 static int possible_dma1s[] = {3, 1, 0, -1};
1423 static int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1},
1424 {0, -1} };
1425
1426 int error;
1427 struct snd_miro *miro;
1428 struct snd_card *card;
1429
1430 error = snd_card_create(index, id, THIS_MODULE,
1431 sizeof(struct snd_miro), &card);
1432 if (error < 0)
1433 return error;
1434
1435 card->private_free = snd_card_miro_free;
1436 miro = card->private_data;
1437
1438 error = snd_card_miro_detect(card, miro);
1439 if (error < 0) {
1440 snd_card_free(card);
1441 snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
1442 return -ENODEV;
1443 }
1444
1445 if (port == SNDRV_AUTO_PORT) {
1446 port = snd_legacy_find_free_ioport(possible_ports, 4);
1447 if (port < 0) {
1448 snd_card_free(card);
1449 snd_printk(KERN_ERR "unable to find a free WSS port\n");
1450 return -EBUSY;
1451 }
1452 }
1453
1454 if (mpu_port == SNDRV_AUTO_PORT) {
1455 mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2);
1456 if (mpu_port < 0) {
1457 snd_card_free(card);
1458 snd_printk(KERN_ERR
1459 "unable to find a free MPU401 port\n");
1460 return -EBUSY;
1461 }
1462 }
1463
1464 if (irq == SNDRV_AUTO_IRQ) {
1465 irq = snd_legacy_find_free_irq(possible_irqs);
1466 if (irq < 0) {
1467 snd_card_free(card);
1468 snd_printk(KERN_ERR "unable to find a free IRQ\n");
1469 return -EBUSY;
1470 }
1471 }
1472 if (mpu_irq == SNDRV_AUTO_IRQ) {
1473 mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs);
1474 if (mpu_irq < 0) {
1475 snd_card_free(card);
1476 snd_printk(KERN_ERR
1477 "unable to find a free MPU401 IRQ\n");
1478 return -EBUSY;
1479 }
1480 }
1481 if (dma1 == SNDRV_AUTO_DMA) {
1482 dma1 = snd_legacy_find_free_dma(possible_dma1s);
1483 if (dma1 < 0) {
1484 snd_card_free(card);
1485 snd_printk(KERN_ERR "unable to find a free DMA1\n");
1486 return -EBUSY;
1487 }
1488 }
1489 if (dma2 == SNDRV_AUTO_DMA) {
1490 dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]);
1491 if (dma2 < 0) {
1492 snd_card_free(card);
1493 snd_printk(KERN_ERR "unable to find a free DMA2\n");
1494 return -EBUSY;
1495 }
1402 } 1496 }
1403 1497
1404 snd_card_set_dev(card, devptr); 1498 snd_card_set_dev(card, devptr);
1405 1499
1406 if ((error = snd_card_register(card))) { 1500 error = snd_miro_probe(card);
1501 if (error < 0) {
1407 snd_card_free(card); 1502 snd_card_free(card);
1408 return error; 1503 return error;
1409 } 1504 }
@@ -1412,7 +1507,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
1412 return 0; 1507 return 0;
1413} 1508}
1414 1509
1415static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev) 1510static int __devexit snd_miro_isa_remove(struct device *devptr,
1511 unsigned int dev)
1416{ 1512{
1417 snd_card_free(dev_get_drvdata(devptr)); 1513 snd_card_free(dev_get_drvdata(devptr));
1418 dev_set_drvdata(devptr, NULL); 1514 dev_set_drvdata(devptr, NULL);
@@ -1422,23 +1518,164 @@ static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev)
1422#define DEV_NAME "miro" 1518#define DEV_NAME "miro"
1423 1519
1424static struct isa_driver snd_miro_driver = { 1520static struct isa_driver snd_miro_driver = {
1425 .match = snd_miro_match, 1521 .match = snd_miro_isa_match,
1426 .probe = snd_miro_probe, 1522 .probe = snd_miro_isa_probe,
1427 .remove = __devexit_p(snd_miro_remove), 1523 .remove = __devexit_p(snd_miro_isa_remove),
1428 /* FIXME: suspend/resume */ 1524 /* FIXME: suspend/resume */
1429 .driver = { 1525 .driver = {
1430 .name = DEV_NAME 1526 .name = DEV_NAME
1431 }, 1527 },
1432}; 1528};
1433 1529
1530#ifdef CONFIG_PNP
1531
1532static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
1533 struct pnp_card_link *card,
1534 const struct pnp_card_device_id *pid)
1535{
1536 struct pnp_dev *pdev;
1537 int err;
1538 struct pnp_dev *devmpu;
1539 struct pnp_dev *devmc;
1540
1541 pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
1542 if (pdev == NULL)
1543 return -EBUSY;
1544
1545 devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
1546 if (devmpu == NULL)
1547 return -EBUSY;
1548
1549 devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
1550 if (devmc == NULL)
1551 return -EBUSY;
1552
1553 err = pnp_activate_dev(pdev);
1554 if (err < 0) {
1555 snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
1556 return err;
1557 }
1558
1559 err = pnp_activate_dev(devmc);
1560 if (err < 0) {
1561 snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
1562 err);
1563 return err;
1564 }
1565
1566 port = pnp_port_start(pdev, 1);
1567 fm_port = pnp_port_start(pdev, 2) + 8;
1568
1569 /*
1570 * The MC(0) is never accessed and the miroSOUND PCM20 card does not
1571 * include it in the PnP resource range. OPTI93x include it.
1572 */
1573 chip->mc_base = pnp_port_start(devmc, 0) - 1;
1574 chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
1575
1576 irq = pnp_irq(pdev, 0);
1577 dma1 = pnp_dma(pdev, 0);
1578 dma2 = pnp_dma(pdev, 1);
1579
1580 if (mpu_port > 0) {
1581 err = pnp_activate_dev(devmpu);
1582 if (err < 0) {
1583 snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
1584 mpu_port = -1;
1585 return err;
1586 }
1587 mpu_port = pnp_port_start(devmpu, 0);
1588 mpu_irq = pnp_irq(devmpu, 0);
1589 }
1590 return 0;
1591}
1592
1593static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
1594 const struct pnp_card_device_id *pid)
1595{
1596 struct snd_card *card;
1597 int err;
1598 struct snd_miro *miro;
1599
1600 if (snd_miro_pnp_is_probed)
1601 return -EBUSY;
1602 if (!isapnp)
1603 return -ENODEV;
1604 err = snd_card_create(index, id, THIS_MODULE,
1605 sizeof(struct snd_miro), &card);
1606 if (err < 0)
1607 return err;
1608
1609 card->private_free = snd_card_miro_free;
1610 miro = card->private_data;
1611
1612 err = snd_card_miro_pnp(miro, pcard, pid);
1613 if (err) {
1614 snd_card_free(card);
1615 return err;
1616 }
1617
1618 /* only miroSOUND PCM20 and PCM12 == OPTi924 */
1619 err = snd_miro_init(miro, OPTi9XX_HW_82C924);
1620 if (err) {
1621 snd_card_free(card);
1622 return err;
1623 }
1624
1625 err = snd_miro_opti_check(miro);
1626 if (err) {
1627 snd_printk(KERN_ERR "OPTI chip not found\n");
1628 snd_card_free(card);
1629 return err;
1630 }
1631
1632 snd_card_set_dev(card, &pcard->card->dev);
1633 err = snd_miro_probe(card);
1634 if (err < 0) {
1635 snd_card_free(card);
1636 return err;
1637 }
1638 pnp_set_card_drvdata(pcard, card);
1639 snd_miro_pnp_is_probed = 1;
1640 return 0;
1641}
1642
1643static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard)
1644{
1645 snd_card_free(pnp_get_card_drvdata(pcard));
1646 pnp_set_card_drvdata(pcard, NULL);
1647 snd_miro_pnp_is_probed = 0;
1648}
1649
1650static struct pnp_card_driver miro_pnpc_driver = {
1651 .flags = PNP_DRIVER_RES_DISABLE,
1652 .name = "miro",
1653 .id_table = snd_miro_pnpids,
1654 .probe = snd_miro_pnp_probe,
1655 .remove = __devexit_p(snd_miro_pnp_remove),
1656};
1657#endif
1658
1434static int __init alsa_card_miro_init(void) 1659static int __init alsa_card_miro_init(void)
1435{ 1660{
1661#ifdef CONFIG_PNP
1662 pnp_register_card_driver(&miro_pnpc_driver);
1663 if (snd_miro_pnp_is_probed)
1664 return 0;
1665 pnp_unregister_card_driver(&miro_pnpc_driver);
1666#endif
1436 return isa_register_driver(&snd_miro_driver, 1); 1667 return isa_register_driver(&snd_miro_driver, 1);
1437} 1668}
1438 1669
1439static void __exit alsa_card_miro_exit(void) 1670static void __exit alsa_card_miro_exit(void)
1440{ 1671{
1441 isa_unregister_driver(&snd_miro_driver); 1672 if (!snd_miro_pnp_is_probed) {
1673 isa_unregister_driver(&snd_miro_driver);
1674 return;
1675 }
1676#ifdef CONFIG_PNP
1677 pnp_unregister_card_driver(&miro_pnpc_driver);
1678#endif
1442} 1679}
1443 1680
1444module_init(alsa_card_miro_init) 1681module_init(alsa_card_miro_init)
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 5cd555325b9d..d08c38906449 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -141,15 +141,7 @@ struct snd_opti9xx {
141 141
142 spinlock_t lock; 142 spinlock_t lock;
143 143
144 long wss_base;
145 int irq; 144 int irq;
146 int dma1;
147 int dma2;
148
149 long fm_port;
150
151 long mpu_port;
152 int mpu_irq;
153 145
154#ifdef CONFIG_PNP 146#ifdef CONFIG_PNP
155 struct pnp_dev *dev; 147 struct pnp_dev *dev;
@@ -216,13 +208,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
216 208
217 spin_lock_init(&chip->lock); 209 spin_lock_init(&chip->lock);
218 210
219 chip->wss_base = -1;
220 chip->irq = -1; 211 chip->irq = -1;
221 chip->dma1 = -1;
222 chip->dma2 = -1;
223 chip->fm_port = -1;
224 chip->mpu_port = -1;
225 chip->mpu_irq = -1;
226 212
227 switch (hardware) { 213 switch (hardware) {
228#ifndef OPTi93X 214#ifndef OPTi93X
@@ -348,7 +334,10 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
348 (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) 334 (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
349 335
350 336
351static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) 337static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
338 long wss_base,
339 int irq, int dma1, int dma2,
340 long mpu_port, int mpu_irq)
352{ 341{
353 unsigned char wss_base_bits; 342 unsigned char wss_base_bits;
354 unsigned char irq_bits; 343 unsigned char irq_bits;
@@ -416,7 +405,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
416 return -EINVAL; 405 return -EINVAL;
417 } 406 }
418 407
419 switch (chip->wss_base) { 408 switch (wss_base) {
420 case 0x530: 409 case 0x530:
421 wss_base_bits = 0x00; 410 wss_base_bits = 0x00;
422 break; 411 break;
@@ -430,14 +419,13 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
430 wss_base_bits = 0x02; 419 wss_base_bits = 0x02;
431 break; 420 break;
432 default: 421 default:
433 snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", 422 snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
434 chip->wss_base);
435 goto __skip_base; 423 goto __skip_base;
436 } 424 }
437 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); 425 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
438 426
439__skip_base: 427__skip_base:
440 switch (chip->irq) { 428 switch (irq) {
441//#ifdef OPTi93X 429//#ifdef OPTi93X
442 case 5: 430 case 5:
443 irq_bits = 0x05; 431 irq_bits = 0x05;
@@ -456,11 +444,11 @@ __skip_base:
456 irq_bits = 0x04; 444 irq_bits = 0x04;
457 break; 445 break;
458 default: 446 default:
459 snd_printk(KERN_WARNING "WSS irq # %d not valid\n", chip->irq); 447 snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq);
460 goto __skip_resources; 448 goto __skip_resources;
461 } 449 }
462 450
463 switch (chip->dma1) { 451 switch (dma1) {
464 case 0: 452 case 0:
465 dma_bits = 0x01; 453 dma_bits = 0x01;
466 break; 454 break;
@@ -471,38 +459,36 @@ __skip_base:
471 dma_bits = 0x03; 459 dma_bits = 0x03;
472 break; 460 break;
473 default: 461 default:
474 snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", 462 snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1);
475 chip->dma1);
476 goto __skip_resources; 463 goto __skip_resources;
477 } 464 }
478 465
479#if defined(CS4231) || defined(OPTi93X) 466#if defined(CS4231) || defined(OPTi93X)
480 if (chip->dma1 == chip->dma2) { 467 if (dma1 == dma2) {
481 snd_printk(KERN_ERR "don't want to share dmas\n"); 468 snd_printk(KERN_ERR "don't want to share dmas\n");
482 return -EBUSY; 469 return -EBUSY;
483 } 470 }
484 471
485 switch (chip->dma2) { 472 switch (dma2) {
486 case 0: 473 case 0:
487 case 1: 474 case 1:
488 break; 475 break;
489 default: 476 default:
490 snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", 477 snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2);
491 chip->dma2);
492 goto __skip_resources; 478 goto __skip_resources;
493 } 479 }
494 dma_bits |= 0x04; 480 dma_bits |= 0x04;
495#endif /* CS4231 || OPTi93X */ 481#endif /* CS4231 || OPTi93X */
496 482
497#ifndef OPTi93X 483#ifndef OPTi93X
498 outb(irq_bits << 3 | dma_bits, chip->wss_base); 484 outb(irq_bits << 3 | dma_bits, wss_base);
499#else /* OPTi93X */ 485#else /* OPTi93X */
500 snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); 486 snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
501#endif /* OPTi93X */ 487#endif /* OPTi93X */
502 488
503__skip_resources: 489__skip_resources:
504 if (chip->hardware > OPTi9XX_HW_82C928) { 490 if (chip->hardware > OPTi9XX_HW_82C928) {
505 switch (chip->mpu_port) { 491 switch (mpu_port) {
506 case 0: 492 case 0:
507 case -1: 493 case -1:
508 break; 494 break;
@@ -520,12 +506,11 @@ __skip_resources:
520 break; 506 break;
521 default: 507 default:
522 snd_printk(KERN_WARNING 508 snd_printk(KERN_WARNING
523 "MPU-401 port 0x%lx not valid\n", 509 "MPU-401 port 0x%lx not valid\n", mpu_port);
524 chip->mpu_port);
525 goto __skip_mpu; 510 goto __skip_mpu;
526 } 511 }
527 512
528 switch (chip->mpu_irq) { 513 switch (mpu_irq) {
529 case 5: 514 case 5:
530 mpu_irq_bits = 0x02; 515 mpu_irq_bits = 0x02;
531 break; 516 break;
@@ -540,12 +525,12 @@ __skip_resources:
540 break; 525 break;
541 default: 526 default:
542 snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", 527 snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
543 chip->mpu_irq); 528 mpu_irq);
544 goto __skip_mpu; 529 goto __skip_mpu;
545 } 530 }
546 531
547 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 532 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
548 (chip->mpu_port <= 0) ? 0x00 : 533 (mpu_port <= 0) ? 0x00 :
549 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, 534 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
550 0xf8); 535 0xf8);
551 } 536 }
@@ -701,6 +686,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
701{ 686{
702 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; 687 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
703 int error; 688 int error;
689 int xdma2;
704 struct snd_opti9xx *chip = card->private_data; 690 struct snd_opti9xx *chip = card->private_data;
705 struct snd_wss *codec; 691 struct snd_wss *codec;
706#ifdef CS4231 692#ifdef CS4231
@@ -715,31 +701,25 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
715 "OPTi9xx MC")) == NULL) 701 "OPTi9xx MC")) == NULL)
716 return -ENOMEM; 702 return -ENOMEM;
717 703
718 chip->wss_base = port;
719 chip->fm_port = fm_port;
720 chip->mpu_port = mpu_port;
721 chip->irq = irq;
722 chip->mpu_irq = mpu_irq;
723 chip->dma1 = dma1;
724#if defined(CS4231) || defined(OPTi93X) 704#if defined(CS4231) || defined(OPTi93X)
725 chip->dma2 = dma2; 705 xdma2 = dma2;
726#else 706#else
727 chip->dma2 = -1; 707 xdma2 = -1;
728#endif 708#endif
729 709
730 if (chip->wss_base == SNDRV_AUTO_PORT) { 710 if (port == SNDRV_AUTO_PORT) {
731 chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4); 711 port = snd_legacy_find_free_ioport(possible_ports, 4);
732 if (chip->wss_base < 0) { 712 if (port < 0) {
733 snd_printk(KERN_ERR "unable to find a free WSS port\n"); 713 snd_printk(KERN_ERR "unable to find a free WSS port\n");
734 return -EBUSY; 714 return -EBUSY;
735 } 715 }
736 } 716 }
737 error = snd_opti9xx_configure(chip); 717 error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
718 mpu_port, mpu_irq);
738 if (error) 719 if (error)
739 return error; 720 return error;
740 721
741 error = snd_wss_create(card, chip->wss_base + 4, -1, 722 error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
742 chip->irq, chip->dma1, chip->dma2,
743#ifdef OPTi93X 723#ifdef OPTi93X
744 WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, 724 WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
745#else 725#else
@@ -763,35 +743,35 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
763 return error; 743 return error;
764#endif 744#endif
765#ifdef OPTi93X 745#ifdef OPTi93X
766 error = request_irq(chip->irq, snd_opti93x_interrupt, 746 error = request_irq(irq, snd_opti93x_interrupt,
767 IRQF_DISABLED, DEV_NAME" - WSS", codec); 747 IRQF_DISABLED, DEV_NAME" - WSS", codec);
768 if (error < 0) { 748 if (error < 0) {
769 snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); 749 snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
770 return error; 750 return error;
771 } 751 }
772#endif 752#endif
753 chip->irq = irq;
773 strcpy(card->driver, chip->name); 754 strcpy(card->driver, chip->name);
774 sprintf(card->shortname, "OPTi %s", card->driver); 755 sprintf(card->shortname, "OPTi %s", card->driver);
775#if defined(CS4231) || defined(OPTi93X) 756#if defined(CS4231) || defined(OPTi93X)
776 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", 757 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
777 card->shortname, pcm->name, chip->wss_base + 4, 758 card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
778 chip->irq, chip->dma1, chip->dma2);
779#else 759#else
780 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", 760 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
781 card->shortname, pcm->name, chip->wss_base + 4, 761 card->shortname, pcm->name, port + 4, irq, dma1);
782 chip->irq, chip->dma1);
783#endif /* CS4231 || OPTi93X */ 762#endif /* CS4231 || OPTi93X */
784 763
785 if (chip->mpu_port <= 0 || chip->mpu_port == SNDRV_AUTO_PORT) 764 if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
786 rmidi = NULL; 765 rmidi = NULL;
787 else 766 else {
788 if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, 767 error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
789 chip->mpu_port, 0, chip->mpu_irq, IRQF_DISABLED, 768 mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi);
790 &rmidi))) 769 if (error)
791 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", 770 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
792 chip->mpu_port); 771 mpu_port);
772 }
793 773
794 if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) { 774 if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
795 struct snd_opl3 *opl3 = NULL; 775 struct snd_opl3 *opl3 = NULL;
796#ifndef OPTi93X 776#ifndef OPTi93X
797 if (chip->hardware == OPTi9XX_HW_82C928 || 777 if (chip->hardware == OPTi9XX_HW_82C928 ||
@@ -801,9 +781,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
801 /* assume we have an OPL4 */ 781 /* assume we have an OPL4 */
802 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 782 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
803 0x20, 0x20); 783 0x20, 0x20);
804 if (snd_opl4_create(card, 784 if (snd_opl4_create(card, fm_port, fm_port - 8,
805 chip->fm_port,
806 chip->fm_port - 8,
807 2, &opl3, &opl4) < 0) { 785 2, &opl3, &opl4) < 0) {
808 /* no luck, use OPL3 instead */ 786 /* no luck, use OPL3 instead */
809 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 787 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
@@ -811,12 +789,10 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
811 } 789 }
812 } 790 }
813#endif /* !OPTi93X */ 791#endif /* !OPTi93X */
814 if (!opl3 && snd_opl3_create(card, 792 if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2,
815 chip->fm_port,
816 chip->fm_port + 2,
817 OPL3_HW_AUTO, 0, &opl3) < 0) { 793 OPL3_HW_AUTO, 0, &opl3) < 0) {
818 snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", 794 snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
819 chip->fm_port, chip->fm_port + 4 - 1); 795 fm_port, fm_port + 4 - 1);
820 } 796 }
821 if (opl3) { 797 if (opl3) {
822 error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); 798 error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 475220bbcc96..318ff0c823e7 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -631,7 +631,7 @@ static struct sbmix_elem snd_sb16_ctl_mic_play_switch =
631static struct sbmix_elem snd_sb16_ctl_mic_play_vol = 631static struct sbmix_elem snd_sb16_ctl_mic_play_vol =
632 SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31); 632 SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31);
633static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol = 633static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol =
634 SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3); 634 SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
635static struct sbmix_elem snd_sb16_ctl_capture_vol = 635static struct sbmix_elem snd_sb16_ctl_capture_vol =
636 SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3); 636 SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3);
637static struct sbmix_elem snd_sb16_ctl_play_vol = 637static struct sbmix_elem snd_sb16_ctl_play_vol =
@@ -689,7 +689,7 @@ static struct sbmix_elem snd_dt019x_ctl_cd_play_vol =
689static struct sbmix_elem snd_dt019x_ctl_mic_play_vol = 689static struct sbmix_elem snd_dt019x_ctl_mic_play_vol =
690 SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7); 690 SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7);
691static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol = 691static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol =
692 SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7); 692 SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0, 7);
693static struct sbmix_elem snd_dt019x_ctl_line_play_vol = 693static struct sbmix_elem snd_dt019x_ctl_line_play_vol =
694 SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15); 694 SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15);
695static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch = 695static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch =
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 66187122377c..e2d5d2d3ed96 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Low-level ALSA driver for the ENSONIQ SoundScape PnP 2 * Low-level ALSA driver for the ENSONIQ SoundScape
3 * Copyright (c) by Chris Rankin 3 * Copyright (c) by Chris Rankin
4 * 4 *
5 * This driver was written in part using information obtained from 5 * This driver was written in part using information obtained from
@@ -25,31 +25,36 @@
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/isa.h> 26#include <linux/isa.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/firmware.h>
28#include <linux/pnp.h> 29#include <linux/pnp.h>
29#include <linux/spinlock.h> 30#include <linux/spinlock.h>
30#include <linux/moduleparam.h> 31#include <linux/moduleparam.h>
31#include <asm/dma.h> 32#include <asm/dma.h>
32#include <sound/core.h> 33#include <sound/core.h>
33#include <sound/hwdep.h>
34#include <sound/wss.h> 34#include <sound/wss.h>
35#include <sound/mpu401.h> 35#include <sound/mpu401.h>
36#include <sound/initval.h> 36#include <sound/initval.h>
37 37
38#include <sound/sscape_ioctl.h>
39
40 38
41MODULE_AUTHOR("Chris Rankin"); 39MODULE_AUTHOR("Chris Rankin");
42MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver"); 40MODULE_DESCRIPTION("ENSONIQ SoundScape driver");
43MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
44 42MODULE_FIRMWARE("sndscape.co0");
45static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX; 43MODULE_FIRMWARE("sndscape.co1");
46static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR; 44MODULE_FIRMWARE("sndscape.co2");
47static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; 45MODULE_FIRMWARE("sndscape.co3");
48static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; 46MODULE_FIRMWARE("sndscape.co4");
49static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; 47MODULE_FIRMWARE("scope.cod");
50static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; 48
51static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; 49static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
52static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; 50static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
51static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
52static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
53static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
54static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
55static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
56static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
57static bool joystick[SNDRV_CARDS];
53 58
54module_param_array(index, int, NULL, 0444); 59module_param_array(index, int, NULL, 0444);
55MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); 60MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
@@ -75,6 +80,9 @@ MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
75module_param_array(dma2, int, NULL, 0444); 80module_param_array(dma2, int, NULL, 0444);
76MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver."); 81MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
77 82
83module_param_array(joystick, bool, NULL, 0444);
84MODULE_PARM_DESC(joystick, "Enable gameport.");
85
78#ifdef CONFIG_PNP 86#ifdef CONFIG_PNP
79static int isa_registered; 87static int isa_registered;
80static int pnp_registered; 88static int pnp_registered;
@@ -101,14 +109,14 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
101#define RX_READY 0x01 109#define RX_READY 0x01
102#define TX_READY 0x02 110#define TX_READY 0x02
103 111
104#define CMD_ACK 0x80 112#define CMD_ACK 0x80
105#define CMD_SET_MIDI_VOL 0x84 113#define CMD_SET_MIDI_VOL 0x84
106#define CMD_GET_MIDI_VOL 0x85 114#define CMD_GET_MIDI_VOL 0x85
107#define CMD_XXX_MIDI_VOL 0x86 115#define CMD_XXX_MIDI_VOL 0x86
108#define CMD_SET_EXTMIDI 0x8a 116#define CMD_SET_EXTMIDI 0x8a
109#define CMD_GET_EXTMIDI 0x8b 117#define CMD_GET_EXTMIDI 0x8b
110#define CMD_SET_MT32 0x8c 118#define CMD_SET_MT32 0x8c
111#define CMD_GET_MT32 0x8d 119#define CMD_GET_MT32 0x8d
112 120
113enum GA_REG { 121enum GA_REG {
114 GA_INTSTAT_REG = 0, 122 GA_INTSTAT_REG = 0,
@@ -127,7 +135,8 @@ enum GA_REG {
127 135
128 136
129enum card_type { 137enum card_type {
130 SSCAPE, 138 MEDIA_FX, /* Sequoia S-1000 */
139 SSCAPE, /* Sequoia S-2000 */
131 SSCAPE_PNP, 140 SSCAPE_PNP,
132 SSCAPE_VIVO, 141 SSCAPE_VIVO,
133}; 142};
@@ -140,16 +149,7 @@ struct soundscape {
140 struct resource *io_res; 149 struct resource *io_res;
141 struct resource *wss_res; 150 struct resource *wss_res;
142 struct snd_wss *chip; 151 struct snd_wss *chip;
143 struct snd_mpu401 *mpu;
144 struct snd_hwdep *hw;
145 152
146 /*
147 * The MIDI device won't work until we've loaded
148 * its firmware via a hardware-dependent device IOCTL
149 */
150 spinlock_t fwlock;
151 int hw_in_use;
152 unsigned long midi_usage;
153 unsigned char midi_vol; 153 unsigned char midi_vol;
154}; 154};
155 155
@@ -161,28 +161,21 @@ static inline struct soundscape *get_card_soundscape(struct snd_card *c)
161 return (struct soundscape *) (c->private_data); 161 return (struct soundscape *) (c->private_data);
162} 162}
163 163
164static inline struct soundscape *get_mpu401_soundscape(struct snd_mpu401 * mpu)
165{
166 return (struct soundscape *) (mpu->private_data);
167}
168
169static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep * hw)
170{
171 return (struct soundscape *) (hw->private_data);
172}
173
174
175/* 164/*
176 * Allocates some kernel memory that we can use for DMA. 165 * Allocates some kernel memory that we can use for DMA.
177 * I think this means that the memory has to map to 166 * I think this means that the memory has to map to
178 * contiguous pages of physical memory. 167 * contiguous pages of physical memory.
179 */ 168 */
180static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size) 169static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf,
170 unsigned long size)
181{ 171{
182 if (buf) { 172 if (buf) {
183 if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(), 173 if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
174 snd_dma_isa_data(),
184 size, buf) < 0) { 175 size, buf) < 0) {
185 snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size); 176 snd_printk(KERN_ERR "sscape: Failed to allocate "
177 "%lu bytes for DMA\n",
178 size);
186 return NULL; 179 return NULL;
187 } 180 }
188 } 181 }
@@ -199,13 +192,13 @@ static void free_dmabuf(struct snd_dma_buffer *buf)
199 snd_dma_free_pages(buf); 192 snd_dma_free_pages(buf);
200} 193}
201 194
202
203/* 195/*
204 * This function writes to the SoundScape's control registers, 196 * This function writes to the SoundScape's control registers,
205 * but doesn't do any locking. It's up to the caller to do that. 197 * but doesn't do any locking. It's up to the caller to do that.
206 * This is why this function is "unsafe" ... 198 * This is why this function is "unsafe" ...
207 */ 199 */
208static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val) 200static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg,
201 unsigned char val)
209{ 202{
210 outb(reg, ODIE_ADDR_IO(io_base)); 203 outb(reg, ODIE_ADDR_IO(io_base));
211 outb(val, ODIE_DATA_IO(io_base)); 204 outb(val, ODIE_DATA_IO(io_base));
@@ -215,7 +208,8 @@ static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsign
215 * Write to the SoundScape's control registers, and do the 208 * Write to the SoundScape's control registers, and do the
216 * necessary locking ... 209 * necessary locking ...
217 */ 210 */
218static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val) 211static void sscape_write(struct soundscape *s, enum GA_REG reg,
212 unsigned char val)
219{ 213{
220 unsigned long flags; 214 unsigned long flags;
221 215
@@ -228,7 +222,8 @@ static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char va
228 * Read from the SoundScape's control registers, but leave any 222 * Read from the SoundScape's control registers, but leave any
229 * locking to the caller. This is why the function is "unsafe" ... 223 * locking to the caller. This is why the function is "unsafe" ...
230 */ 224 */
231static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg) 225static inline unsigned char sscape_read_unsafe(unsigned io_base,
226 enum GA_REG reg)
232{ 227{
233 outb(reg, ODIE_ADDR_IO(io_base)); 228 outb(reg, ODIE_ADDR_IO(io_base));
234 return inb(ODIE_DATA_IO(io_base)); 229 return inb(ODIE_DATA_IO(io_base));
@@ -257,9 +252,8 @@ static inline void set_midi_mode_unsafe(unsigned io_base)
257static inline int host_read_unsafe(unsigned io_base) 252static inline int host_read_unsafe(unsigned io_base)
258{ 253{
259 int data = -1; 254 int data = -1;
260 if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) { 255 if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0)
261 data = inb(HOST_DATA_IO(io_base)); 256 data = inb(HOST_DATA_IO(io_base));
262 }
263 257
264 return data; 258 return data;
265} 259}
@@ -301,7 +295,7 @@ static inline int host_write_unsafe(unsigned io_base, unsigned char data)
301 * Also leaves all locking-issues to the caller ... 295 * Also leaves all locking-issues to the caller ...
302 */ 296 */
303static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, 297static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
304 unsigned timeout) 298 unsigned timeout)
305{ 299{
306 int err; 300 int err;
307 301
@@ -320,7 +314,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
320 * 314 *
321 * NOTE: This check is based upon observation, not documentation. 315 * NOTE: This check is based upon observation, not documentation.
322 */ 316 */
323static inline int verify_mpu401(const struct snd_mpu401 * mpu) 317static inline int verify_mpu401(const struct snd_mpu401 *mpu)
324{ 318{
325 return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); 319 return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
326} 320}
@@ -328,7 +322,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu)
328/* 322/*
329 * This is apparently the standard way to initailise an MPU-401 323 * This is apparently the standard way to initailise an MPU-401
330 */ 324 */
331static inline void initialise_mpu401(const struct snd_mpu401 * mpu) 325static inline void initialise_mpu401(const struct snd_mpu401 *mpu)
332{ 326{
333 outb(0, MPU401D(mpu)); 327 outb(0, MPU401D(mpu));
334} 328}
@@ -338,9 +332,10 @@ static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
338 * The AD1845 detection fails if we *don't* do this, so I 332 * The AD1845 detection fails if we *don't* do this, so I
339 * think that this is a good idea ... 333 * think that this is a good idea ...
340 */ 334 */
341static inline void activate_ad1845_unsafe(unsigned io_base) 335static void activate_ad1845_unsafe(unsigned io_base)
342{ 336{
343 sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10); 337 unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG);
338 sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10);
344 sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80); 339 sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
345} 340}
346 341
@@ -359,24 +354,27 @@ static void soundscape_free(struct snd_card *c)
359 * Tell the SoundScape to begin a DMA tranfer using the given channel. 354 * Tell the SoundScape to begin a DMA tranfer using the given channel.
360 * All locking issues are left to the caller. 355 * All locking issues are left to the caller.
361 */ 356 */
362static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg) 357static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
363{ 358{
364 sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01); 359 sscape_write_unsafe(io_base, reg,
365 sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe); 360 sscape_read_unsafe(io_base, reg) | 0x01);
361 sscape_write_unsafe(io_base, reg,
362 sscape_read_unsafe(io_base, reg) & 0xfe);
366} 363}
367 364
368/* 365/*
369 * Wait for a DMA transfer to complete. This is a "limited busy-wait", 366 * Wait for a DMA transfer to complete. This is a "limited busy-wait",
370 * and all locking issues are left to the caller. 367 * and all locking issues are left to the caller.
371 */ 368 */
372static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout) 369static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg,
370 unsigned timeout)
373{ 371{
374 while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) { 372 while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
375 udelay(100); 373 udelay(100);
376 --timeout; 374 --timeout;
377 } /* while */ 375 } /* while */
378 376
379 return (sscape_read_unsafe(io_base, reg) & 0x01); 377 return sscape_read_unsafe(io_base, reg) & 0x01;
380} 378}
381 379
382/* 380/*
@@ -392,12 +390,12 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
392 390
393 do { 391 do {
394 unsigned long flags; 392 unsigned long flags;
395 unsigned char x; 393 int x;
396 394
397 spin_lock_irqsave(&s->lock, flags); 395 spin_lock_irqsave(&s->lock, flags);
398 x = inb(HOST_DATA_IO(s->io_base)); 396 x = host_read_unsafe(s->io_base);
399 spin_unlock_irqrestore(&s->lock, flags); 397 spin_unlock_irqrestore(&s->lock, flags);
400 if ((x & 0xfe) == 0xfe) 398 if (x == 0xfe || x == 0xff)
401 return 1; 399 return 1;
402 400
403 msleep(10); 401 msleep(10);
@@ -419,10 +417,10 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
419 417
420 do { 418 do {
421 unsigned long flags; 419 unsigned long flags;
422 unsigned char x; 420 int x;
423 421
424 spin_lock_irqsave(&s->lock, flags); 422 spin_lock_irqsave(&s->lock, flags);
425 x = inb(HOST_DATA_IO(s->io_base)); 423 x = host_read_unsafe(s->io_base);
426 spin_unlock_irqrestore(&s->lock, flags); 424 spin_unlock_irqrestore(&s->lock, flags);
427 if (x == 0xfe) 425 if (x == 0xfe)
428 return 1; 426 return 1;
@@ -436,15 +434,15 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
436/* 434/*
437 * Upload a byte-stream into the SoundScape using DMA channel A. 435 * Upload a byte-stream into the SoundScape using DMA channel A.
438 */ 436 */
439static int upload_dma_data(struct soundscape *s, 437static int upload_dma_data(struct soundscape *s, const unsigned char *data,
440 const unsigned char __user *data, 438 size_t size)
441 size_t size)
442{ 439{
443 unsigned long flags; 440 unsigned long flags;
444 struct snd_dma_buffer dma; 441 struct snd_dma_buffer dma;
445 int ret; 442 int ret;
443 unsigned char val;
446 444
447 if (!get_dmabuf(&dma, PAGE_ALIGN(size))) 445 if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024)))
448 return -ENOMEM; 446 return -ENOMEM;
449 447
450 spin_lock_irqsave(&s->lock, flags); 448 spin_lock_irqsave(&s->lock, flags);
@@ -452,70 +450,57 @@ static int upload_dma_data(struct soundscape *s,
452 /* 450 /*
453 * Reset the board ... 451 * Reset the board ...
454 */ 452 */
455 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f); 453 val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
454 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f);
456 455
457 /* 456 /*
458 * Enable the DMA channels and configure them ... 457 * Enable the DMA channels and configure them ...
459 */ 458 */
460 sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50); 459 val = (s->chip->dma1 << 4) | DMA_8BIT;
461 sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT); 460 sscape_write_unsafe(s->io_base, GA_DMAA_REG, val);
462 sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20); 461 sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);
463 462
464 /* 463 /*
465 * Take the board out of reset ... 464 * Take the board out of reset ...
466 */ 465 */
467 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80); 466 val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
467 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80);
468 468
469 /* 469 /*
470 * Upload the user's data (firmware?) to the SoundScape 470 * Upload the firmware to the SoundScape
471 * board through the DMA channel ... 471 * board through the DMA channel ...
472 */ 472 */
473 while (size != 0) { 473 while (size != 0) {
474 unsigned long len; 474 unsigned long len;
475 475
476 /*
477 * Apparently, copying to/from userspace can sleep.
478 * We are therefore forbidden from holding any
479 * spinlocks while we copy ...
480 */
481 spin_unlock_irqrestore(&s->lock, flags);
482
483 /*
484 * Remember that the data that we want to DMA
485 * comes from USERSPACE. We have already verified
486 * the userspace pointer ...
487 */
488 len = min(size, dma.bytes); 476 len = min(size, dma.bytes);
489 len -= __copy_from_user(dma.area, data, len); 477 memcpy(dma.area, data, len);
490 data += len; 478 data += len;
491 size -= len; 479 size -= len;
492 480
493 /*
494 * Grab that spinlock again, now that we've
495 * finished copying!
496 */
497 spin_lock_irqsave(&s->lock, flags);
498
499 snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE); 481 snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
500 sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG); 482 sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
501 if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) { 483 if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
502 /* 484 /*
503 * Don't forget to release this spinlock we're holding ... 485 * Don't forget to release this spinlock we're holding
504 */ 486 */
505 spin_unlock_irqrestore(&s->lock, flags); 487 spin_unlock_irqrestore(&s->lock, flags);
506 488
507 snd_printk(KERN_ERR "sscape: DMA upload has timed out\n"); 489 snd_printk(KERN_ERR
490 "sscape: DMA upload has timed out\n");
508 ret = -EAGAIN; 491 ret = -EAGAIN;
509 goto _release_dma; 492 goto _release_dma;
510 } 493 }
511 } /* while */ 494 } /* while */
512 495
513 set_host_mode_unsafe(s->io_base); 496 set_host_mode_unsafe(s->io_base);
497 outb(0x0, s->io_base);
514 498
515 /* 499 /*
516 * Boot the board ... (I think) 500 * Boot the board ... (I think)
517 */ 501 */
518 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40); 502 val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
503 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40);
519 spin_unlock_irqrestore(&s->lock, flags); 504 spin_unlock_irqrestore(&s->lock, flags);
520 505
521 /* 506 /*
@@ -525,10 +510,12 @@ static int upload_dma_data(struct soundscape *s,
525 */ 510 */
526 ret = 0; 511 ret = 0;
527 if (!obp_startup_ack(s, 5000)) { 512 if (!obp_startup_ack(s, 5000)) {
528 snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); 513 snd_printk(KERN_ERR "sscape: No response "
514 "from on-board processor after upload\n");
529 ret = -EAGAIN; 515 ret = -EAGAIN;
530 } else if (!host_startup_ack(s, 5000)) { 516 } else if (!host_startup_ack(s, 5000)) {
531 snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); 517 snd_printk(KERN_ERR
518 "sscape: SoundScape failed to initialise\n");
532 ret = -EAGAIN; 519 ret = -EAGAIN;
533 } 520 }
534 521
@@ -536,7 +523,7 @@ _release_dma:
536 /* 523 /*
537 * NOTE!!! We are NOT holding any spinlocks at this point !!! 524 * NOTE!!! We are NOT holding any spinlocks at this point !!!
538 */ 525 */
539 sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40)); 526 sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70));
540 free_dmabuf(&dma); 527 free_dmabuf(&dma);
541 528
542 return ret; 529 return ret;
@@ -546,167 +533,76 @@ _release_dma:
546 * Upload the bootblock(?) into the SoundScape. The only 533 * Upload the bootblock(?) into the SoundScape. The only
547 * purpose of this block of code seems to be to tell 534 * purpose of this block of code seems to be to tell
548 * us which version of the microcode we should be using. 535 * us which version of the microcode we should be using.
549 *
550 * NOTE: The boot-block data resides in USER-SPACE!!!
551 * However, we have already verified its memory
552 * addresses by the time we get here.
553 */ 536 */
554static int sscape_upload_bootblock(struct soundscape *sscape, struct sscape_bootblock __user *bb) 537static int sscape_upload_bootblock(struct snd_card *card)
555{ 538{
539 struct soundscape *sscape = get_card_soundscape(card);
556 unsigned long flags; 540 unsigned long flags;
541 const struct firmware *init_fw = NULL;
557 int data = 0; 542 int data = 0;
558 int ret; 543 int ret;
559 544
560 ret = upload_dma_data(sscape, bb->code, sizeof(bb->code)); 545 ret = request_firmware(&init_fw, "scope.cod", card->dev);
561 546 if (ret < 0) {
562 spin_lock_irqsave(&sscape->lock, flags); 547 snd_printk(KERN_ERR "sscape: Error loading scope.cod");
563 if (ret == 0) { 548 return ret;
564 data = host_read_ctrl_unsafe(sscape->io_base, 100);
565 }
566 set_midi_mode_unsafe(sscape->io_base);
567 spin_unlock_irqrestore(&sscape->lock, flags);
568
569 if (ret == 0) {
570 if (data < 0) {
571 snd_printk(KERN_ERR "sscape: timeout reading firmware version\n");
572 ret = -EAGAIN;
573 }
574 else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) {
575 ret = -EFAULT;
576 }
577 } 549 }
550 ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
578 551
579 return ret; 552 release_firmware(init_fw);
580}
581
582/*
583 * Upload the microcode into the SoundScape. The
584 * microcode is 64K of data, and if we try to copy
585 * it into a local variable then we will SMASH THE
586 * KERNEL'S STACK! We therefore leave it in USER
587 * SPACE, and save ourselves from copying it at all.
588 */
589static int sscape_upload_microcode(struct soundscape *sscape,
590 const struct sscape_microcode __user *mc)
591{
592 unsigned long flags;
593 char __user *code;
594 int err;
595 553
596 /* 554 spin_lock_irqsave(&sscape->lock, flags);
597 * We are going to have to copy this data into a special 555 if (ret == 0)
598 * DMA-able buffer before we can upload it. We shall therefore 556 data = host_read_ctrl_unsafe(sscape->io_base, 100);
599 * just check that the data pointer is valid for now.
600 *
601 * NOTE: This buffer is 64K long! That's WAY too big to
602 * copy into a stack-temporary anyway.
603 */
604 if ( get_user(code, &mc->code) ||
605 !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) )
606 return -EFAULT;
607 557
608 if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) { 558 if (data & 0x10)
609 snd_printk(KERN_INFO "sscape: MIDI firmware loaded\n"); 559 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f);
610 }
611 560
612 spin_lock_irqsave(&sscape->lock, flags);
613 set_midi_mode_unsafe(sscape->io_base);
614 spin_unlock_irqrestore(&sscape->lock, flags); 561 spin_unlock_irqrestore(&sscape->lock, flags);
615 562
616 initialise_mpu401(sscape->mpu); 563 data &= 0xf;
564 if (ret == 0 && data > 7) {
565 snd_printk(KERN_ERR
566 "sscape: timeout reading firmware version\n");
567 ret = -EAGAIN;
568 }
617 569
618 return err; 570 return (ret == 0) ? data : ret;
619} 571}
620 572
621/* 573/*
622 * Hardware-specific device functions, to implement special 574 * Upload the microcode into the SoundScape.
623 * IOCTLs for the SoundScape card. This is how we upload
624 * the microcode into the card, for example, and so we
625 * must ensure that no two processes can open this device
626 * simultaneously, and that we can't open it at all if
627 * someone is using the MIDI device.
628 */ 575 */
629static int sscape_hw_open(struct snd_hwdep * hw, struct file *file) 576static int sscape_upload_microcode(struct snd_card *card, int version)
630{ 577{
631 register struct soundscape *sscape = get_hwdep_soundscape(hw); 578 struct soundscape *sscape = get_card_soundscape(card);
632 unsigned long flags; 579 const struct firmware *init_fw = NULL;
580 char name[14];
633 int err; 581 int err;
634 582
635 spin_lock_irqsave(&sscape->fwlock, flags); 583 snprintf(name, sizeof(name), "sndscape.co%d", version);
636 584
637 if ((sscape->midi_usage != 0) || sscape->hw_in_use) { 585 err = request_firmware(&init_fw, name, card->dev);
638 err = -EBUSY; 586 if (err < 0) {
639 } else { 587 snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d",
640 sscape->hw_in_use = 1; 588 version);
641 err = 0; 589 return err;
642 } 590 }
591 err = upload_dma_data(sscape, init_fw->data, init_fw->size);
592 if (err == 0)
593 snd_printk(KERN_INFO "sscape: MIDI firmware loaded %d KBs\n",
594 init_fw->size >> 10);
643 595
644 spin_unlock_irqrestore(&sscape->fwlock, flags); 596 release_firmware(init_fw);
645 return err;
646}
647
648static int sscape_hw_release(struct snd_hwdep * hw, struct file *file)
649{
650 register struct soundscape *sscape = get_hwdep_soundscape(hw);
651 unsigned long flags;
652
653 spin_lock_irqsave(&sscape->fwlock, flags);
654 sscape->hw_in_use = 0;
655 spin_unlock_irqrestore(&sscape->fwlock, flags);
656 return 0;
657}
658
659static int sscape_hw_ioctl(struct snd_hwdep * hw, struct file *file,
660 unsigned int cmd, unsigned long arg)
661{
662 struct soundscape *sscape = get_hwdep_soundscape(hw);
663 int err = -EBUSY;
664
665 switch (cmd) {
666 case SND_SSCAPE_LOAD_BOOTB:
667 {
668 register struct sscape_bootblock __user *bb = (struct sscape_bootblock __user *) arg;
669
670 /*
671 * We are going to have to copy this data into a special
672 * DMA-able buffer before we can upload it. We shall therefore
673 * just check that the data pointer is valid for now ...
674 */
675 if ( !access_ok(VERIFY_READ, bb->code, sizeof(bb->code)) )
676 return -EFAULT;
677
678 /*
679 * Now check that we can write the firmware version number too...
680 */
681 if ( !access_ok(VERIFY_WRITE, &bb->version, sizeof(bb->version)) )
682 return -EFAULT;
683
684 err = sscape_upload_bootblock(sscape, bb);
685 }
686 break;
687
688 case SND_SSCAPE_LOAD_MCODE:
689 {
690 register const struct sscape_microcode __user *mc = (const struct sscape_microcode __user *) arg;
691
692 err = sscape_upload_microcode(sscape, mc);
693 }
694 break;
695
696 default:
697 err = -EINVAL;
698 break;
699 } /* switch */
700 597
701 return err; 598 return err;
702} 599}
703 600
704
705/* 601/*
706 * Mixer control for the SoundScape's MIDI device. 602 * Mixer control for the SoundScape's MIDI device.
707 */ 603 */
708static int sscape_midi_info(struct snd_kcontrol *ctl, 604static int sscape_midi_info(struct snd_kcontrol *ctl,
709 struct snd_ctl_elem_info *uinfo) 605 struct snd_ctl_elem_info *uinfo)
710{ 606{
711 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 607 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
712 uinfo->count = 1; 608 uinfo->count = 1;
@@ -716,7 +612,7 @@ static int sscape_midi_info(struct snd_kcontrol *ctl,
716} 612}
717 613
718static int sscape_midi_get(struct snd_kcontrol *kctl, 614static int sscape_midi_get(struct snd_kcontrol *kctl,
719 struct snd_ctl_elem_value *uctl) 615 struct snd_ctl_elem_value *uctl)
720{ 616{
721 struct snd_wss *chip = snd_kcontrol_chip(kctl); 617 struct snd_wss *chip = snd_kcontrol_chip(kctl);
722 struct snd_card *card = chip->card; 618 struct snd_card *card = chip->card;
@@ -730,16 +626,18 @@ static int sscape_midi_get(struct snd_kcontrol *kctl,
730} 626}
731 627
732static int sscape_midi_put(struct snd_kcontrol *kctl, 628static int sscape_midi_put(struct snd_kcontrol *kctl,
733 struct snd_ctl_elem_value *uctl) 629 struct snd_ctl_elem_value *uctl)
734{ 630{
735 struct snd_wss *chip = snd_kcontrol_chip(kctl); 631 struct snd_wss *chip = snd_kcontrol_chip(kctl);
736 struct snd_card *card = chip->card; 632 struct snd_card *card = chip->card;
737 register struct soundscape *s = get_card_soundscape(card); 633 struct soundscape *s = get_card_soundscape(card);
738 unsigned long flags; 634 unsigned long flags;
739 int change; 635 int change;
636 unsigned char new_val;
740 637
741 spin_lock_irqsave(&s->lock, flags); 638 spin_lock_irqsave(&s->lock, flags);
742 639
640 new_val = uctl->value.integer.value[0] & 127;
743 /* 641 /*
744 * We need to put the board into HOST mode before we 642 * We need to put the board into HOST mode before we
745 * can send any volume-changing HOST commands ... 643 * can send any volume-changing HOST commands ...
@@ -752,15 +650,16 @@ static int sscape_midi_put(struct snd_kcontrol *kctl,
752 * and then perform another volume-related command. Perhaps the 650 * and then perform another volume-related command. Perhaps the
753 * first command is an "open" and the second command is a "close"? 651 * first command is an "open" and the second command is a "close"?
754 */ 652 */
755 if (s->midi_vol == ((unsigned char) uctl->value.integer. value[0] & 127)) { 653 if (s->midi_vol == new_val) {
756 change = 0; 654 change = 0;
757 goto __skip_change; 655 goto __skip_change;
758 } 656 }
759 change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) 657 change = host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
760 && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) 658 && host_write_ctrl_unsafe(s->io_base, new_val, 100)
761 && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); 659 && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)
762 s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127; 660 && host_write_ctrl_unsafe(s->io_base, new_val, 100);
763 __skip_change: 661 s->midi_vol = new_val;
662__skip_change:
764 663
765 /* 664 /*
766 * Take the board out of HOST mode and back into MIDI mode ... 665 * Take the board out of HOST mode and back into MIDI mode ...
@@ -784,20 +683,25 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
784 * These IRQs are encoded as bit patterns so that they can be 683 * These IRQs are encoded as bit patterns so that they can be
785 * written to the control registers. 684 * written to the control registers.
786 */ 685 */
787static unsigned __devinit get_irq_config(int irq) 686static unsigned __devinit get_irq_config(int sscape_type, int irq)
788{ 687{
789 static const int valid_irq[] = { 9, 5, 7, 10 }; 688 static const int valid_irq[] = { 9, 5, 7, 10 };
689 static const int old_irq[] = { 9, 7, 5, 15 };
790 unsigned cfg; 690 unsigned cfg;
791 691
792 for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) { 692 if (sscape_type == MEDIA_FX) {
793 if (irq == valid_irq[cfg]) 693 for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg)
794 return cfg; 694 if (irq == old_irq[cfg])
795 } /* for */ 695 return cfg;
696 } else {
697 for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg)
698 if (irq == valid_irq[cfg])
699 return cfg;
700 }
796 701
797 return INVALID_IRQ; 702 return INVALID_IRQ;
798} 703}
799 704
800
801/* 705/*
802 * Perform certain arcane port-checks to see whether there 706 * Perform certain arcane port-checks to see whether there
803 * is a SoundScape board lurking behind the given ports. 707 * is a SoundScape board lurking behind the given ports.
@@ -842,11 +746,38 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
842 if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) 746 if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
843 goto _done; 747 goto _done;
844 748
845 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; 749 if (s->ic_type == IC_OPUS)
846 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); 750 activate_ad1845_unsafe(s->io_base);
847 751
848 if (s->type == SSCAPE_VIVO) 752 if (s->type == SSCAPE_VIVO)
849 wss_io += 4; 753 wss_io += 4;
754
755 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
756 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
757
758 /* wait for WSS codec */
759 for (d = 0; d < 500; d++) {
760 if ((inb(wss_io) & 0x80) == 0)
761 break;
762 spin_unlock_irqrestore(&s->lock, flags);
763 msleep(1);
764 spin_lock_irqsave(&s->lock, flags);
765 }
766
767 if ((inb(wss_io) & 0x80) != 0)
768 goto _done;
769
770 if (inb(wss_io + 2) == 0xff)
771 goto _done;
772
773 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
774 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d);
775
776 if ((inb(wss_io) & 0x80) != 0)
777 s->type = MEDIA_FX;
778
779 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
780 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
850 /* wait for WSS codec */ 781 /* wait for WSS codec */
851 for (d = 0; d < 500; d++) { 782 for (d = 0; d < 500; d++) {
852 if ((inb(wss_io) & 0x80) == 0) 783 if ((inb(wss_io) & 0x80) == 0)
@@ -855,14 +786,13 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
855 msleep(1); 786 msleep(1);
856 spin_lock_irqsave(&s->lock, flags); 787 spin_lock_irqsave(&s->lock, flags);
857 } 788 }
858 snd_printd(KERN_INFO "init delay = %d ms\n", d);
859 789
860 /* 790 /*
861 * SoundScape successfully detected! 791 * SoundScape successfully detected!
862 */ 792 */
863 retval = 1; 793 retval = 1;
864 794
865 _done: 795_done:
866 spin_unlock_irqrestore(&s->lock, flags); 796 spin_unlock_irqrestore(&s->lock, flags);
867 return retval; 797 return retval;
868} 798}
@@ -873,63 +803,35 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
873 * to crash the machine. Also check that someone isn't using the hardware 803 * to crash the machine. Also check that someone isn't using the hardware
874 * IOCTL device. 804 * IOCTL device.
875 */ 805 */
876static int mpu401_open(struct snd_mpu401 * mpu) 806static int mpu401_open(struct snd_mpu401 *mpu)
877{ 807{
878 int err;
879
880 if (!verify_mpu401(mpu)) { 808 if (!verify_mpu401(mpu)) {
881 snd_printk(KERN_ERR "sscape: MIDI disabled, please load firmware\n"); 809 snd_printk(KERN_ERR "sscape: MIDI disabled, "
882 err = -ENODEV; 810 "please load firmware\n");
883 } else { 811 return -ENODEV;
884 register struct soundscape *sscape = get_mpu401_soundscape(mpu);
885 unsigned long flags;
886
887 spin_lock_irqsave(&sscape->fwlock, flags);
888
889 if (sscape->hw_in_use || (sscape->midi_usage == ULONG_MAX)) {
890 err = -EBUSY;
891 } else {
892 ++(sscape->midi_usage);
893 err = 0;
894 }
895
896 spin_unlock_irqrestore(&sscape->fwlock, flags);
897 } 812 }
898 813
899 return err; 814 return 0;
900}
901
902static void mpu401_close(struct snd_mpu401 * mpu)
903{
904 register struct soundscape *sscape = get_mpu401_soundscape(mpu);
905 unsigned long flags;
906
907 spin_lock_irqsave(&sscape->fwlock, flags);
908 --(sscape->midi_usage);
909 spin_unlock_irqrestore(&sscape->fwlock, flags);
910} 815}
911 816
912/* 817/*
913 * Initialse an MPU-401 subdevice for MIDI support on the SoundScape. 818 * Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
914 */ 819 */
915static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned long port, int irq) 820static int __devinit create_mpu401(struct snd_card *card, int devnum,
821 unsigned long port, int irq)
916{ 822{
917 struct soundscape *sscape = get_card_soundscape(card); 823 struct soundscape *sscape = get_card_soundscape(card);
918 struct snd_rawmidi *rawmidi; 824 struct snd_rawmidi *rawmidi;
919 int err; 825 int err;
920 826
921 if ((err = snd_mpu401_uart_new(card, devnum, 827 err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port,
922 MPU401_HW_MPU401, 828 MPU401_INFO_INTEGRATED, irq, IRQF_DISABLED,
923 port, MPU401_INFO_INTEGRATED, 829 &rawmidi);
924 irq, IRQF_DISABLED, 830 if (err == 0) {
925 &rawmidi)) == 0) { 831 struct snd_mpu401 *mpu = rawmidi->private_data;
926 struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data;
927 mpu->open_input = mpu401_open; 832 mpu->open_input = mpu401_open;
928 mpu->open_output = mpu401_open; 833 mpu->open_output = mpu401_open;
929 mpu->close_input = mpu401_close;
930 mpu->close_output = mpu401_close;
931 mpu->private_data = sscape; 834 mpu->private_data = sscape;
932 sscape->mpu = mpu;
933 835
934 initialise_mpu401(mpu); 836 initialise_mpu401(mpu);
935 } 837 }
@@ -950,32 +852,34 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
950 register struct soundscape *sscape = get_card_soundscape(card); 852 register struct soundscape *sscape = get_card_soundscape(card);
951 struct snd_wss *chip; 853 struct snd_wss *chip;
952 int err; 854 int err;
855 int codec_type = WSS_HW_DETECT;
953 856
954 if (sscape->type == SSCAPE_VIVO) 857 switch (sscape->type) {
955 port += 4; 858 case MEDIA_FX:
859 case SSCAPE:
860 /*
861 * There are some freak examples of early Soundscape cards
862 * with CS4231 instead of AD1848/CS4248. Unfortunately, the
863 * CS4231 works only in CS4248 compatibility mode on
864 * these cards so force it.
865 */
866 if (sscape->ic_type != IC_OPUS)
867 codec_type = WSS_HW_AD1848;
868 break;
956 869
957 if (dma1 == dma2) 870 case SSCAPE_VIVO:
958 dma2 = -1; 871 port += 4;
872 break;
873 default:
874 break;
875 }
959 876
960 err = snd_wss_create(card, port, -1, irq, dma1, dma2, 877 err = snd_wss_create(card, port, -1, irq, dma1, dma2,
961 WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip); 878 codec_type, WSS_HWSHARE_DMA1, &chip);
962 if (!err) { 879 if (!err) {
963 unsigned long flags; 880 unsigned long flags;
964 struct snd_pcm *pcm; 881 struct snd_pcm *pcm;
965 882
966/*
967 * It turns out that the PLAYBACK_ENABLE bit is set
968 * by the lowlevel driver ...
969 *
970#define AD1845_IFACE_CONFIG \
971 (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
972 snd_wss_mce_up(chip);
973 spin_lock_irqsave(&chip->reg_lock, flags);
974 snd_wss_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
975 spin_unlock_irqrestore(&chip->reg_lock, flags);
976 snd_wss_mce_down(chip);
977 */
978
979 if (sscape->type != SSCAPE_VIVO) { 883 if (sscape->type != SSCAPE_VIVO) {
980 /* 884 /*
981 * The input clock frequency on the SoundScape must 885 * The input clock frequency on the SoundScape must
@@ -1022,17 +926,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1022 } 926 }
1023 } 927 }
1024 928
1025 strcpy(card->driver, "SoundScape");
1026 strcpy(card->shortname, pcm->name);
1027 snprintf(card->longname, sizeof(card->longname),
1028 "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
1029 pcm->name, chip->port, chip->irq,
1030 chip->dma1, chip->dma2);
1031
1032 sscape->chip = chip; 929 sscape->chip = chip;
1033 } 930 }
1034 931
1035 _error: 932_error:
1036 return err; 933 return err;
1037} 934}
1038 935
@@ -1051,21 +948,8 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1051 struct resource *wss_res; 948 struct resource *wss_res;
1052 unsigned long flags; 949 unsigned long flags;
1053 int err; 950 int err;
1054 951 int val;
1055 /* 952 const char *name;
1056 * Check that the user didn't pass us garbage data ...
1057 */
1058 irq_cfg = get_irq_config(irq[dev]);
1059 if (irq_cfg == INVALID_IRQ) {
1060 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
1061 return -ENXIO;
1062 }
1063
1064 mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
1065 if (mpu_irq_cfg == INVALID_IRQ) {
1066 printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
1067 return -ENXIO;
1068 }
1069 953
1070 /* 954 /*
1071 * Grab IO ports that we will need to probe so that we 955 * Grab IO ports that we will need to probe so that we
@@ -1098,41 +982,51 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1098 } 982 }
1099 983
1100 spin_lock_init(&sscape->lock); 984 spin_lock_init(&sscape->lock);
1101 spin_lock_init(&sscape->fwlock);
1102 sscape->io_res = io_res; 985 sscape->io_res = io_res;
1103 sscape->wss_res = wss_res; 986 sscape->wss_res = wss_res;
1104 sscape->io_base = port[dev]; 987 sscape->io_base = port[dev];
1105 988
1106 if (!detect_sscape(sscape, wss_port[dev])) { 989 if (!detect_sscape(sscape, wss_port[dev])) {
1107 printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); 990 printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
991 sscape->io_base);
1108 err = -ENODEV; 992 err = -ENODEV;
1109 goto _release_dma; 993 goto _release_dma;
1110 } 994 }
1111 995
1112 printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", 996 switch (sscape->type) {
1113 sscape->io_base, irq[dev], dma[dev]); 997 case MEDIA_FX:
998 name = "MediaFX/SoundFX";
999 break;
1000 case SSCAPE:
1001 name = "Soundscape";
1002 break;
1003 case SSCAPE_PNP:
1004 name = "Soundscape PnP";
1005 break;
1006 case SSCAPE_VIVO:
1007 name = "Soundscape VIVO";
1008 break;
1009 default:
1010 name = "unknown Soundscape";
1011 break;
1012 }
1114 1013
1115 if (sscape->type != SSCAPE_VIVO) { 1014 printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n",
1116 /* 1015 name, sscape->io_base, irq[dev], dma[dev]);
1117 * Now create the hardware-specific device so that we can 1016
1118 * load the microcode into the on-board processor. 1017 /*
1119 * We cannot use the MPU-401 MIDI system until this firmware 1018 * Check that the user didn't pass us garbage data ...
1120 * has been loaded into the card. 1019 */
1121 */ 1020 irq_cfg = get_irq_config(sscape->type, irq[dev]);
1122 err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw)); 1021 if (irq_cfg == INVALID_IRQ) {
1123 if (err < 0) { 1022 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
1124 printk(KERN_ERR "sscape: Failed to create " 1023 return -ENXIO;
1125 "firmware device\n"); 1024 }
1126 goto _release_dma; 1025
1127 } 1026 mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
1128 strlcpy(sscape->hw->name, "SoundScape M68K", 1027 if (mpu_irq_cfg == INVALID_IRQ) {
1129 sizeof(sscape->hw->name)); 1028 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
1130 sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; 1029 return -ENXIO;
1131 sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
1132 sscape->hw->ops.open = sscape_hw_open;
1133 sscape->hw->ops.release = sscape_hw_release;
1134 sscape->hw->ops.ioctl = sscape_hw_ioctl;
1135 sscape->hw->private_data = sscape;
1136 } 1030 }
1137 1031
1138 /* 1032 /*
@@ -1141,9 +1035,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1141 */ 1035 */
1142 spin_lock_irqsave(&sscape->lock, flags); 1036 spin_lock_irqsave(&sscape->lock, flags);
1143 1037
1144 activate_ad1845_unsafe(sscape->io_base);
1145
1146 sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
1147 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); 1038 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
1148 sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); 1039 sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
1149 1040
@@ -1151,15 +1042,23 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1151 * Enable and configure the DMA channels ... 1042 * Enable and configure the DMA channels ...
1152 */ 1043 */
1153 sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); 1044 sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
1154 dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40); 1045 dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70);
1155 sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); 1046 sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
1156 sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); 1047 sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
1157 1048
1158 sscape_write_unsafe(sscape->io_base, 1049 mpu_irq_cfg |= mpu_irq_cfg << 2;
1159 GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); 1050 val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7;
1051 if (joystick[dev])
1052 val |= 8;
1053 sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10);
1054 sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg);
1160 sscape_write_unsafe(sscape->io_base, 1055 sscape_write_unsafe(sscape->io_base,
1161 GA_CDCFG_REG, 0x09 | DMA_8BIT 1056 GA_CDCFG_REG, 0x09 | DMA_8BIT
1162 | (dma[dev] << 4) | (irq_cfg << 1)); 1057 | (dma[dev] << 4) | (irq_cfg << 1));
1058 /*
1059 * Enable the master IRQ ...
1060 */
1061 sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80);
1163 1062
1164 spin_unlock_irqrestore(&sscape->lock, flags); 1063 spin_unlock_irqrestore(&sscape->lock, flags);
1165 1064
@@ -1170,32 +1069,56 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1170 err = create_ad1845(card, wss_port[dev], irq[dev], 1069 err = create_ad1845(card, wss_port[dev], irq[dev],
1171 dma[dev], dma2[dev]); 1070 dma[dev], dma2[dev]);
1172 if (err < 0) { 1071 if (err < 0) {
1173 printk(KERN_ERR "sscape: No AD1845 device at 0x%lx, IRQ %d\n", 1072 snd_printk(KERN_ERR
1174 wss_port[dev], irq[dev]); 1073 "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
1074 wss_port[dev], irq[dev]);
1175 goto _release_dma; 1075 goto _release_dma;
1176 } 1076 }
1077 strcpy(card->driver, "SoundScape");
1078 strcpy(card->shortname, name);
1079 snprintf(card->longname, sizeof(card->longname),
1080 "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
1081 name, sscape->chip->port, sscape->chip->irq,
1082 sscape->chip->dma1, sscape->chip->dma2);
1083
1177#define MIDI_DEVNUM 0 1084#define MIDI_DEVNUM 0
1178 if (sscape->type != SSCAPE_VIVO) { 1085 if (sscape->type != SSCAPE_VIVO) {
1179 err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); 1086 err = sscape_upload_bootblock(card);
1180 if (err < 0) { 1087 if (err >= 0)
1181 printk(KERN_ERR "sscape: Failed to create " 1088 err = sscape_upload_microcode(card, err);
1182 "MPU-401 device at 0x%lx\n",
1183 port[dev]);
1184 goto _release_dma;
1185 }
1186 1089
1187 /* 1090 if (err == 0) {
1188 * Enable the master IRQ ... 1091 err = create_mpu401(card, MIDI_DEVNUM, port[dev],
1189 */ 1092 mpu_irq[dev]);
1190 sscape_write(sscape, GA_INTENA_REG, 0x80); 1093 if (err < 0) {
1094 snd_printk(KERN_ERR "sscape: Failed to create "
1095 "MPU-401 device at 0x%lx\n",
1096 port[dev]);
1097 goto _release_dma;
1098 }
1191 1099
1192 /* 1100 /*
1193 * Initialize mixer 1101 * Initialize mixer
1194 */ 1102 */
1195 sscape->midi_vol = 0; 1103 spin_lock_irqsave(&sscape->lock, flags);
1196 host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); 1104 sscape->midi_vol = 0;
1197 host_write_ctrl_unsafe(sscape->io_base, 0, 100); 1105 host_write_ctrl_unsafe(sscape->io_base,
1198 host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); 1106 CMD_SET_MIDI_VOL, 100);
1107 host_write_ctrl_unsafe(sscape->io_base,
1108 sscape->midi_vol, 100);
1109 host_write_ctrl_unsafe(sscape->io_base,
1110 CMD_XXX_MIDI_VOL, 100);
1111 host_write_ctrl_unsafe(sscape->io_base,
1112 sscape->midi_vol, 100);
1113 host_write_ctrl_unsafe(sscape->io_base,
1114 CMD_SET_EXTMIDI, 100);
1115 host_write_ctrl_unsafe(sscape->io_base,
1116 0, 100);
1117 host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100);
1118
1119 set_midi_mode_unsafe(sscape->io_base);
1120 spin_unlock_irqrestore(&sscape->lock, flags);
1121 }
1199 } 1122 }
1200 1123
1201 /* 1124 /*
@@ -1231,7 +1154,8 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
1231 mpu_irq[i] == SNDRV_AUTO_IRQ || 1154 mpu_irq[i] == SNDRV_AUTO_IRQ ||
1232 dma[i] == SNDRV_AUTO_DMA) { 1155 dma[i] == SNDRV_AUTO_DMA) {
1233 printk(KERN_INFO 1156 printk(KERN_INFO
1234 "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n"); 1157 "sscape: insufficient parameters, "
1158 "need IO, IRQ, MPU-IRQ and DMA\n");
1235 return 0; 1159 return 0;
1236 } 1160 }
1237 1161
@@ -1253,13 +1177,15 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
1253 sscape->type = SSCAPE; 1177 sscape->type = SSCAPE;
1254 1178
1255 dma[dev] &= 0x03; 1179 dma[dev] &= 0x03;
1180 snd_card_set_dev(card, pdev);
1181
1256 ret = create_sscape(dev, card); 1182 ret = create_sscape(dev, card);
1257 if (ret < 0) 1183 if (ret < 0)
1258 goto _release_card; 1184 goto _release_card;
1259 1185
1260 snd_card_set_dev(card, pdev); 1186 ret = snd_card_register(card);
1261 if ((ret = snd_card_register(card)) < 0) { 1187 if (ret < 0) {
1262 printk(KERN_ERR "sscape: Failed to register sound card\n"); 1188 snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
1263 goto _release_card; 1189 goto _release_card;
1264 } 1190 }
1265 dev_set_drvdata(pdev, card); 1191 dev_set_drvdata(pdev, card);
@@ -1311,36 +1237,20 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
1311 * Allow this function to fail *quietly* if all the ISA PnP 1237 * Allow this function to fail *quietly* if all the ISA PnP
1312 * devices were configured using module parameters instead. 1238 * devices were configured using module parameters instead.
1313 */ 1239 */
1314 if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS) 1240 idx = get_next_autoindex(idx);
1241 if (idx >= SNDRV_CARDS)
1315 return -ENOSPC; 1242 return -ENOSPC;
1316 1243
1317 /* 1244 /*
1318 * We have found a candidate ISA PnP card. Now we
1319 * have to check that it has the devices that we
1320 * expect it to have.
1321 *
1322 * We will NOT try and autoconfigure all of the resources
1323 * needed and then activate the card as we are assuming that
1324 * has already been done at boot-time using /proc/isapnp.
1325 * We shall simply try to give each active card the resources
1326 * that it wants. This is a sensible strategy for a modular
1327 * system where unused modules are unloaded regularly.
1328 *
1329 * This strategy is utterly useless if we compile the driver
1330 * into the kernel, of course.
1331 */
1332 // printk(KERN_INFO "sscape: %s\n", card->name);
1333
1334 /*
1335 * Check that we still have room for another sound card ... 1245 * Check that we still have room for another sound card ...
1336 */ 1246 */
1337 dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); 1247 dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
1338 if (! dev) 1248 if (!dev)
1339 return -ENODEV; 1249 return -ENODEV;
1340 1250
1341 if (!pnp_is_active(dev)) { 1251 if (!pnp_is_active(dev)) {
1342 if (pnp_activate_dev(dev) < 0) { 1252 if (pnp_activate_dev(dev) < 0) {
1343 printk(KERN_INFO "sscape: device is inactive\n"); 1253 snd_printk(KERN_INFO "sscape: device is inactive\n");
1344 return -EBUSY; 1254 return -EBUSY;
1345 } 1255 }
1346 } 1256 }
@@ -1378,14 +1288,15 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
1378 wss_port[idx] = pnp_port_start(dev, 1); 1288 wss_port[idx] = pnp_port_start(dev, 1);
1379 dma2[idx] = pnp_dma(dev, 1); 1289 dma2[idx] = pnp_dma(dev, 1);
1380 } 1290 }
1291 snd_card_set_dev(card, &pcard->card->dev);
1381 1292
1382 ret = create_sscape(idx, card); 1293 ret = create_sscape(idx, card);
1383 if (ret < 0) 1294 if (ret < 0)
1384 goto _release_card; 1295 goto _release_card;
1385 1296
1386 snd_card_set_dev(card, &pcard->card->dev); 1297 ret = snd_card_register(card);
1387 if ((ret = snd_card_register(card)) < 0) { 1298 if (ret < 0) {
1388 printk(KERN_ERR "sscape: Failed to register sound card\n"); 1299 snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
1389 goto _release_card; 1300 goto _release_card;
1390 } 1301 }
1391 1302
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 5d2ba1b749ab..5b9d6c18bc45 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1682,7 +1682,7 @@ static void snd_wss_resume(struct snd_wss *chip)
1682} 1682}
1683#endif /* CONFIG_PM */ 1683#endif /* CONFIG_PM */
1684 1684
1685int snd_wss_free(struct snd_wss *chip) 1685static int snd_wss_free(struct snd_wss *chip)
1686{ 1686{
1687 release_and_free_resource(chip->res_port); 1687 release_and_free_resource(chip->res_port);
1688 release_and_free_resource(chip->res_cport); 1688 release_and_free_resource(chip->res_cport);
@@ -1705,7 +1705,6 @@ int snd_wss_free(struct snd_wss *chip)
1705 kfree(chip); 1705 kfree(chip);
1706 return 0; 1706 return 0;
1707} 1707}
1708EXPORT_SYMBOL(snd_wss_free);
1709 1708
1710static int snd_wss_dev_free(struct snd_device *device) 1709static int snd_wss_dev_free(struct snd_device *device)
1711{ 1710{
@@ -2198,84 +2197,61 @@ EXPORT_SYMBOL(snd_wss_put_double);
2198static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); 2197static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2199static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); 2198static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2200static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); 2199static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2200static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
2201 2201
2202static struct snd_kcontrol_new snd_ad1848_controls[] = { 2202static struct snd_kcontrol_new snd_wss_controls[] = {
2203WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 2203WSS_DOUBLE("PCM Playback Switch", 0,
2204 7, 7, 1, 1), 2204 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2205WSS_DOUBLE_TLV("PCM Playback Volume", 0, 2205WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2206 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, 2206 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2207 db_scale_6bit), 2207 db_scale_6bit),
2208WSS_DOUBLE("Aux Playback Switch", 0, 2208WSS_DOUBLE("Aux Playback Switch", 0,
2209 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 2209 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2210WSS_DOUBLE_TLV("Aux Playback Volume", 0, 2210WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2211 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, 2211 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2212 db_scale_5bit_12db_max), 2212 db_scale_5bit_12db_max),
2213WSS_DOUBLE("Aux Playback Switch", 1, 2213WSS_DOUBLE("Aux Playback Switch", 1,
2214 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 2214 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2215WSS_DOUBLE_TLV("Aux Playback Volume", 1, 2215WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2216 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, 2216 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2217 db_scale_5bit_12db_max), 2217 db_scale_5bit_12db_max),
2218WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 2218WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2219 0, 0, 15, 0, db_scale_rec_gain), 2219 0, 0, 15, 0, db_scale_rec_gain),
2220{ 2220{
2221 .name = "Capture Source",
2222 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2222 .name = "Capture Source",
2223 .info = snd_wss_info_mux, 2223 .info = snd_wss_info_mux,
2224 .get = snd_wss_get_mux, 2224 .get = snd_wss_get_mux,
2225 .put = snd_wss_put_mux, 2225 .put = snd_wss_put_mux,
2226}, 2226},
2227WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), 2227WSS_DOUBLE("Mic Boost (+20dB)", 0,
2228WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0, 2228 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2229 db_scale_6bit), 2229WSS_SINGLE("Loopback Capture Switch", 0,
2230}; 2230 CS4231_LOOPBACK, 0, 1, 0),
2231 2231WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1,
2232static struct snd_kcontrol_new snd_wss_controls[] = { 2232 db_scale_6bit),
2233WSS_DOUBLE("PCM Playback Switch", 0,
2234 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2235WSS_DOUBLE("PCM Playback Volume", 0,
2236 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
2237WSS_DOUBLE("Line Playback Switch", 0, 2233WSS_DOUBLE("Line Playback Switch", 0,
2238 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 2234 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2239WSS_DOUBLE("Line Playback Volume", 0, 2235WSS_DOUBLE_TLV("Line Playback Volume", 0,
2240 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 2236 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
2241WSS_DOUBLE("Aux Playback Switch", 0, 2237 db_scale_5bit_12db_max),
2242 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 2238WSS_SINGLE("Beep Playback Switch", 0,
2243WSS_DOUBLE("Aux Playback Volume", 0,
2244 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
2245WSS_DOUBLE("Aux Playback Switch", 1,
2246 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2247WSS_DOUBLE("Aux Playback Volume", 1,
2248 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
2249WSS_SINGLE("Mono Playback Switch", 0,
2250 CS4231_MONO_CTRL, 7, 1, 1), 2239 CS4231_MONO_CTRL, 7, 1, 1),
2251WSS_SINGLE("Mono Playback Volume", 0, 2240WSS_SINGLE_TLV("Beep Playback Volume", 0,
2252 CS4231_MONO_CTRL, 0, 15, 1), 2241 CS4231_MONO_CTRL, 0, 15, 1,
2242 db_scale_4bit),
2253WSS_SINGLE("Mono Output Playback Switch", 0, 2243WSS_SINGLE("Mono Output Playback Switch", 0,
2254 CS4231_MONO_CTRL, 6, 1, 1), 2244 CS4231_MONO_CTRL, 6, 1, 1),
2255WSS_SINGLE("Mono Output Playback Bypass", 0, 2245WSS_SINGLE("Beep Bypass Playback Switch", 0,
2256 CS4231_MONO_CTRL, 5, 1, 0), 2246 CS4231_MONO_CTRL, 5, 1, 0),
2257WSS_DOUBLE("Capture Volume", 0,
2258 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2259{
2260 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2261 .name = "Capture Source",
2262 .info = snd_wss_info_mux,
2263 .get = snd_wss_get_mux,
2264 .put = snd_wss_put_mux,
2265},
2266WSS_DOUBLE("Mic Boost", 0,
2267 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2268WSS_SINGLE("Loopback Capture Switch", 0,
2269 CS4231_LOOPBACK, 0, 1, 0),
2270WSS_SINGLE("Loopback Capture Volume", 0,
2271 CS4231_LOOPBACK, 2, 63, 1)
2272}; 2247};
2273 2248
2274static struct snd_kcontrol_new snd_opti93x_controls[] = { 2249static struct snd_kcontrol_new snd_opti93x_controls[] = {
2275WSS_DOUBLE("Master Playback Switch", 0, 2250WSS_DOUBLE("Master Playback Switch", 0,
2276 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), 2251 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
2277WSS_DOUBLE("Master Playback Volume", 0, 2252WSS_DOUBLE_TLV("Master Playback Volume", 0,
2278 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 2253 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1,
2254 db_scale_6bit),
2279WSS_DOUBLE("PCM Playback Switch", 0, 2255WSS_DOUBLE("PCM Playback Switch", 0,
2280 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 2256 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2281WSS_DOUBLE("PCM Playback Volume", 0, 2257WSS_DOUBLE("PCM Playback Volume", 0,
@@ -2334,22 +2310,21 @@ int snd_wss_mixer(struct snd_wss *chip)
2334 if (err < 0) 2310 if (err < 0)
2335 return err; 2311 return err;
2336 } 2312 }
2337 else if (chip->hardware & WSS_HW_AD1848_MASK) 2313 else {
2338 for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { 2314 int count = ARRAY_SIZE(snd_wss_controls);
2339 err = snd_ctl_add(card, 2315
2340 snd_ctl_new1(&snd_ad1848_controls[idx], 2316 /* Use only the first 11 entries on AD1848 */
2341 chip)); 2317 if (chip->hardware & WSS_HW_AD1848_MASK)
2342 if (err < 0) 2318 count = 11;
2343 return err; 2319
2344 } 2320 for (idx = 0; idx < count; idx++) {
2345 else
2346 for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
2347 err = snd_ctl_add(card, 2321 err = snd_ctl_add(card,
2348 snd_ctl_new1(&snd_wss_controls[idx], 2322 snd_ctl_new1(&snd_wss_controls[idx],
2349 chip)); 2323 chip));
2350 if (err < 0) 2324 if (err < 0)
2351 return err; 2325 return err;
2352 } 2326 }
2327 }
2353 return 0; 2328 return 0;
2354} 2329}
2355EXPORT_SYMBOL(snd_wss_mixer); 2330EXPORT_SYMBOL(snd_wss_mixer);
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index bcf2a0698d54..135a2b77cc4a 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -287,18 +287,6 @@ config SOUND_DMAP
287 287
288 Say Y unless you have 16MB or more RAM or a PCI sound card. 288 Say Y unless you have 16MB or more RAM or a PCI sound card.
289 289
290config SOUND_SSCAPE
291 tristate "Ensoniq SoundScape support"
292 help
293 Answer Y if you have a sound card based on the Ensoniq SoundScape
294 chipset. Such cards are being manufactured at least by Ensoniq, Spea
295 and Reveal (Reveal makes also other cards).
296
297 If you compile the driver into the kernel, you have to add
298 "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
299 line.
300
301
302config SOUND_VMIDI 290config SOUND_VMIDI
303 tristate "Loopback MIDI device support" 291 tristate "Loopback MIDI device support"
304 help 292 help
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index e0ae4d4d6a5c..567b8a74178a 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o
13obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o 13obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o
14obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o 14obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
15obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o 15obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
16obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
17obj-$(CONFIG_SOUND_MSS) += ad1848.o 16obj-$(CONFIG_SOUND_MSS) += ad1848.o
18obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o 17obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o
19obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o 18obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o
diff --git a/sound/oss/audio.c b/sound/oss/audio.c
index b69c05b7ea7b..7df48a25c4ee 100644
--- a/sound/oss/audio.c
+++ b/sound/oss/audio.c
@@ -838,7 +838,7 @@ static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
838 if ((err = audio_devs[dev]->d->prepare_for_input(dev, 838 if ((err = audio_devs[dev]->d->prepare_for_input(dev,
839 dmap_in->fragment_size, dmap_in->nbufs)) < 0) { 839 dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
840 spin_unlock_irqrestore(&dmap_in->lock,flags); 840 spin_unlock_irqrestore(&dmap_in->lock,flags);
841 return -err; 841 return err;
842 } 842 }
843 dmap_in->dma_mode = DMODE_INPUT; 843 dmap_in->dma_mode = DMODE_INPUT;
844 audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT; 844 audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT;
diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c
index 9e450988ed36..3bc7104c5379 100644
--- a/sound/oss/midi_synth.c
+++ b/sound/oss/midi_synth.c
@@ -426,7 +426,7 @@ midi_synth_open(int dev, int mode)
426 int err; 426 int err;
427 struct midi_input_info *inc; 427 struct midi_input_info *inc;
428 428
429 if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL) 429 if (orig_dev < 0 || orig_dev >= num_midis || midi_devs[orig_dev] == NULL)
430 return -ENXIO; 430 return -ENXIO;
431 431
432 midi2synth[orig_dev] = dev; 432 midi2synth[orig_dev] = dev;
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 734b8f9e2f78..0af9d24feb8f 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -770,7 +770,7 @@ static int mpu_synth_ioctl(int dev, unsigned int cmd, void __user *arg)
770 770
771 midi_dev = synth_devs[dev]->midi_dev; 771 midi_dev = synth_devs[dev]->midi_dev;
772 772
773 if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) 773 if (midi_dev < 0 || midi_dev >= num_midis || midi_devs[midi_dev] == NULL)
774 return -ENXIO; 774 return -ENXIO;
775 775
776 devc = &dev_conf[midi_dev]; 776 devc = &dev_conf[midi_dev];
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index b2ed8757542a..4153752507e3 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -164,9 +164,6 @@ static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
164 int free; 164 int free;
165 int nbytes; 165 int nbytes;
166 166
167 if (count < 0)
168 return -EINVAL;
169
170 if (!count) { 167 if (!count) {
171 dac_audio_sync(); 168 dac_audio_sync();
172 return 0; 169 return 0;
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
deleted file mode 100644
index 30c36d1f35d7..000000000000
--- a/sound/oss/sscape.c
+++ /dev/null
@@ -1,1480 +0,0 @@
1/*
2 * sound/oss/sscape.c
3 *
4 * Low level driver for Ensoniq SoundScape
5 *
6 *
7 * Copyright (C) by Hannu Savolainen 1993-1997
8 *
9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
11 * for more info.
12 *
13 *
14 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
15 * Sergey Smitienko : ensoniq p'n'p support
16 * Christoph Hellwig : adapted to module_init/module_exit
17 * Bartlomiej Zolnierkiewicz : added __init to attach_sscape()
18 * Chris Rankin : Specify that this module owns the coprocessor
19 * Arnaldo C. de Melo : added missing restore_flags in sscape_pnp_upload_file
20 */
21
22#include <linux/init.h>
23#include <linux/module.h>
24
25#include "sound_config.h"
26#include "sound_firmware.h"
27
28#include <linux/types.h>
29#include <linux/errno.h>
30#include <linux/signal.h>
31#include <linux/fcntl.h>
32#include <linux/ctype.h>
33#include <linux/stddef.h>
34#include <linux/kmod.h>
35#include <asm/dma.h>
36#include <asm/io.h>
37#include <linux/wait.h>
38#include <linux/slab.h>
39#include <linux/ioport.h>
40#include <linux/delay.h>
41#include <linux/proc_fs.h>
42#include <linux/mm.h>
43#include <linux/spinlock.h>
44
45#include "coproc.h"
46
47#include "ad1848.h"
48#include "mpu401.h"
49
50/*
51 * I/O ports
52 */
53#define MIDI_DATA 0
54#define MIDI_CTRL 1
55#define HOST_CTRL 2
56#define TX_READY 0x02
57#define RX_READY 0x01
58#define HOST_DATA 3
59#define ODIE_ADDR 4
60#define ODIE_DATA 5
61
62/*
63 * Indirect registers
64 */
65
66#define GA_INTSTAT_REG 0
67#define GA_INTENA_REG 1
68#define GA_DMAA_REG 2
69#define GA_DMAB_REG 3
70#define GA_INTCFG_REG 4
71#define GA_DMACFG_REG 5
72#define GA_CDCFG_REG 6
73#define GA_SMCFGA_REG 7
74#define GA_SMCFGB_REG 8
75#define GA_HMCTL_REG 9
76
77/*
78 * DMA channel identifiers (A and B)
79 */
80
81#define SSCAPE_DMA_A 0
82#define SSCAPE_DMA_B 1
83
84#define PORT(name) (devc->base+name)
85
86/*
87 * Host commands recognized by the OBP microcode
88 */
89
90#define CMD_GEN_HOST_ACK 0x80
91#define CMD_GEN_MPU_ACK 0x81
92#define CMD_GET_BOARD_TYPE 0x82
93#define CMD_SET_CONTROL 0x88 /* Old firmware only */
94#define CMD_GET_CONTROL 0x89 /* Old firmware only */
95#define CTL_MASTER_VOL 0
96#define CTL_MIC_MODE 2
97#define CTL_SYNTH_VOL 4
98#define CTL_WAVE_VOL 7
99#define CMD_SET_EXTMIDI 0x8a
100#define CMD_GET_EXTMIDI 0x8b
101#define CMD_SET_MT32 0x8c
102#define CMD_GET_MT32 0x8d
103
104#define CMD_ACK 0x80
105
106#define IC_ODIE 1
107#define IC_OPUS 2
108
109typedef struct sscape_info
110{
111 int base, irq, dma;
112
113 int codec, codec_irq; /* required to setup pnp cards*/
114 int codec_type;
115 int ic_type;
116 char* raw_buf;
117 unsigned long raw_buf_phys;
118 int buffsize; /* -------------------------- */
119 spinlock_t lock;
120 int ok; /* Properly detected */
121 int failed;
122 int dma_allocated;
123 int codec_audiodev;
124 int opened;
125 int *osp;
126 int my_audiodev;
127} sscape_info;
128
129static struct sscape_info adev_info = {
130 0
131};
132
133static struct sscape_info *devc = &adev_info;
134static int sscape_mididev = -1;
135
136/* Some older cards have assigned interrupt bits differently than new ones */
137static char valid_interrupts_old[] = {
138 9, 7, 5, 15
139};
140
141static char valid_interrupts_new[] = {
142 9, 5, 7, 10
143};
144
145static char *valid_interrupts = valid_interrupts_new;
146
147/*
148 * See the bottom of the driver. This can be set by spea =0/1.
149 */
150
151#ifdef REVEAL_SPEA
152static char old_hardware = 1;
153#else
154static char old_hardware;
155#endif
156
157static void sleep(unsigned howlong)
158{
159 current->state = TASK_INTERRUPTIBLE;
160 schedule_timeout(howlong);
161}
162
163static unsigned char sscape_read(struct sscape_info *devc, int reg)
164{
165 unsigned long flags;
166 unsigned char val;
167
168 spin_lock_irqsave(&devc->lock,flags);
169 outb(reg, PORT(ODIE_ADDR));
170 val = inb(PORT(ODIE_DATA));
171 spin_unlock_irqrestore(&devc->lock,flags);
172 return val;
173}
174
175static void __sscape_write(int reg, int data)
176{
177 outb(reg, PORT(ODIE_ADDR));
178 outb(data, PORT(ODIE_DATA));
179}
180
181static void sscape_write(struct sscape_info *devc, int reg, int data)
182{
183 unsigned long flags;
184
185 spin_lock_irqsave(&devc->lock,flags);
186 __sscape_write(reg, data);
187 spin_unlock_irqrestore(&devc->lock,flags);
188}
189
190static unsigned char sscape_pnp_read_codec(sscape_info* devc, unsigned char reg)
191{
192 unsigned char res;
193 unsigned long flags;
194
195 spin_lock_irqsave(&devc->lock,flags);
196 outb( reg, devc -> codec);
197 res = inb (devc -> codec + 1);
198 spin_unlock_irqrestore(&devc->lock,flags);
199 return res;
200
201}
202
203static void sscape_pnp_write_codec(sscape_info* devc, unsigned char reg, unsigned char data)
204{
205 unsigned long flags;
206
207 spin_lock_irqsave(&devc->lock,flags);
208 outb( reg, devc -> codec);
209 outb( data, devc -> codec + 1);
210 spin_unlock_irqrestore(&devc->lock,flags);
211}
212
213static void host_open(struct sscape_info *devc)
214{
215 outb((0x00), PORT(HOST_CTRL)); /* Put the board to the host mode */
216}
217
218static void host_close(struct sscape_info *devc)
219{
220 outb((0x03), PORT(HOST_CTRL)); /* Put the board to the MIDI mode */
221}
222
223static int host_write(struct sscape_info *devc, unsigned char *data, int count)
224{
225 unsigned long flags;
226 int i, timeout_val;
227
228 spin_lock_irqsave(&devc->lock,flags);
229 /*
230 * Send the command and data bytes
231 */
232
233 for (i = 0; i < count; i++)
234 {
235 for (timeout_val = 10000; timeout_val > 0; timeout_val--)
236 if (inb(PORT(HOST_CTRL)) & TX_READY)
237 break;
238
239 if (timeout_val <= 0)
240 {
241 spin_unlock_irqrestore(&devc->lock,flags);
242 return 0;
243 }
244 outb(data[i], PORT(HOST_DATA));
245 }
246 spin_unlock_irqrestore(&devc->lock,flags);
247 return 1;
248}
249
250static int host_read(struct sscape_info *devc)
251{
252 unsigned long flags;
253 int timeout_val;
254 unsigned char data;
255
256 spin_lock_irqsave(&devc->lock,flags);
257 /*
258 * Read a byte
259 */
260
261 for (timeout_val = 10000; timeout_val > 0; timeout_val--)
262 if (inb(PORT(HOST_CTRL)) & RX_READY)
263 break;
264
265 if (timeout_val <= 0)
266 {
267 spin_unlock_irqrestore(&devc->lock,flags);
268 return -1;
269 }
270 data = inb(PORT(HOST_DATA));
271 spin_unlock_irqrestore(&devc->lock,flags);
272 return data;
273}
274
275#if 0 /* unused */
276static int host_command1(struct sscape_info *devc, int cmd)
277{
278 unsigned char buf[10];
279 buf[0] = (unsigned char) (cmd & 0xff);
280 return host_write(devc, buf, 1);
281}
282#endif /* unused */
283
284
285static int host_command2(struct sscape_info *devc, int cmd, int parm1)
286{
287 unsigned char buf[10];
288
289 buf[0] = (unsigned char) (cmd & 0xff);
290 buf[1] = (unsigned char) (parm1 & 0xff);
291
292 return host_write(devc, buf, 2);
293}
294
295static int host_command3(struct sscape_info *devc, int cmd, int parm1, int parm2)
296{
297 unsigned char buf[10];
298
299 buf[0] = (unsigned char) (cmd & 0xff);
300 buf[1] = (unsigned char) (parm1 & 0xff);
301 buf[2] = (unsigned char) (parm2 & 0xff);
302 return host_write(devc, buf, 3);
303}
304
305static void set_mt32(struct sscape_info *devc, int value)
306{
307 host_open(devc);
308 host_command2(devc, CMD_SET_MT32, value ? 1 : 0);
309 if (host_read(devc) != CMD_ACK)
310 {
311 /* printk( "SNDSCAPE: Setting MT32 mode failed\n"); */
312 }
313 host_close(devc);
314}
315
316static void set_control(struct sscape_info *devc, int ctrl, int value)
317{
318 host_open(devc);
319 host_command3(devc, CMD_SET_CONTROL, ctrl, value);
320 if (host_read(devc) != CMD_ACK)
321 {
322 /* printk( "SNDSCAPE: Setting control (%d) failed\n", ctrl); */
323 }
324 host_close(devc);
325}
326
327static void do_dma(struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
328{
329 unsigned char temp;
330
331 if (dma_chan != SSCAPE_DMA_A)
332 {
333 printk(KERN_WARNING "soundscape: Tried to use DMA channel != A. Why?\n");
334 return;
335 }
336 audio_devs[devc->codec_audiodev]->flags &= ~DMA_AUTOMODE;
337 DMAbuf_start_dma(devc->codec_audiodev, buf, blk_size, mode);
338 audio_devs[devc->codec_audiodev]->flags |= DMA_AUTOMODE;
339
340 temp = devc->dma << 4; /* Setup DMA channel select bits */
341 if (devc->dma <= 3)
342 temp |= 0x80; /* 8 bit DMA channel */
343
344 temp |= 1; /* Trigger DMA */
345 sscape_write(devc, GA_DMAA_REG, temp);
346 temp &= 0xfe; /* Clear DMA trigger */
347 sscape_write(devc, GA_DMAA_REG, temp);
348}
349
350static int verify_mpu(struct sscape_info *devc)
351{
352 /*
353 * The SoundScape board could be in three modes (MPU, 8250 and host).
354 * If the card is not in the MPU mode, enabling the MPU driver will
355 * cause infinite loop (the driver believes that there is always some
356 * received data in the buffer.
357 *
358 * Detect this by looking if there are more than 10 received MIDI bytes
359 * (0x00) in the buffer.
360 */
361
362 int i;
363
364 for (i = 0; i < 10; i++)
365 {
366 if (inb(devc->base + HOST_CTRL) & 0x80)
367 return 1;
368
369 if (inb(devc->base) != 0x00)
370 return 1;
371 }
372 printk(KERN_WARNING "SoundScape: The device is not in the MPU-401 mode\n");
373 return 0;
374}
375
376static int sscape_coproc_open(void *dev_info, int sub_device)
377{
378 if (sub_device == COPR_MIDI)
379 {
380 set_mt32(devc, 0);
381 if (!verify_mpu(devc))
382 return -EIO;
383 }
384 return 0;
385}
386
387static void sscape_coproc_close(void *dev_info, int sub_device)
388{
389 struct sscape_info *devc = dev_info;
390 unsigned long flags;
391
392 spin_lock_irqsave(&devc->lock,flags);
393 if (devc->dma_allocated)
394 {
395 __sscape_write(GA_DMAA_REG, 0x20); /* DMA channel disabled */
396 devc->dma_allocated = 0;
397 }
398 spin_unlock_irqrestore(&devc->lock,flags);
399 return;
400}
401
402static void sscape_coproc_reset(void *dev_info)
403{
404}
405
406static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag)
407{
408 unsigned long flags;
409 unsigned char temp;
410 volatile int done, timeout_val;
411 static unsigned char codec_dma_bits;
412
413 if (flag & CPF_FIRST)
414 {
415 /*
416 * First block. Have to allocate DMA and to reset the board
417 * before continuing.
418 */
419
420 spin_lock_irqsave(&devc->lock,flags);
421 codec_dma_bits = sscape_read(devc, GA_CDCFG_REG);
422
423 if (devc->dma_allocated == 0)
424 devc->dma_allocated = 1;
425
426 spin_unlock_irqrestore(&devc->lock,flags);
427
428 sscape_write(devc, GA_HMCTL_REG,
429 (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /*Reset */
430
431 for (timeout_val = 10000; timeout_val > 0; timeout_val--)
432 sscape_read(devc, GA_HMCTL_REG); /* Delay */
433
434 /* Take board out of reset */
435 sscape_write(devc, GA_HMCTL_REG,
436 (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
437 }
438 /*
439 * Transfer one code block using DMA
440 */
441 if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL)
442 {
443 printk(KERN_WARNING "soundscape: DMA buffer not available\n");
444 return 0;
445 }
446 memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size);
447
448 spin_lock_irqsave(&devc->lock,flags);
449
450 /******** INTERRUPTS DISABLED NOW ********/
451
452 do_dma(devc, SSCAPE_DMA_A,
453 audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys,
454 size, DMA_MODE_WRITE);
455
456 /*
457 * Wait until transfer completes.
458 */
459
460 done = 0;
461 timeout_val = 30;
462 while (!done && timeout_val-- > 0)
463 {
464 int resid;
465
466 if (HZ / 50)
467 sleep(HZ / 50);
468 clear_dma_ff(devc->dma);
469 if ((resid = get_dma_residue(devc->dma)) == 0)
470 done = 1;
471 }
472
473 spin_unlock_irqrestore(&devc->lock,flags);
474 if (!done)
475 return 0;
476
477 if (flag & CPF_LAST)
478 {
479 /*
480 * Take the board out of reset
481 */
482 outb((0x00), PORT(HOST_CTRL));
483 outb((0x00), PORT(MIDI_CTRL));
484
485 temp = sscape_read(devc, GA_HMCTL_REG);
486 temp |= 0x40;
487 sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */
488
489 /*
490 * Wait until the ODB wakes up
491 */
492 spin_lock_irqsave(&devc->lock,flags);
493 done = 0;
494 timeout_val = 5 * HZ;
495 while (!done && timeout_val-- > 0)
496 {
497 unsigned char x;
498
499 sleep(1);
500 x = inb(PORT(HOST_DATA));
501 if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */
502 {
503 DDB(printk("Soundscape: Acknowledge = %x\n", x));
504 done = 1;
505 }
506 }
507 sscape_write(devc, GA_CDCFG_REG, codec_dma_bits);
508
509 spin_unlock_irqrestore(&devc->lock,flags);
510 if (!done)
511 {
512 printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n");
513 return 0;
514 }
515 spin_lock_irqsave(&devc->lock,flags);
516 done = 0;
517 timeout_val = 5 * HZ;
518 while (!done && timeout_val-- > 0)
519 {
520 sleep(1);
521 if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */
522 done = 1;
523 }
524 spin_unlock_irqrestore(&devc->lock,flags);
525 if (!done)
526 {
527 printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
528 return 0;
529 }
530 printk(KERN_INFO "SoundScape board initialized OK\n");
531 set_control(devc, CTL_MASTER_VOL, 100);
532 set_control(devc, CTL_SYNTH_VOL, 100);
533
534#ifdef SSCAPE_DEBUG3
535 /*
536 * Temporary debugging aid. Print contents of the registers after
537 * downloading the code.
538 */
539 {
540 int i;
541
542 for (i = 0; i < 13; i++)
543 printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
544 }
545#endif
546
547 }
548 return 1;
549}
550
551static int download_boot_block(void *dev_info, copr_buffer * buf)
552{
553 if (buf->len <= 0 || buf->len > sizeof(buf->data))
554 return -EINVAL;
555
556 if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags))
557 {
558 printk(KERN_ERR "soundscape: Unable to load microcode block to the OBP.\n");
559 return -EIO;
560 }
561 return 0;
562}
563
564static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local)
565{
566 copr_buffer *buf;
567 int err;
568
569 switch (cmd)
570 {
571 case SNDCTL_COPR_RESET:
572 sscape_coproc_reset(dev_info);
573 return 0;
574
575 case SNDCTL_COPR_LOAD:
576 buf = (copr_buffer *) vmalloc(sizeof(copr_buffer));
577 if (buf == NULL)
578 return -ENOSPC;
579 if (copy_from_user(buf, arg, sizeof(copr_buffer)))
580 {
581 vfree(buf);
582 return -EFAULT;
583 }
584 err = download_boot_block(dev_info, buf);
585 vfree(buf);
586 return err;
587
588 default:
589 return -EINVAL;
590 }
591}
592
593static coproc_operations sscape_coproc_operations =
594{
595 "SoundScape M68K",
596 THIS_MODULE,
597 sscape_coproc_open,
598 sscape_coproc_close,
599 sscape_coproc_ioctl,
600 sscape_coproc_reset,
601 &adev_info
602};
603
604static struct resource *sscape_ports;
605static int sscape_is_pnp;
606
607static void __init attach_sscape(struct address_info *hw_config)
608{
609#ifndef SSCAPE_REGS
610 /*
611 * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
612 * These values are card
613 * dependent. If you have another SoundScape based card, you have to
614 * find the correct values. Do the following:
615 * - Compile this driver with SSCAPE_DEBUG1 defined.
616 * - Shut down and power off your machine.
617 * - Boot with DOS so that the SSINIT.EXE program is run.
618 * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
619 * when detecting the SoundScape.
620 * - Modify the following list to use the values printed during boot.
621 * Undefine the SSCAPE_DEBUG1
622 */
623#define SSCAPE_REGS { \
624/* I0 */ 0x00, \
625/* I1 */ 0xf0, /* Note! Ignored. Set always to 0xf0 */ \
626/* I2 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \
627/* I3 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \
628/* I4 */ 0xf5, /* Ignored */ \
629/* I5 */ 0x10, \
630/* I6 */ 0x00, \
631/* I7 */ 0x2e, /* I7 MEM config A. Likely to vary between models */ \
632/* I8 */ 0x00, /* I8 MEM config B. Likely to vary between models */ \
633/* I9 */ 0x40 /* Ignored */ \
634 }
635#endif
636
637 unsigned long flags;
638 static unsigned char regs[10] = SSCAPE_REGS;
639
640 int i, irq_bits = 0xff;
641
642 if (old_hardware)
643 {
644 valid_interrupts = valid_interrupts_old;
645 conf_printf("Ensoniq SoundScape (old)", hw_config);
646 }
647 else
648 conf_printf("Ensoniq SoundScape", hw_config);
649
650 for (i = 0; i < 4; i++)
651 {
652 if (hw_config->irq == valid_interrupts[i])
653 {
654 irq_bits = i;
655 break;
656 }
657 }
658 if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
659 {
660 printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
661 release_region(devc->base, 2);
662 release_region(devc->base + 2, 6);
663 if (sscape_is_pnp)
664 release_region(devc->codec, 2);
665 return;
666 }
667
668 if (!sscape_is_pnp) {
669
670 spin_lock_irqsave(&devc->lock,flags);
671 /* Host interrupt enable */
672 sscape_write(devc, 1, 0xf0); /* All interrupts enabled */
673 /* DMA A status/trigger register */
674 sscape_write(devc, 2, 0x20); /* DMA channel disabled */
675 /* DMA B status/trigger register */
676 sscape_write(devc, 3, 0x20); /* DMA channel disabled */
677 /* Host interrupt config reg */
678 sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits);
679 /* Don't destroy CD-ROM DMA config bits (0xc0) */
680 sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0));
681 /* CD-ROM config (WSS codec actually) */
682 sscape_write(devc, 6, regs[6]);
683 sscape_write(devc, 7, regs[7]);
684 sscape_write(devc, 8, regs[8]);
685 /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
686 sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08);
687 spin_unlock_irqrestore(&devc->lock,flags);
688 }
689#ifdef SSCAPE_DEBUG2
690 /*
691 * Temporary debugging aid. Print contents of the registers after
692 * changing them.
693 */
694 {
695 int i;
696
697 for (i = 0; i < 13; i++)
698 printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
699 }
700#endif
701
702 if (probe_mpu401(hw_config, sscape_ports))
703 hw_config->always_detect = 1;
704 hw_config->name = "SoundScape";
705
706 hw_config->irq *= -1; /* Negative value signals IRQ sharing */
707 attach_mpu401(hw_config, THIS_MODULE);
708 hw_config->irq *= -1; /* Restore it */
709
710 if (hw_config->slots[1] != -1) /* The MPU driver installed itself */
711 {
712 sscape_mididev = hw_config->slots[1];
713 midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations;
714 }
715 sscape_write(devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */
716 devc->ok = 1;
717 devc->failed = 0;
718}
719
720static int detect_ga(sscape_info * devc)
721{
722 unsigned char save;
723
724 DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base));
725
726 /*
727 * First check that the address register of "ODIE" is
728 * there and that it has exactly 4 writable bits.
729 * First 4 bits
730 */
731
732 if ((save = inb(PORT(ODIE_ADDR))) & 0xf0)
733 {
734 DDB(printk("soundscape: Detect error A\n"));
735 return 0;
736 }
737 outb((0x00), PORT(ODIE_ADDR));
738 if (inb(PORT(ODIE_ADDR)) != 0x00)
739 {
740 DDB(printk("soundscape: Detect error B\n"));
741 return 0;
742 }
743 outb((0xff), PORT(ODIE_ADDR));
744 if (inb(PORT(ODIE_ADDR)) != 0x0f)
745 {
746 DDB(printk("soundscape: Detect error C\n"));
747 return 0;
748 }
749 outb((save), PORT(ODIE_ADDR));
750
751 /*
752 * Now verify that some indirect registers return zero on some bits.
753 * This may break the driver with some future revisions of "ODIE" but...
754 */
755
756 if (sscape_read(devc, 0) & 0x0c)
757 {
758 DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0)));
759 return 0;
760 }
761 if (sscape_read(devc, 1) & 0x0f)
762 {
763 DDB(printk("soundscape: Detect error E\n"));
764 return 0;
765 }
766 if (sscape_read(devc, 5) & 0x0f)
767 {
768 DDB(printk("soundscape: Detect error F\n"));
769 return 0;
770 }
771 return 1;
772}
773
774static int sscape_read_host_ctrl(sscape_info* devc)
775{
776 return host_read(devc);
777}
778
779static void sscape_write_host_ctrl2(sscape_info *devc, int a, int b)
780{
781 host_command2(devc, a, b);
782}
783
784static int sscape_alloc_dma(sscape_info *devc)
785{
786 char *start_addr, *end_addr;
787 int dma_pagesize;
788 int sz, size;
789 struct page *page;
790
791 if (devc->raw_buf != NULL) return 0; /* Already done */
792 dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024);
793 devc->raw_buf = NULL;
794 devc->buffsize = 8192*4;
795 if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize;
796 start_addr = NULL;
797 /*
798 * Now loop until we get a free buffer. Try to get smaller buffer if
799 * it fails. Don't accept smaller than 8k buffer for performance
800 * reasons.
801 */
802 while (start_addr == NULL && devc->buffsize > PAGE_SIZE) {
803 for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
804 devc->buffsize = PAGE_SIZE * (1 << sz);
805 start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz);
806 if (start_addr == NULL) devc->buffsize /= 2;
807 }
808
809 if (start_addr == NULL) {
810 printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n");
811 return 0;
812 } else {
813 /* make some checks */
814 end_addr = start_addr + devc->buffsize - 1;
815 /* now check if it fits into the same dma-pagesize */
816
817 if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1))
818 || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
819 printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize);
820 return 0;
821 }
822 }
823 devc->raw_buf = start_addr;
824 devc->raw_buf_phys = virt_to_bus(start_addr);
825
826 for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
827 SetPageReserved(page);
828 return 1;
829}
830
831static void sscape_free_dma(sscape_info *devc)
832{
833 int sz, size;
834 unsigned long start_addr, end_addr;
835 struct page *page;
836
837 if (devc->raw_buf == NULL) return;
838 for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
839 start_addr = (unsigned long) devc->raw_buf;
840 end_addr = start_addr + devc->buffsize;
841
842 for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
843 ClearPageReserved(page);
844
845 free_pages((unsigned long) devc->raw_buf, sz);
846 devc->raw_buf = NULL;
847}
848
849/* Intel version !!!!!!!!! */
850
851static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode)
852{
853 unsigned long flags;
854
855 flags = claim_dma_lock();
856 disable_dma(chan);
857 clear_dma_ff(chan);
858 set_dma_mode(chan, dma_mode);
859 set_dma_addr(chan, physaddr);
860 set_dma_count(chan, count);
861 enable_dma(chan);
862 release_dma_lock(flags);
863 return 0;
864}
865
866static void sscape_pnp_start_dma(sscape_info* devc, int arg )
867{
868 int reg;
869 if (arg == 0) reg = 2;
870 else reg = 3;
871
872 sscape_write(devc, reg, sscape_read( devc, reg) | 0x01);
873 sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE);
874}
875
876static int sscape_pnp_wait_dma (sscape_info* devc, int arg )
877{
878 int reg;
879 unsigned long i;
880 unsigned char d;
881
882 if (arg == 0) reg = 2;
883 else reg = 3;
884
885 sleep ( 1 );
886 i = 0;
887 do {
888 d = sscape_read(devc, reg) & 1;
889 if ( d == 1) break;
890 i++;
891 } while (i < 500000);
892 d = sscape_read(devc, reg) & 1;
893 return d;
894}
895
896static int sscape_pnp_alloc_dma(sscape_info* devc)
897{
898 /* printk(KERN_INFO "sscape: requesting dma\n"); */
899 if (request_dma(devc -> dma, "sscape")) return 0;
900 /* printk(KERN_INFO "sscape: dma channel allocated\n"); */
901 if (!sscape_alloc_dma(devc)) {
902 free_dma(devc -> dma);
903 return 0;
904 };
905 return 1;
906}
907
908static void sscape_pnp_free_dma(sscape_info* devc)
909{
910 sscape_free_dma( devc);
911 free_dma(devc -> dma );
912 /* printk(KERN_INFO "sscape: dma released\n"); */
913}
914
915static int sscape_pnp_upload_file(sscape_info* devc, char* fn)
916{
917 int done = 0;
918 int timeout_val;
919 char* data,*dt;
920 int len,l;
921 unsigned long flags;
922
923 sscape_write( devc, 9, sscape_read(devc, 9 ) & 0x3F );
924 sscape_write( devc, 2, (devc -> dma << 4) | 0x80 );
925 sscape_write( devc, 3, 0x20 );
926 sscape_write( devc, 9, sscape_read( devc, 9 ) | 0x80 );
927
928 len = mod_firmware_load(fn, &data);
929 if (len == 0) {
930 printk(KERN_ERR "sscape: file not found: %s\n", fn);
931 return 0;
932 }
933 dt = data;
934 spin_lock_irqsave(&devc->lock,flags);
935 while ( len > 0 ) {
936 if (len > devc -> buffsize) l = devc->buffsize;
937 else l = len;
938 len -= l;
939 memcpy(devc->raw_buf, dt, l); dt += l;
940 sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
941 sscape_pnp_start_dma ( devc, 0 );
942 if (sscape_pnp_wait_dma ( devc, 0 ) == 0) {
943 spin_unlock_irqrestore(&devc->lock,flags);
944 return 0;
945 }
946 }
947
948 spin_unlock_irqrestore(&devc->lock,flags);
949 vfree(data);
950
951 outb(0, devc -> base + 2);
952 outb(0, devc -> base);
953
954 sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40);
955
956 timeout_val = 5 * HZ;
957 while (!done && timeout_val-- > 0)
958 {
959 unsigned char x;
960 sleep(1);
961 x = inb( devc -> base + 3);
962 if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */
963 {
964 //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
965 done = 1;
966 }
967 }
968 timeout_val = 5 * HZ;
969 done = 0;
970 while (!done && timeout_val-- > 0)
971 {
972 unsigned char x;
973 sleep(1);
974 x = inb( devc -> base + 3);
975 if (x == 0xfe) /* OBP startup acknowledge */
976 {
977 //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
978 done = 1;
979 }
980 }
981
982 if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
983
984 sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
985 sscape_write( devc, 3, (devc -> dma << 4) + 0x80);
986 return 1;
987}
988
989static void __init sscape_pnp_init_hw(sscape_info* devc)
990{
991 unsigned char midi_irq = 0, sb_irq = 0;
992 unsigned i;
993 static char code_file_name[23] = "/sndscape/sndscape.cox";
994
995 int sscape_joystic_enable = 0x7f;
996 int sscape_mic_enable = 0;
997 int sscape_ext_midi = 0;
998
999 if ( !sscape_pnp_alloc_dma(devc) ) {
1000 printk(KERN_ERR "sscape: faild to allocate dma\n");
1001 return;
1002 }
1003
1004 for (i = 0; i < 4; i++) {
1005 if ( devc -> irq == valid_interrupts[i] )
1006 midi_irq = i;
1007 if ( devc -> codec_irq == valid_interrupts[i] )
1008 sb_irq = i;
1009 }
1010
1011 sscape_write( devc, 5, 0x50);
1012 sscape_write( devc, 7, 0x2e);
1013 sscape_write( devc, 8, 0x00);
1014
1015 sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
1016 sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);
1017
1018 sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
1019
1020 i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
1021 if (sscape_joystic_enable) i |= 8;
1022
1023 sscape_write (devc, 9, i);
1024 sscape_write (devc, 6, 0x80);
1025 sscape_write (devc, 1, 0x80);
1026
1027 if (devc -> codec_type == 2) {
1028 sscape_pnp_write_codec( devc, 0x0C, 0x50);
1029 sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F);
1030 sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0);
1031 sscape_pnp_write_codec( devc, 29, 0x20);
1032 }
1033
1034 if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) {
1035 printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n");
1036 sscape_pnp_free_dma(devc);
1037 return;
1038 }
1039
1040 i = sscape_read_host_ctrl( devc );
1041
1042 if ( (i & 0x0F) > 7 ) {
1043 printk(KERN_ERR "sscape: scope.cod faild\n");
1044 sscape_pnp_free_dma(devc);
1045 return;
1046 }
1047 if ( i & 0x10 ) sscape_write( devc, 7, 0x2F);
1048 code_file_name[21] = (char) ( i & 0x0F) + 0x30;
1049 if (sscape_pnp_upload_file( devc, code_file_name) == 0) {
1050 printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name);
1051 sscape_pnp_free_dma(devc);
1052 return;
1053 }
1054
1055 if (devc->ic_type != IC_ODIE) {
1056 sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
1057 ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
1058 }
1059 sscape_write_host_ctrl2( devc, 0x84, 0x64 ); /* MIDI volume */
1060 sscape_write_host_ctrl2( devc, 0x86, 0x64 ); /* MIDI volume?? */
1061 sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);
1062
1063 sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
1064 sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL
1065 sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL
1066 sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR
1067
1068 if (devc -> codec_type == 1) {
1069 sscape_pnp_write_codec ( devc, 4, 0x1F );
1070 sscape_pnp_write_codec ( devc, 5, 0x1F );
1071 sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable);
1072 } else {
1073 int t;
1074 sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1);
1075 sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1));
1076
1077 t = sscape_pnp_read_codec( devc, 0x00) & 0xDF;
1078 if ( (sscape_mic_enable == 0)) t |= 0;
1079 else t |= 0x20;
1080 sscape_pnp_write_codec ( devc, 0x00, t);
1081 t = sscape_pnp_read_codec( devc, 0x01) & 0xDF;
1082 if ( (sscape_mic_enable == 0) ) t |= 0;
1083 else t |= 0x20;
1084 sscape_pnp_write_codec ( devc, 0x01, t);
1085 sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20);
1086 outb(0, devc -> codec);
1087 }
1088 if (devc -> ic_type == IC_OPUS ) {
1089 int i = sscape_read( devc, 9 );
1090 sscape_write( devc, 9, i | 3 );
1091 sscape_write( devc, 3, 0x40);
1092
1093 if (request_region(0x228, 1, "sscape setup junk")) {
1094 outb(0, 0x228);
1095 release_region(0x228,1);
1096 }
1097 sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
1098 sscape_write( devc, 9, i );
1099 }
1100
1101 host_close ( devc );
1102 sscape_pnp_free_dma(devc);
1103}
1104
1105static int __init detect_sscape_pnp(sscape_info* devc)
1106{
1107 long i, irq_bits = 0xff;
1108 unsigned int d;
1109
1110 DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));
1111
1112 if (!request_region(devc->codec, 2, "sscape codec")) {
1113 printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);
1114 return 0;
1115 }
1116
1117 if ((inb(devc->base + 2) & 0x78) != 0)
1118 goto fail;
1119
1120 d = inb ( devc -> base + 4) & 0xF0;
1121 if (d & 0x80)
1122 goto fail;
1123
1124 if (d == 0) {
1125 devc->codec_type = 1;
1126 devc->ic_type = IC_ODIE;
1127 } else if ( (d & 0x60) != 0) {
1128 devc->codec_type = 2;
1129 devc->ic_type = IC_OPUS;
1130 } else if ( (d & 0x40) != 0) { /* WTF? */
1131 devc->codec_type = 2;
1132 devc->ic_type = IC_ODIE;
1133 } else
1134 goto fail;
1135
1136 sscape_is_pnp = 1;
1137
1138 outb(0xFA, devc -> base+4);
1139 if ((inb( devc -> base+4) & 0x9F) != 0x0A)
1140 goto fail;
1141 outb(0xFE, devc -> base+4);
1142 if ( (inb(devc -> base+4) & 0x9F) != 0x0E)
1143 goto fail;
1144 if ( (inb(devc -> base+5) & 0x9F) != 0x0E)
1145 goto fail;
1146
1147 if (devc->codec_type == 2) {
1148 if (devc->codec != devc->base + 8) {
1149 printk("soundscape warning: incorrect codec port specified\n");
1150 goto fail;
1151 }
1152 d = 0x10 | (sscape_read(devc, 9) & 0xCF);
1153 sscape_write(devc, 9, d);
1154 sscape_write(devc, 6, 0x80);
1155 } else {
1156 //todo: check codec is not base + 8
1157 }
1158
1159 d = (sscape_read(devc, 9) & 0x3F) | 0xC0;
1160 sscape_write(devc, 9, d);
1161
1162 for (i = 0; i < 550000; i++)
1163 if ( !(inb(devc -> codec) & 0x80) ) break;
1164
1165 d = inb(devc -> codec);
1166 if (d & 0x80)
1167 goto fail;
1168 if ( inb(devc -> codec + 2) == 0xFF)
1169 goto fail;
1170
1171 sscape_write(devc, 9, sscape_read(devc, 9) & 0x3F );
1172
1173 d = inb(devc -> codec) & 0x80;
1174 if ( d == 0) {
1175 printk(KERN_INFO "soundscape: hardware detected\n");
1176 valid_interrupts = valid_interrupts_new;
1177 } else {
1178 printk(KERN_INFO "soundscape: board looks like media fx\n");
1179 valid_interrupts = valid_interrupts_old;
1180 old_hardware = 1;
1181 }
1182
1183 sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9) & 0x3F) );
1184
1185 for (i = 0; i < 550000; i++)
1186 if ( !(inb(devc -> codec) & 0x80))
1187 break;
1188
1189 sscape_pnp_init_hw(devc);
1190
1191 for (i = 0; i < 4; i++)
1192 {
1193 if (devc->codec_irq == valid_interrupts[i]) {
1194 irq_bits = i;
1195 break;
1196 }
1197 }
1198 sscape_write(devc, GA_INTENA_REG, 0x00);
1199 sscape_write(devc, GA_DMACFG_REG, 0x50);
1200 sscape_write(devc, GA_DMAA_REG, 0x70);
1201 sscape_write(devc, GA_DMAB_REG, 0x20);
1202 sscape_write(devc, GA_INTCFG_REG, 0xf0);
1203 sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1));
1204
1205 sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
1206 sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
1207
1208 return 1;
1209fail:
1210 release_region(devc->codec, 2);
1211 return 0;
1212}
1213
1214static int __init probe_sscape(struct address_info *hw_config)
1215{
1216 devc->base = hw_config->io_base;
1217 devc->irq = hw_config->irq;
1218 devc->dma = hw_config->dma;
1219 devc->osp = hw_config->osp;
1220
1221#ifdef SSCAPE_DEBUG1
1222 /*
1223 * Temporary debugging aid. Print contents of the registers before
1224 * changing them.
1225 */
1226 {
1227 int i;
1228
1229 for (i = 0; i < 13; i++)
1230 printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
1231 }
1232#endif
1233 devc->failed = 1;
1234
1235 sscape_ports = request_region(devc->base, 2, "mpu401");
1236 if (!sscape_ports)
1237 return 0;
1238
1239 if (!request_region(devc->base + 2, 6, "SoundScape")) {
1240 release_region(devc->base, 2);
1241 return 0;
1242 }
1243
1244 if (!detect_ga(devc)) {
1245 if (detect_sscape_pnp(devc))
1246 return 1;
1247 release_region(devc->base, 2);
1248 release_region(devc->base + 2, 6);
1249 return 0;
1250 }
1251
1252 if (old_hardware) /* Check that it's really an old Spea/Reveal card. */
1253 {
1254 unsigned char tmp;
1255 int cc;
1256
1257 if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
1258 {
1259 sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
1260 for (cc = 0; cc < 200000; ++cc)
1261 inb(devc->base + ODIE_ADDR);
1262 }
1263 }
1264 return 1;
1265}
1266
1267static int __init init_ss_ms_sound(struct address_info *hw_config)
1268{
1269 int i, irq_bits = 0xff;
1270 int ad_flags = 0;
1271 struct resource *ports;
1272
1273 if (devc->failed)
1274 {
1275 printk(KERN_ERR "soundscape: Card not detected\n");
1276 return 0;
1277 }
1278 if (devc->ok == 0)
1279 {
1280 printk(KERN_ERR "soundscape: Invalid initialization order.\n");
1281 return 0;
1282 }
1283 for (i = 0; i < 4; i++)
1284 {
1285 if (hw_config->irq == valid_interrupts[i])
1286 {
1287 irq_bits = i;
1288 break;
1289 }
1290 }
1291 if (irq_bits == 0xff) {
1292 printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
1293 return 0;
1294 }
1295
1296 if (old_hardware)
1297 ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
1298 else if (sscape_is_pnp)
1299 ad_flags = 0x87654321; /* Tell that we have a soundscape pnp with 1845 chip */
1300
1301 ports = request_region(hw_config->io_base, 4, "ad1848");
1302 if (!ports) {
1303 printk(KERN_ERR "soundscape: ports busy\n");
1304 return 0;
1305 }
1306
1307 if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
1308 release_region(hw_config->io_base, 4);
1309 return 0;
1310 }
1311
1312 if (!sscape_is_pnp) /*pnp is already setup*/
1313 {
1314 /*
1315 * Setup the DMA polarity.
1316 */
1317 sscape_write(devc, GA_DMACFG_REG, 0x50);
1318
1319 /*
1320 * Take the gate-array off of the DMA channel.
1321 */
1322 sscape_write(devc, GA_DMAB_REG, 0x20);
1323
1324 /*
1325 * Init the AD1848 (CD-ROM) config reg.
1326 */
1327 sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
1328 }
1329
1330 if (hw_config->irq == devc->irq)
1331 printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
1332
1333 hw_config->slots[0] = ad1848_init(
1334 sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
1335 ports,
1336 hw_config->irq,
1337 hw_config->dma,
1338 hw_config->dma,
1339 0,
1340 devc->osp,
1341 THIS_MODULE);
1342
1343
1344 if (hw_config->slots[0] != -1) /* The AD1848 driver installed itself */
1345 {
1346 audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
1347 devc->codec_audiodev = hw_config->slots[0];
1348 devc->my_audiodev = hw_config->slots[0];
1349
1350 /* Set proper routings here (what are they) */
1351 AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
1352 }
1353
1354#ifdef SSCAPE_DEBUG5
1355 /*
1356 * Temporary debugging aid. Print contents of the registers
1357 * after the AD1848 device has been initialized.
1358 */
1359 {
1360 int i;
1361
1362 for (i = 0; i < 13; i++)
1363 printk("I%d = %02x\n", i, sscape_read(devc, i));
1364 }
1365#endif
1366 return 1;
1367}
1368
1369static void __exit unload_sscape(struct address_info *hw_config)
1370{
1371 release_region(devc->base + 2, 6);
1372 unload_mpu401(hw_config);
1373 if (sscape_is_pnp)
1374 release_region(devc->codec, 2);
1375}
1376
1377static void __exit unload_ss_ms_sound(struct address_info *hw_config)
1378{
1379 ad1848_unload(hw_config->io_base,
1380 hw_config->irq,
1381 devc->dma,
1382 devc->dma,
1383 0);
1384 sound_unload_audiodev(hw_config->slots[0]);
1385}
1386
1387static struct address_info cfg;
1388static struct address_info cfg_mpu;
1389
1390static int __initdata spea = -1;
1391static int mss = 0;
1392static int __initdata dma = -1;
1393static int __initdata irq = -1;
1394static int __initdata io = -1;
1395static int __initdata mpu_irq = -1;
1396static int __initdata mpu_io = -1;
1397
1398module_param(dma, int, 0);
1399module_param(irq, int, 0);
1400module_param(io, int, 0);
1401module_param(spea, int, 0); /* spea=0/1 set the old_hardware */
1402module_param(mpu_irq, int, 0);
1403module_param(mpu_io, int, 0);
1404module_param(mss, int, 0);
1405
1406static int __init init_sscape(void)
1407{
1408 printk(KERN_INFO "Soundscape driver Copyright (C) by Hannu Savolainen 1993-1996\n");
1409
1410 cfg.irq = irq;
1411 cfg.dma = dma;
1412 cfg.io_base = io;
1413
1414 cfg_mpu.irq = mpu_irq;
1415 cfg_mpu.io_base = mpu_io;
1416 /* WEH - Try to get right dma channel */
1417 cfg_mpu.dma = dma;
1418
1419 devc->codec = cfg.io_base;
1420 devc->codec_irq = cfg.irq;
1421 devc->codec_type = 0;
1422 devc->ic_type = 0;
1423 devc->raw_buf = NULL;
1424 spin_lock_init(&devc->lock);
1425
1426 if (cfg.dma == -1 || cfg.irq == -1 || cfg.io_base == -1) {
1427 printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n");
1428 return -EINVAL;
1429 }
1430
1431 if (cfg_mpu.irq == -1 && cfg_mpu.io_base != -1) {
1432 printk(KERN_ERR "MPU_IRQ must be specified if MPU_IO is set.\n");
1433 return -EINVAL;
1434 }
1435
1436 if(spea != -1) {
1437 old_hardware = spea;
1438 printk(KERN_INFO "Forcing %s hardware support.\n",
1439 spea?"new":"old");
1440 }
1441 if (probe_sscape(&cfg_mpu) == 0)
1442 return -ENODEV;
1443
1444 attach_sscape(&cfg_mpu);
1445
1446 mss = init_ss_ms_sound(&cfg);
1447
1448 return 0;
1449}
1450
1451static void __exit cleanup_sscape(void)
1452{
1453 if (mss)
1454 unload_ss_ms_sound(&cfg);
1455 unload_sscape(&cfg_mpu);
1456}
1457
1458module_init(init_sscape);
1459module_exit(cleanup_sscape);
1460
1461#ifndef MODULE
1462static int __init setup_sscape(char *str)
1463{
1464 /* io, irq, dma, mpu_io, mpu_irq */
1465 int ints[6];
1466
1467 str = get_options(str, ARRAY_SIZE(ints), ints);
1468
1469 io = ints[1];
1470 irq = ints[2];
1471 dma = ints[3];
1472 mpu_io = ints[4];
1473 mpu_irq = ints[5];
1474
1475 return 1;
1476}
1477
1478__setup("sscape=", setup_sscape);
1479#endif
1480MODULE_LICENSE("GPL");
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 75c602b5b132..351654cf7b09 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -570,6 +570,7 @@ config SND_ICE1712
570 tristate "ICEnsemble ICE1712 (Envy24)" 570 tristate "ICEnsemble ICE1712 (Envy24)"
571 select SND_MPU401_UART 571 select SND_MPU401_UART
572 select SND_AC97_CODEC 572 select SND_AC97_CODEC
573 select BITREVERSE
573 help 574 help
574 Say Y here to include support for soundcards based on the 575 Say Y here to include support for soundcards based on the
575 ICE1712 (Envy24) chip. 576 ICE1712 (Envy24) chip.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 78288dbfc17a..20cb60afb200 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -603,8 +603,8 @@ AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1)
603}; 603};
604 604
605static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = { 605static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = {
606AC97_SINGLE("PC Speaker Playback Switch", AC97_PC_BEEP, 15, 1, 1), 606AC97_SINGLE("Beep Playback Switch", AC97_PC_BEEP, 15, 1, 1),
607AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) 607AC97_SINGLE("Beep Playback Volume", AC97_PC_BEEP, 1, 15, 1)
608}; 608};
609 609
610static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = 610static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
@@ -1393,7 +1393,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1393 } 1393 }
1394 } 1394 }
1395 1395
1396 /* build PC Speaker controls */ 1396 /* build Beep controls */
1397 if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && 1397 if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) &&
1398 ((ac97->flags & AC97_HAS_PC_BEEP) || 1398 ((ac97->flags & AC97_HAS_PC_BEEP) ||
1399 snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { 1399 snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) {
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 7337abdbe4e3..139cf3b2b9d7 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -800,12 +800,12 @@ AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
800AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0), 800AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
801AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1), 801AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
802 802
803AC97_SINGLE("PC Beep to Headphone Switch", AC97_AUX, 15, 1, 1), 803AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
804AC97_SINGLE("PC Beep to Headphone Volume", AC97_AUX, 12, 7, 1), 804AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
805AC97_SINGLE("PC Beep to Master Switch", AC97_AUX, 11, 1, 1), 805AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
806AC97_SINGLE("PC Beep to Master Volume", AC97_AUX, 8, 7, 1), 806AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
807AC97_SINGLE("PC Beep to Mono Switch", AC97_AUX, 7, 1, 1), 807AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
808AC97_SINGLE("PC Beep to Mono Volume", AC97_AUX, 4, 7, 1), 808AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
809 809
810AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1), 810AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
811AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1), 811AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 8451a0169f32..69867ace7860 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -830,8 +830,8 @@ static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
830 AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0), 830 AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0),
831 AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1), 831 AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1),
832 AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1), 832 AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1),
833 AZF3328_MIXER_SWITCH("PC Speaker Playback Switch", IDX_MIXER_PCBEEP, 15, 1), 833 AZF3328_MIXER_SWITCH("Beep Playback Switch", IDX_MIXER_PCBEEP, 15, 1),
834 AZF3328_MIXER_VOL_SPECIAL("PC Speaker Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), 834 AZF3328_MIXER_VOL_SPECIAL("Beep Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1),
835 AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1), 835 AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1),
836 AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1), 836 AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1),
837 AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1), 837 AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1),
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index c8c6f437f5b3..8f443a9d61ec 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -792,8 +792,8 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
792 "Phone Playback Volume", 792 "Phone Playback Volume",
793 "Video Playback Switch", 793 "Video Playback Switch",
794 "Video Playback Volume", 794 "Video Playback Volume",
795 "PC Speaker Playback Switch", 795 "Beep Playback Switch",
796 "PC Speaker Playback Volume", 796 "Beep Playback Volume",
797 "Mono Output Select", 797 "Mono Output Select",
798 "Capture Source", 798 "Capture Source",
799 "Capture Switch", 799 "Capture Switch",
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index c62b7d10ec61..15523e60351c 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -304,7 +304,7 @@ static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry,
304 while (!snd_info_get_line(buffer, line, sizeof(line))) { 304 while (!snd_info_get_line(buffer, line, sizeof(line))) {
305 if (sscanf(line, "%x %x", &reg, &val) != 2) 305 if (sscanf(line, "%x %x", &reg, &val) != 2)
306 continue; 306 continue;
307 if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) { 307 if (reg < 0x40 && val <= 0xffffffff) {
308 spin_lock_irqsave(&emu->emu_lock, flags); 308 spin_lock_irqsave(&emu->emu_lock, flags);
309 outl(val, emu->port + (reg & 0xfffffffc)); 309 outl(val, emu->port + (reg & 0xfffffffc));
310 spin_unlock_irqrestore(&emu->emu_lock, flags); 310 spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -405,7 +405,7 @@ static void snd_ca0106_proc_reg_write(struct snd_info_entry *entry,
405 while (!snd_info_get_line(buffer, line, sizeof(line))) { 405 while (!snd_info_get_line(buffer, line, sizeof(line))) {
406 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3) 406 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
407 continue; 407 continue;
408 if ((reg < 0x80) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) ) 408 if (reg < 0x80 && val <= 0xffffffff && channel_id <= 3)
409 snd_ca0106_ptr_write(emu, reg, channel_id, val); 409 snd_ca0106_ptr_write(emu, reg, channel_id, val);
410 } 410 }
411} 411}
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index ddcd4a9fd7e6..a312bae08f52 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2302,7 +2302,7 @@ static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
2302 CMIPCI_SB_VOL_MONO("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), 2302 CMIPCI_SB_VOL_MONO("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
2303 CMIPCI_SB_SW_MONO("Mic Playback Switch", 0), 2303 CMIPCI_SB_SW_MONO("Mic Playback Switch", 0),
2304 CMIPCI_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1, 0, 0), 2304 CMIPCI_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1, 0, 0),
2305 CMIPCI_SB_VOL_MONO("PC Speaker Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3), 2305 CMIPCI_SB_VOL_MONO("Beep Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
2306 CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), 2306 CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15),
2307 CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), 2307 CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0),
2308 CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), 2308 CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0),
@@ -2310,7 +2310,7 @@ static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
2310 CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), 2310 CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7),
2311 CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), 2311 CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7),
2312 CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), 2312 CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0),
2313 CMIPCI_DOUBLE("PC Speaker Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), 2313 CMIPCI_DOUBLE("Beep Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0),
2314 CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), 2314 CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0),
2315}; 2315};
2316 2316
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 75454648d50c..cb65bd0dd35b 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -240,7 +240,7 @@ static int select_rom(unsigned int pitch)
240 } else if (pitch == 0x02000000) { 240 } else if (pitch == 0x02000000) {
241 /* pitch == 2 */ 241 /* pitch == 2 */
242 return 3; 242 return 3;
243 } else if (pitch >= 0x0 && pitch <= 0x08000000) { 243 } else if (pitch <= 0x08000000) {
244 /* 0 <= pitch <= 8 */ 244 /* 0 <= pitch <= 8 */
245 return 0; 245 return 0;
246 } else { 246 } else {
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 36e08bd2b3cc..6b8ae7b5cd54 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1040,8 +1040,7 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
1040 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3) 1040 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
1041 continue; 1041 continue;
1042 1042
1043 if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff) 1043 if (reg < 0x49 && val <= 0xffffffff && channel_id <= 2)
1044 && (channel_id >= 0) && (channel_id <= 2) )
1045 snd_emu10k1x_ptr_write(emu, reg, channel_id, val); 1044 snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
1046 } 1045 }
1047} 1046}
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index b0fb6c917c38..05afe06e353a 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -1818,8 +1818,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1818 "Master Playback Switch", "Master Capture Switch", 1818 "Master Playback Switch", "Master Capture Switch",
1819 "Master Playback Volume", "Master Capture Volume", 1819 "Master Playback Volume", "Master Capture Volume",
1820 "Wave Master Playback Volume", "Master Playback Volume", 1820 "Wave Master Playback Volume", "Master Playback Volume",
1821 "PC Speaker Playback Switch", "PC Speaker Capture Switch", 1821 "Beep Playback Switch", "Beep Capture Switch",
1822 "PC Speaker Playback Volume", "PC Speaker Capture Volume", 1822 "Beep Playback Volume", "Beep Capture Volume",
1823 "Phone Playback Switch", "Phone Capture Switch", 1823 "Phone Playback Switch", "Phone Capture Switch",
1824 "Phone Playback Volume", "Phone Capture Volume", 1824 "Phone Playback Volume", "Phone Capture Volume",
1825 "Mic Playback Switch", "Mic Capture Switch", 1825 "Mic Playback Switch", "Mic Capture Switch",
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 216f9748aff5..baa7cd508cd8 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -451,7 +451,7 @@ static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
451 while (!snd_info_get_line(buffer, line, sizeof(line))) { 451 while (!snd_info_get_line(buffer, line, sizeof(line))) {
452 if (sscanf(line, "%x %x", &reg, &val) != 2) 452 if (sscanf(line, "%x %x", &reg, &val) != 2)
453 continue; 453 continue;
454 if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) { 454 if (reg < 0x40 && val <= 0xffffffff) {
455 spin_lock_irqsave(&emu->emu_lock, flags); 455 spin_lock_irqsave(&emu->emu_lock, flags);
456 outl(val, emu->port + (reg & 0xfffffffc)); 456 outl(val, emu->port + (reg & 0xfffffffc));
457 spin_unlock_irqrestore(&emu->emu_lock, flags); 457 spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -527,7 +527,7 @@ static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
527 while (!snd_info_get_line(buffer, line, sizeof(line))) { 527 while (!snd_info_get_line(buffer, line, sizeof(line))) {
528 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3) 528 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
529 continue; 529 continue;
530 if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) ) 530 if (reg < 0xa0 && val <= 0xffffffff && channel_id <= 3)
531 snd_ptr_write(emu, iobase, reg, channel_id, val); 531 snd_ptr_write(emu, iobase, reg, channel_id, val);
532 } 532 }
533} 533}
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index c1a5aa15af8f..5ef7080e14d0 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -256,7 +256,7 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
256 if (reg > 0x3f) 256 if (reg > 0x3f)
257 return 1; 257 return 1;
258 reg += 0x40; /* 0x40 upwards are registers. */ 258 reg += 0x40; /* 0x40 upwards are registers. */
259 if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ 259 if (value > 0x3f) /* 0 to 0x3f are values */
260 return 1; 260 return 1;
261 spin_lock_irqsave(&emu->emu_lock, flags); 261 spin_lock_irqsave(&emu->emu_lock, flags);
262 outl(reg, emu->port + A_IOCFG); 262 outl(reg, emu->port + A_IOCFG);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 820318ee62c1..fb83e1ffa5cb 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1387,7 +1387,7 @@ ES1938_DOUBLE_TLV("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0,
1387 db_scale_line), 1387 db_scale_line),
1388ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0, 1388ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0,
1389 db_scale_capture), 1389 db_scale_capture),
1390ES1938_SINGLE("PC Speaker Volume", 0, 0x3c, 0, 7, 0), 1390ES1938_SINGLE("Beep Volume", 0, 0x3c, 0, 7, 0),
1391ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), 1391ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0),
1392ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), 1392ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
1393{ 1393{
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 60cdb9e0b68d..83508b3964fb 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -55,7 +55,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
55 * 1 = MediaForte 256-PCS 55 * 1 = MediaForte 256-PCS
56 * 2 = MediaForte 256-PCPR 56 * 2 = MediaForte 256-PCPR
57 * 3 = MediaForte 64-PCR 57 * 3 = MediaForte 64-PCR
58 * 16 = setup tuner only (this is additional bit), i.e. SF-64-PCR FM card 58 * 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card
59 * High 16-bits are video (radio) device number + 1 59 * High 16-bits are video (radio) device number + 1
60 */ 60 */
61static int tea575x_tuner[SNDRV_CARDS]; 61static int tea575x_tuner[SNDRV_CARDS];
@@ -67,7 +67,10 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
67module_param_array(enable, bool, NULL, 0444); 67module_param_array(enable, bool, NULL, 0444);
68MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); 68MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
69module_param_array(tea575x_tuner, int, NULL, 0444); 69module_param_array(tea575x_tuner, int, NULL, 0444);
70MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner."); 70MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (1 = SF256-PCS, 2=SF256-PCPR, 3=SF64-PCR, +16=tuner-only).");
71
72#define TUNER_ONLY (1<<4)
73#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF)
71 74
72/* 75/*
73 * Direct registers 76 * Direct registers
@@ -160,7 +163,7 @@ struct fm801 {
160 unsigned int multichannel: 1, /* multichannel support */ 163 unsigned int multichannel: 1, /* multichannel support */
161 secondary: 1; /* secondary codec */ 164 secondary: 1; /* secondary codec */
162 unsigned char secondary_addr; /* address of the secondary codec */ 165 unsigned char secondary_addr; /* address of the secondary codec */
163 unsigned int tea575x_tuner; /* tuner flags */ 166 unsigned int tea575x_tuner; /* tuner access method & flags */
164 167
165 unsigned short ply_ctrl; /* playback control */ 168 unsigned short ply_ctrl; /* playback control */
166 unsigned short cap_ctrl; /* capture control */ 169 unsigned short cap_ctrl; /* capture control */
@@ -1287,7 +1290,7 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
1287{ 1290{
1288 unsigned short cmdw; 1291 unsigned short cmdw;
1289 1292
1290 if (chip->tea575x_tuner & 0x0010) 1293 if (chip->tea575x_tuner & TUNER_ONLY)
1291 goto __ac97_ok; 1294 goto __ac97_ok;
1292 1295
1293 /* codec cold reset + AC'97 warm reset */ 1296 /* codec cold reset + AC'97 warm reset */
@@ -1296,11 +1299,13 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
1296 udelay(100); 1299 udelay(100);
1297 outw(0, FM801_REG(chip, CODEC_CTRL)); 1300 outw(0, FM801_REG(chip, CODEC_CTRL));
1298 1301
1299 if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) { 1302 if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0)
1300 snd_printk(KERN_ERR "Primary AC'97 codec not found\n"); 1303 if (!resume) {
1301 if (! resume) 1304 snd_printk(KERN_INFO "Primary AC'97 codec not found, "
1302 return -EIO; 1305 "assume SF64-PCR (tuner-only)\n");
1303 } 1306 chip->tea575x_tuner = 3 | TUNER_ONLY;
1307 goto __ac97_ok;
1308 }
1304 1309
1305 if (chip->multichannel) { 1310 if (chip->multichannel) {
1306 if (chip->secondary_addr) { 1311 if (chip->secondary_addr) {
@@ -1414,7 +1419,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
1414 return err; 1419 return err;
1415 } 1420 }
1416 chip->port = pci_resource_start(pci, 0); 1421 chip->port = pci_resource_start(pci, 0);
1417 if ((tea575x_tuner & 0x0010) == 0) { 1422 if ((tea575x_tuner & TUNER_ONLY) == 0) {
1418 if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, 1423 if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
1419 "FM801", chip)) { 1424 "FM801", chip)) {
1420 snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); 1425 snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
@@ -1429,6 +1434,14 @@ static int __devinit snd_fm801_create(struct snd_card *card,
1429 chip->multichannel = 1; 1434 chip->multichannel = 1;
1430 1435
1431 snd_fm801_chip_init(chip, 0); 1436 snd_fm801_chip_init(chip, 0);
1437 /* init might set tuner access method */
1438 tea575x_tuner = chip->tea575x_tuner;
1439
1440 if (chip->irq >= 0 && (tea575x_tuner & TUNER_ONLY)) {
1441 pci_clear_master(pci);
1442 free_irq(chip->irq, chip);
1443 chip->irq = -1;
1444 }
1432 1445
1433 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 1446 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1434 snd_fm801_free(chip); 1447 snd_fm801_free(chip);
@@ -1438,12 +1451,13 @@ static int __devinit snd_fm801_create(struct snd_card *card,
1438 snd_card_set_dev(card, &pci->dev); 1451 snd_card_set_dev(card, &pci->dev);
1439 1452
1440#ifdef TEA575X_RADIO 1453#ifdef TEA575X_RADIO
1441 if (tea575x_tuner > 0 && (tea575x_tuner & 0x000f) < 4) { 1454 if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
1455 (tea575x_tuner & TUNER_TYPE_MASK) < 4) {
1442 chip->tea.dev_nr = tea575x_tuner >> 16; 1456 chip->tea.dev_nr = tea575x_tuner >> 16;
1443 chip->tea.card = card; 1457 chip->tea.card = card;
1444 chip->tea.freq_fixup = 10700; 1458 chip->tea.freq_fixup = 10700;
1445 chip->tea.private_data = chip; 1459 chip->tea.private_data = chip;
1446 chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0x000f) - 1]; 1460 chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & TUNER_TYPE_MASK) - 1];
1447 snd_tea575x_init(&chip->tea); 1461 snd_tea575x_init(&chip->tea);
1448 } 1462 }
1449#endif 1463#endif
@@ -1483,7 +1497,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
1483 sprintf(card->longname, "%s at 0x%lx, irq %i", 1497 sprintf(card->longname, "%s at 0x%lx, irq %i",
1484 card->shortname, chip->port, chip->irq); 1498 card->shortname, chip->port, chip->irq);
1485 1499
1486 if (tea575x_tuner[dev] & 0x0010) 1500 if (chip->tea575x_tuner & TUNER_ONLY)
1487 goto __fm801_tuner_only; 1501 goto __fm801_tuner_only;
1488 1502
1489 if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { 1503 if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) {
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 55545e0818b5..556cff937be7 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -38,9 +38,20 @@ config SND_HDA_INPUT_BEEP
38 Say Y here to build a digital beep interface for HD-audio 38 Say Y here to build a digital beep interface for HD-audio
39 driver. This interface is used to generate digital beeps. 39 driver. This interface is used to generate digital beeps.
40 40
41config SND_HDA_INPUT_BEEP_MODE
42 int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)"
43 depends on SND_HDA_INPUT_BEEP=y
44 default "1"
45 range 0 2
46 help
47 Set 0 to disable the digital beep interface for HD-audio by default.
48 Set 1 to always enable the digital beep interface for HD-audio by
49 default. Set 2 to control the beep device registration to input
50 layer using a "Beep Switch" in mixer applications.
51
41config SND_HDA_INPUT_JACK 52config SND_HDA_INPUT_JACK
42 bool "Support jack plugging notification via input layer" 53 bool "Support jack plugging notification via input layer"
43 depends on INPUT=y || INPUT=SND_HDA_INTEL 54 depends on INPUT=y || INPUT=SND
44 select SND_JACK 55 select SND_JACK
45 help 56 help
46 Say Y here to enable the jack plugging notification via 57 Say Y here to enable the jack plugging notification via
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 3f51a981e604..5fe34a8d8c81 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -113,23 +113,25 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
113 return 0; 113 return 0;
114} 114}
115 115
116int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) 116static void snd_hda_do_detach(struct hda_beep *beep)
117{
118 input_unregister_device(beep->dev);
119 beep->dev = NULL;
120 cancel_work_sync(&beep->beep_work);
121 /* turn off beep for sure */
122 snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
123 AC_VERB_SET_BEEP_CONTROL, 0);
124}
125
126static int snd_hda_do_attach(struct hda_beep *beep)
117{ 127{
118 struct input_dev *input_dev; 128 struct input_dev *input_dev;
119 struct hda_beep *beep; 129 struct hda_codec *codec = beep->codec;
120 int err; 130 int err;
121 131
122 if (!snd_hda_get_bool_hint(codec, "beep"))
123 return 0; /* disabled explicitly */
124
125 beep = kzalloc(sizeof(*beep), GFP_KERNEL);
126 if (beep == NULL)
127 return -ENOMEM;
128 snprintf(beep->phys, sizeof(beep->phys),
129 "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
130 input_dev = input_allocate_device(); 132 input_dev = input_allocate_device();
131 if (!input_dev) { 133 if (!input_dev) {
132 kfree(beep); 134 printk(KERN_INFO "hda_beep: unable to allocate input device\n");
133 return -ENOMEM; 135 return -ENOMEM;
134 } 136 }
135 137
@@ -151,21 +153,96 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
151 err = input_register_device(input_dev); 153 err = input_register_device(input_dev);
152 if (err < 0) { 154 if (err < 0) {
153 input_free_device(input_dev); 155 input_free_device(input_dev);
154 kfree(beep); 156 printk(KERN_INFO "hda_beep: unable to register input device\n");
155 return err; 157 return err;
156 } 158 }
159 beep->dev = input_dev;
160 return 0;
161}
162
163static void snd_hda_do_register(struct work_struct *work)
164{
165 struct hda_beep *beep =
166 container_of(work, struct hda_beep, register_work);
167
168 mutex_lock(&beep->mutex);
169 if (beep->enabled && !beep->dev)
170 snd_hda_do_attach(beep);
171 mutex_unlock(&beep->mutex);
172}
173
174static void snd_hda_do_unregister(struct work_struct *work)
175{
176 struct hda_beep *beep =
177 container_of(work, struct hda_beep, unregister_work.work);
178
179 mutex_lock(&beep->mutex);
180 if (!beep->enabled && beep->dev)
181 snd_hda_do_detach(beep);
182 mutex_unlock(&beep->mutex);
183}
157 184
185int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
186{
187 struct hda_beep *beep = codec->beep;
188 enable = !!enable;
189 if (beep == NULL)
190 return 0;
191 if (beep->enabled != enable) {
192 beep->enabled = enable;
193 if (!enable) {
194 /* turn off beep */
195 snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
196 AC_VERB_SET_BEEP_CONTROL, 0);
197 }
198 if (beep->mode == HDA_BEEP_MODE_SWREG) {
199 if (enable) {
200 cancel_delayed_work(&beep->unregister_work);
201 schedule_work(&beep->register_work);
202 } else {
203 schedule_delayed_work(&beep->unregister_work,
204 HZ);
205 }
206 }
207 return 1;
208 }
209 return 0;
210}
211EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device);
212
213int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
214{
215 struct hda_beep *beep;
216
217 if (!snd_hda_get_bool_hint(codec, "beep"))
218 return 0; /* disabled explicitly by hints */
219 if (codec->beep_mode == HDA_BEEP_MODE_OFF)
220 return 0; /* disabled by module option */
221
222 beep = kzalloc(sizeof(*beep), GFP_KERNEL);
223 if (beep == NULL)
224 return -ENOMEM;
225 snprintf(beep->phys, sizeof(beep->phys),
226 "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
158 /* enable linear scale */ 227 /* enable linear scale */
159 snd_hda_codec_write(codec, nid, 0, 228 snd_hda_codec_write(codec, nid, 0,
160 AC_VERB_SET_DIGI_CONVERT_2, 0x01); 229 AC_VERB_SET_DIGI_CONVERT_2, 0x01);
161 230
162 beep->nid = nid; 231 beep->nid = nid;
163 beep->dev = input_dev;
164 beep->codec = codec; 232 beep->codec = codec;
165 beep->enabled = 1; 233 beep->mode = codec->beep_mode;
166 codec->beep = beep; 234 codec->beep = beep;
167 235
236 INIT_WORK(&beep->register_work, &snd_hda_do_register);
237 INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister);
168 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); 238 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
239 mutex_init(&beep->mutex);
240
241 if (beep->mode == HDA_BEEP_MODE_ON) {
242 beep->enabled = 1;
243 snd_hda_do_register(&beep->register_work);
244 }
245
169 return 0; 246 return 0;
170} 247}
171EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); 248EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
@@ -174,11 +251,12 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
174{ 251{
175 struct hda_beep *beep = codec->beep; 252 struct hda_beep *beep = codec->beep;
176 if (beep) { 253 if (beep) {
177 cancel_work_sync(&beep->beep_work); 254 cancel_work_sync(&beep->register_work);
178 255 cancel_delayed_work(&beep->unregister_work);
179 input_unregister_device(beep->dev); 256 if (beep->enabled)
180 kfree(beep); 257 snd_hda_do_detach(beep);
181 codec->beep = NULL; 258 codec->beep = NULL;
259 kfree(beep);
182 } 260 }
183} 261}
184EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); 262EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index 0c3de787c717..f1de1bac042c 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -24,19 +24,29 @@
24 24
25#include "hda_codec.h" 25#include "hda_codec.h"
26 26
27#define HDA_BEEP_MODE_OFF 0
28#define HDA_BEEP_MODE_ON 1
29#define HDA_BEEP_MODE_SWREG 2
30
27/* beep information */ 31/* beep information */
28struct hda_beep { 32struct hda_beep {
29 struct input_dev *dev; 33 struct input_dev *dev;
30 struct hda_codec *codec; 34 struct hda_codec *codec;
35 unsigned int mode;
31 char phys[32]; 36 char phys[32];
32 int tone; 37 int tone;
33 hda_nid_t nid; 38 hda_nid_t nid;
34 unsigned int enabled:1; 39 unsigned int enabled:1;
40 unsigned int request_enable:1;
35 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ 41 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
42 struct work_struct register_work; /* registration work */
43 struct delayed_work unregister_work; /* unregistration work */
36 struct work_struct beep_work; /* scheduled task for beep event */ 44 struct work_struct beep_work; /* scheduled task for beep event */
45 struct mutex mutex;
37}; 46};
38 47
39#ifdef CONFIG_SND_HDA_INPUT_BEEP 48#ifdef CONFIG_SND_HDA_INPUT_BEEP
49int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
40int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); 50int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
41void snd_hda_detach_beep_device(struct hda_codec *codec); 51void snd_hda_detach_beep_device(struct hda_codec *codec);
42#else 52#else
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index af989f660cca..9cfdb771928c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -30,6 +30,7 @@
30#include <sound/tlv.h> 30#include <sound/tlv.h>
31#include <sound/initval.h> 31#include <sound/initval.h>
32#include "hda_local.h" 32#include "hda_local.h"
33#include "hda_beep.h"
33#include <sound/hda_hwdep.h> 34#include <sound/hda_hwdep.h>
34 35
35/* 36/*
@@ -93,6 +94,13 @@ static void hda_keep_power_on(struct hda_codec *codec);
93static inline void hda_keep_power_on(struct hda_codec *codec) {} 94static inline void hda_keep_power_on(struct hda_codec *codec) {}
94#endif 95#endif
95 96
97/**
98 * snd_hda_get_jack_location - Give a location string of the jack
99 * @cfg: pin default config value
100 *
101 * Parse the pin default config value and returns the string of the
102 * jack location, e.g. "Rear", "Front", etc.
103 */
96const char *snd_hda_get_jack_location(u32 cfg) 104const char *snd_hda_get_jack_location(u32 cfg)
97{ 105{
98 static char *bases[7] = { 106 static char *bases[7] = {
@@ -120,6 +128,13 @@ const char *snd_hda_get_jack_location(u32 cfg)
120} 128}
121EXPORT_SYMBOL_HDA(snd_hda_get_jack_location); 129EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
122 130
131/**
132 * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
133 * @cfg: pin default config value
134 *
135 * Parse the pin default config value and returns the string of the
136 * jack connectivity, i.e. external or internal connection.
137 */
123const char *snd_hda_get_jack_connectivity(u32 cfg) 138const char *snd_hda_get_jack_connectivity(u32 cfg)
124{ 139{
125 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; 140 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
@@ -128,6 +143,13 @@ const char *snd_hda_get_jack_connectivity(u32 cfg)
128} 143}
129EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity); 144EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
130 145
146/**
147 * snd_hda_get_jack_type - Give a type string of the jack
148 * @cfg: pin default config value
149 *
150 * Parse the pin default config value and returns the string of the
151 * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
152 */
131const char *snd_hda_get_jack_type(u32 cfg) 153const char *snd_hda_get_jack_type(u32 cfg)
132{ 154{
133 static char *jack_types[16] = { 155 static char *jack_types[16] = {
@@ -515,6 +537,7 @@ static int snd_hda_bus_dev_register(struct snd_device *device)
515 struct hda_codec *codec; 537 struct hda_codec *codec;
516 list_for_each_entry(codec, &bus->codec_list, list) { 538 list_for_each_entry(codec, &bus->codec_list, list) {
517 snd_hda_hwdep_add_sysfs(codec); 539 snd_hda_hwdep_add_sysfs(codec);
540 snd_hda_hwdep_add_power_sysfs(codec);
518 } 541 }
519 return 0; 542 return 0;
520} 543}
@@ -820,6 +843,16 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
820 return 0; 843 return 0;
821} 844}
822 845
846/**
847 * snd_hda_codec_set_pincfg - Override a pin default configuration
848 * @codec: the HDA codec
849 * @nid: NID to set the pin config
850 * @cfg: the pin default config value
851 *
852 * Override a pin default configuration value in the cache.
853 * This value can be read by snd_hda_codec_get_pincfg() in a higher
854 * priority than the real hardware value.
855 */
823int snd_hda_codec_set_pincfg(struct hda_codec *codec, 856int snd_hda_codec_set_pincfg(struct hda_codec *codec,
824 hda_nid_t nid, unsigned int cfg) 857 hda_nid_t nid, unsigned int cfg)
825{ 858{
@@ -827,7 +860,15 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec,
827} 860}
828EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg); 861EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
829 862
830/* get the current pin config value of the given pin NID */ 863/**
864 * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
865 * @codec: the HDA codec
866 * @nid: NID to get the pin config
867 *
868 * Get the current pin config value of the given pin NID.
869 * If the pincfg value is cached or overridden via sysfs or driver,
870 * returns the cached value.
871 */
831unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) 872unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
832{ 873{
833 struct hda_pincfg *pin; 874 struct hda_pincfg *pin;
@@ -944,7 +985,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
944 mutex_init(&codec->control_mutex); 985 mutex_init(&codec->control_mutex);
945 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); 986 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
946 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); 987 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
947 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); 988 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60);
948 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); 989 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
949 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); 990 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
950 if (codec->bus->modelname) { 991 if (codec->bus->modelname) {
@@ -1026,6 +1067,15 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
1026} 1067}
1027EXPORT_SYMBOL_HDA(snd_hda_codec_new); 1068EXPORT_SYMBOL_HDA(snd_hda_codec_new);
1028 1069
1070/**
1071 * snd_hda_codec_configure - (Re-)configure the HD-audio codec
1072 * @codec: the HDA codec
1073 *
1074 * Start parsing of the given codec tree and (re-)initialize the whole
1075 * patch instance.
1076 *
1077 * Returns 0 if successful or a negative error code.
1078 */
1029int snd_hda_codec_configure(struct hda_codec *codec) 1079int snd_hda_codec_configure(struct hda_codec *codec)
1030{ 1080{
1031 int err; 1081 int err;
@@ -1088,6 +1138,11 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1088} 1138}
1089EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); 1139EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
1090 1140
1141/**
1142 * snd_hda_codec_cleanup_stream - clean up the codec for closing
1143 * @codec: the CODEC to clean up
1144 * @nid: the NID to clean up
1145 */
1091void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) 1146void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1092{ 1147{
1093 if (!nid) 1148 if (!nid)
@@ -1163,8 +1218,17 @@ get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1163 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); 1218 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1164} 1219}
1165 1220
1166/* 1221/**
1167 * query AMP capabilities for the given widget and direction 1222 * query_amp_caps - query AMP capabilities
1223 * @codec: the HD-auio codec
1224 * @nid: the NID to query
1225 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1226 *
1227 * Query AMP capabilities for the given widget and direction.
1228 * Returns the obtained capability bits.
1229 *
1230 * When cap bits have been already read, this doesn't read again but
1231 * returns the cached value.
1168 */ 1232 */
1169u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) 1233u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
1170{ 1234{
@@ -1187,6 +1251,19 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
1187} 1251}
1188EXPORT_SYMBOL_HDA(query_amp_caps); 1252EXPORT_SYMBOL_HDA(query_amp_caps);
1189 1253
1254/**
1255 * snd_hda_override_amp_caps - Override the AMP capabilities
1256 * @codec: the CODEC to clean up
1257 * @nid: the NID to clean up
1258 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1259 * @caps: the capability bits to set
1260 *
1261 * Override the cached AMP caps bits value by the given one.
1262 * This function is useful if the driver needs to adjust the AMP ranges,
1263 * e.g. limit to 0dB, etc.
1264 *
1265 * Returns zero if successful or a negative error code.
1266 */
1190int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, 1267int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1191 unsigned int caps) 1268 unsigned int caps)
1192{ 1269{
@@ -1222,6 +1299,17 @@ static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1222 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); 1299 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1223} 1300}
1224 1301
1302/**
1303 * snd_hda_query_pin_caps - Query PIN capabilities
1304 * @codec: the HD-auio codec
1305 * @nid: the NID to query
1306 *
1307 * Query PIN capabilities for the given widget.
1308 * Returns the obtained capability bits.
1309 *
1310 * When cap bits have been already read, this doesn't read again but
1311 * returns the cached value.
1312 */
1225u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) 1313u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1226{ 1314{
1227 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid), 1315 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
@@ -1229,6 +1317,40 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1229} 1317}
1230EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); 1318EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1231 1319
1320/**
1321 * snd_hda_pin_sense - execute pin sense measurement
1322 * @codec: the CODEC to sense
1323 * @nid: the pin NID to sense
1324 *
1325 * Execute necessary pin sense measurement and return its Presence Detect,
1326 * Impedance, ELD Valid etc. status bits.
1327 */
1328u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
1329{
1330 u32 pincap = snd_hda_query_pin_caps(codec, nid);
1331
1332 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
1333 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
1334
1335 return snd_hda_codec_read(codec, nid, 0,
1336 AC_VERB_GET_PIN_SENSE, 0);
1337}
1338EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
1339
1340/**
1341 * snd_hda_jack_detect - query pin Presence Detect status
1342 * @codec: the CODEC to sense
1343 * @nid: the pin NID to sense
1344 *
1345 * Query and return the pin's Presence Detect status.
1346 */
1347int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
1348{
1349 u32 sense = snd_hda_pin_sense(codec, nid);
1350 return !!(sense & AC_PINSENSE_PRESENCE);
1351}
1352EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
1353
1232/* 1354/*
1233 * read the current volume to info 1355 * read the current volume to info
1234 * if the cache exists, read the cache value. 1356 * if the cache exists, read the cache value.
@@ -1269,8 +1391,15 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
1269 info->vol[ch] = val; 1391 info->vol[ch] = val;
1270} 1392}
1271 1393
1272/* 1394/**
1273 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. 1395 * snd_hda_codec_amp_read - Read AMP value
1396 * @codec: HD-audio codec
1397 * @nid: NID to read the AMP value
1398 * @ch: channel (left=0 or right=1)
1399 * @direction: #HDA_INPUT or #HDA_OUTPUT
1400 * @index: the index value (only for input direction)
1401 *
1402 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
1274 */ 1403 */
1275int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, 1404int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1276 int direction, int index) 1405 int direction, int index)
@@ -1283,8 +1412,18 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1283} 1412}
1284EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read); 1413EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
1285 1414
1286/* 1415/**
1287 * update the AMP value, mask = bit mask to set, val = the value 1416 * snd_hda_codec_amp_update - update the AMP value
1417 * @codec: HD-audio codec
1418 * @nid: NID to read the AMP value
1419 * @ch: channel (left=0 or right=1)
1420 * @direction: #HDA_INPUT or #HDA_OUTPUT
1421 * @idx: the index value (only for input direction)
1422 * @mask: bit mask to set
1423 * @val: the bits value to set
1424 *
1425 * Update the AMP value with a bit mask.
1426 * Returns 0 if the value is unchanged, 1 if changed.
1288 */ 1427 */
1289int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, 1428int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1290 int direction, int idx, int mask, int val) 1429 int direction, int idx, int mask, int val)
@@ -1303,8 +1442,17 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1303} 1442}
1304EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update); 1443EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
1305 1444
1306/* 1445/**
1307 * update the AMP stereo with the same mask and value 1446 * snd_hda_codec_amp_stereo - update the AMP stereo values
1447 * @codec: HD-audio codec
1448 * @nid: NID to read the AMP value
1449 * @direction: #HDA_INPUT or #HDA_OUTPUT
1450 * @idx: the index value (only for input direction)
1451 * @mask: bit mask to set
1452 * @val: the bits value to set
1453 *
1454 * Update the AMP values like snd_hda_codec_amp_update(), but for a
1455 * stereo widget with the same mask and value.
1308 */ 1456 */
1309int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, 1457int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1310 int direction, int idx, int mask, int val) 1458 int direction, int idx, int mask, int val)
@@ -1318,7 +1466,12 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1318EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo); 1466EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
1319 1467
1320#ifdef SND_HDA_NEEDS_RESUME 1468#ifdef SND_HDA_NEEDS_RESUME
1321/* resume the all amp commands from the cache */ 1469/**
1470 * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
1471 * @codec: HD-audio codec
1472 *
1473 * Resume the all amp commands from the cache.
1474 */
1322void snd_hda_codec_resume_amp(struct hda_codec *codec) 1475void snd_hda_codec_resume_amp(struct hda_codec *codec)
1323{ 1476{
1324 struct hda_amp_info *buffer = codec->amp_cache.buf.list; 1477 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
@@ -1344,7 +1497,12 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
1344EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); 1497EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
1345#endif /* SND_HDA_NEEDS_RESUME */ 1498#endif /* SND_HDA_NEEDS_RESUME */
1346 1499
1347/* volume */ 1500/**
1501 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1502 *
1503 * The control element is supposed to have the private_value field
1504 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1505 */
1348int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, 1506int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1349 struct snd_ctl_elem_info *uinfo) 1507 struct snd_ctl_elem_info *uinfo)
1350{ 1508{
@@ -1400,6 +1558,12 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1400 HDA_AMP_VOLMASK, val); 1558 HDA_AMP_VOLMASK, val);
1401} 1559}
1402 1560
1561/**
1562 * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
1563 *
1564 * The control element is supposed to have the private_value field
1565 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1566 */
1403int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, 1567int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1404 struct snd_ctl_elem_value *ucontrol) 1568 struct snd_ctl_elem_value *ucontrol)
1405{ 1569{
@@ -1419,6 +1583,12 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1419} 1583}
1420EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); 1584EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
1421 1585
1586/**
1587 * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
1588 *
1589 * The control element is supposed to have the private_value field
1590 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1591 */
1422int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, 1592int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1423 struct snd_ctl_elem_value *ucontrol) 1593 struct snd_ctl_elem_value *ucontrol)
1424{ 1594{
@@ -1443,6 +1613,12 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1443} 1613}
1444EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put); 1614EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
1445 1615
1616/**
1617 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
1618 *
1619 * The control element is supposed to have the private_value field
1620 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1621 */
1446int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, 1622int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1447 unsigned int size, unsigned int __user *_tlv) 1623 unsigned int size, unsigned int __user *_tlv)
1448{ 1624{
@@ -1472,8 +1648,16 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1472} 1648}
1473EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv); 1649EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
1474 1650
1475/* 1651/**
1476 * set (static) TLV for virtual master volume; recalculated as max 0dB 1652 * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
1653 * @codec: HD-audio codec
1654 * @nid: NID of a reference widget
1655 * @dir: #HDA_INPUT or #HDA_OUTPUT
1656 * @tlv: TLV data to be stored, at least 4 elements
1657 *
1658 * Set (static) TLV data for a virtual master volume using the AMP caps
1659 * obtained from the reference NID.
1660 * The volume range is recalculated as if the max volume is 0dB.
1477 */ 1661 */
1478void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, 1662void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1479 unsigned int *tlv) 1663 unsigned int *tlv)
@@ -1507,6 +1691,13 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
1507 return snd_ctl_find_id(codec->bus->card, &id); 1691 return snd_ctl_find_id(codec->bus->card, &id);
1508} 1692}
1509 1693
1694/**
1695 * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
1696 * @codec: HD-audio codec
1697 * @name: ctl id name string
1698 *
1699 * Get the control element with the given id string and IFACE_MIXER.
1700 */
1510struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, 1701struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1511 const char *name) 1702 const char *name)
1512{ 1703{
@@ -1514,30 +1705,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1514} 1705}
1515EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); 1706EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
1516 1707
1517/* Add a control element and assign to the codec */ 1708/**
1518int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) 1709 * snd_hda_ctl-add - Add a control element and assign to the codec
1710 * @codec: HD-audio codec
1711 * @nid: corresponding NID (optional)
1712 * @kctl: the control element to assign
1713 *
1714 * Add the given control element to an array inside the codec instance.
1715 * All control elements belonging to a codec are supposed to be added
1716 * by this function so that a proper clean-up works at the free or
1717 * reconfiguration time.
1718 *
1719 * If non-zero @nid is passed, the NID is assigned to the control element.
1720 * The assignment is shown in the codec proc file.
1721 *
1722 * snd_hda_ctl_add() checks the control subdev id field whether
1723 * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
1724 * bits value is taken as the NID to assign.
1725 */
1726int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
1727 struct snd_kcontrol *kctl)
1519{ 1728{
1520 int err; 1729 int err;
1521 struct snd_kcontrol **knewp; 1730 struct hda_nid_item *item;
1522 1731
1732 if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) {
1733 if (nid == 0)
1734 nid = kctl->id.subdevice & 0xffff;
1735 kctl->id.subdevice = 0;
1736 }
1523 err = snd_ctl_add(codec->bus->card, kctl); 1737 err = snd_ctl_add(codec->bus->card, kctl);
1524 if (err < 0) 1738 if (err < 0)
1525 return err; 1739 return err;
1526 knewp = snd_array_new(&codec->mixers); 1740 item = snd_array_new(&codec->mixers);
1527 if (!knewp) 1741 if (!item)
1528 return -ENOMEM; 1742 return -ENOMEM;
1529 *knewp = kctl; 1743 item->kctl = kctl;
1744 item->nid = nid;
1530 return 0; 1745 return 0;
1531} 1746}
1532EXPORT_SYMBOL_HDA(snd_hda_ctl_add); 1747EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
1533 1748
1534/* Clear all controls assigned to the given codec */ 1749/**
1750 * snd_hda_ctls_clear - Clear all controls assigned to the given codec
1751 * @codec: HD-audio codec
1752 */
1535void snd_hda_ctls_clear(struct hda_codec *codec) 1753void snd_hda_ctls_clear(struct hda_codec *codec)
1536{ 1754{
1537 int i; 1755 int i;
1538 struct snd_kcontrol **kctls = codec->mixers.list; 1756 struct hda_nid_item *items = codec->mixers.list;
1539 for (i = 0; i < codec->mixers.used; i++) 1757 for (i = 0; i < codec->mixers.used; i++)
1540 snd_ctl_remove(codec->bus->card, kctls[i]); 1758 snd_ctl_remove(codec->bus->card, items[i].kctl);
1541 snd_array_free(&codec->mixers); 1759 snd_array_free(&codec->mixers);
1542} 1760}
1543 1761
@@ -1563,6 +1781,16 @@ static void hda_unlock_devices(struct snd_card *card)
1563 spin_unlock(&card->files_lock); 1781 spin_unlock(&card->files_lock);
1564} 1782}
1565 1783
1784/**
1785 * snd_hda_codec_reset - Clear all objects assigned to the codec
1786 * @codec: HD-audio codec
1787 *
1788 * This frees the all PCM and control elements assigned to the codec, and
1789 * clears the caches and restores the pin default configurations.
1790 *
1791 * When a device is being used, it returns -EBSY. If successfully freed,
1792 * returns zero.
1793 */
1566int snd_hda_codec_reset(struct hda_codec *codec) 1794int snd_hda_codec_reset(struct hda_codec *codec)
1567{ 1795{
1568 struct snd_card *card = codec->bus->card; 1796 struct snd_card *card = codec->bus->card;
@@ -1626,7 +1854,22 @@ int snd_hda_codec_reset(struct hda_codec *codec)
1626 return 0; 1854 return 0;
1627} 1855}
1628 1856
1629/* create a virtual master control and add slaves */ 1857/**
1858 * snd_hda_add_vmaster - create a virtual master control and add slaves
1859 * @codec: HD-audio codec
1860 * @name: vmaster control name
1861 * @tlv: TLV data (optional)
1862 * @slaves: slave control names (optional)
1863 *
1864 * Create a virtual master control with the given name. The TLV data
1865 * must be either NULL or a valid data.
1866 *
1867 * @slaves is a NULL-terminated array of strings, each of which is a
1868 * slave control name. All controls with these names are assigned to
1869 * the new virtual master control.
1870 *
1871 * This function returns zero if successful or a negative error code.
1872 */
1630int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 1873int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1631 unsigned int *tlv, const char **slaves) 1874 unsigned int *tlv, const char **slaves)
1632{ 1875{
@@ -1643,7 +1886,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1643 kctl = snd_ctl_make_virtual_master(name, tlv); 1886 kctl = snd_ctl_make_virtual_master(name, tlv);
1644 if (!kctl) 1887 if (!kctl)
1645 return -ENOMEM; 1888 return -ENOMEM;
1646 err = snd_hda_ctl_add(codec, kctl); 1889 err = snd_hda_ctl_add(codec, 0, kctl);
1647 if (err < 0) 1890 if (err < 0)
1648 return err; 1891 return err;
1649 1892
@@ -1668,7 +1911,12 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1668} 1911}
1669EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); 1912EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
1670 1913
1671/* switch */ 1914/**
1915 * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
1916 *
1917 * The control element is supposed to have the private_value field
1918 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1919 */
1672int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, 1920int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1673 struct snd_ctl_elem_info *uinfo) 1921 struct snd_ctl_elem_info *uinfo)
1674{ 1922{
@@ -1682,6 +1930,12 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1682} 1930}
1683EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info); 1931EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
1684 1932
1933/**
1934 * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
1935 *
1936 * The control element is supposed to have the private_value field
1937 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1938 */
1685int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, 1939int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1686 struct snd_ctl_elem_value *ucontrol) 1940 struct snd_ctl_elem_value *ucontrol)
1687{ 1941{
@@ -1702,6 +1956,12 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1702} 1956}
1703EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get); 1957EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
1704 1958
1959/**
1960 * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
1961 *
1962 * The control element is supposed to have the private_value field
1963 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1964 */
1705int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, 1965int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1706 struct snd_ctl_elem_value *ucontrol) 1966 struct snd_ctl_elem_value *ucontrol)
1707{ 1967{
@@ -1733,6 +1993,25 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1733} 1993}
1734EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); 1994EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
1735 1995
1996#ifdef CONFIG_SND_HDA_INPUT_BEEP
1997/**
1998 * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch
1999 *
2000 * This function calls snd_hda_enable_beep_device(), which behaves differently
2001 * depending on beep_mode option.
2002 */
2003int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
2004 struct snd_ctl_elem_value *ucontrol)
2005{
2006 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2007 long *valp = ucontrol->value.integer.value;
2008
2009 snd_hda_enable_beep_device(codec, *valp);
2010 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2011}
2012EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
2013#endif /* CONFIG_SND_HDA_INPUT_BEEP */
2014
1736/* 2015/*
1737 * bound volume controls 2016 * bound volume controls
1738 * 2017 *
@@ -1742,6 +2021,12 @@ EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
1742#define AMP_VAL_IDX_SHIFT 19 2021#define AMP_VAL_IDX_SHIFT 19
1743#define AMP_VAL_IDX_MASK (0x0f<<19) 2022#define AMP_VAL_IDX_MASK (0x0f<<19)
1744 2023
2024/**
2025 * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
2026 *
2027 * The control element is supposed to have the private_value field
2028 * set up via HDA_BIND_MUTE*() macros.
2029 */
1745int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, 2030int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1746 struct snd_ctl_elem_value *ucontrol) 2031 struct snd_ctl_elem_value *ucontrol)
1747{ 2032{
@@ -1759,6 +2044,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1759} 2044}
1760EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get); 2045EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
1761 2046
2047/**
2048 * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
2049 *
2050 * The control element is supposed to have the private_value field
2051 * set up via HDA_BIND_MUTE*() macros.
2052 */
1762int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, 2053int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1763 struct snd_ctl_elem_value *ucontrol) 2054 struct snd_ctl_elem_value *ucontrol)
1764{ 2055{
@@ -1783,8 +2074,11 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1783} 2074}
1784EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put); 2075EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
1785 2076
1786/* 2077/**
1787 * generic bound volume/swtich controls 2078 * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
2079 *
2080 * The control element is supposed to have the private_value field
2081 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
1788 */ 2082 */
1789int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, 2083int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1790 struct snd_ctl_elem_info *uinfo) 2084 struct snd_ctl_elem_info *uinfo)
@@ -1803,6 +2097,12 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1803} 2097}
1804EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info); 2098EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
1805 2099
2100/**
2101 * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
2102 *
2103 * The control element is supposed to have the private_value field
2104 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2105 */
1806int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, 2106int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1807 struct snd_ctl_elem_value *ucontrol) 2107 struct snd_ctl_elem_value *ucontrol)
1808{ 2108{
@@ -1820,6 +2120,12 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1820} 2120}
1821EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get); 2121EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
1822 2122
2123/**
2124 * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
2125 *
2126 * The control element is supposed to have the private_value field
2127 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2128 */
1823int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, 2129int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1824 struct snd_ctl_elem_value *ucontrol) 2130 struct snd_ctl_elem_value *ucontrol)
1825{ 2131{
@@ -1843,6 +2149,12 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1843} 2149}
1844EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put); 2150EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
1845 2151
2152/**
2153 * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
2154 *
2155 * The control element is supposed to have the private_value field
2156 * set up via HDA_BIND_VOL() macro.
2157 */
1846int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, 2158int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1847 unsigned int size, unsigned int __user *tlv) 2159 unsigned int size, unsigned int __user *tlv)
1848{ 2160{
@@ -2126,7 +2438,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
2126 return -ENOMEM; 2438 return -ENOMEM;
2127 kctl->id.index = idx; 2439 kctl->id.index = idx;
2128 kctl->private_value = nid; 2440 kctl->private_value = nid;
2129 err = snd_hda_ctl_add(codec, kctl); 2441 err = snd_hda_ctl_add(codec, nid, kctl);
2130 if (err < 0) 2442 if (err < 0)
2131 return err; 2443 return err;
2132 } 2444 }
@@ -2165,14 +2477,19 @@ static struct snd_kcontrol_new spdif_share_sw = {
2165 .put = spdif_share_sw_put, 2477 .put = spdif_share_sw_put,
2166}; 2478};
2167 2479
2480/**
2481 * snd_hda_create_spdif_share_sw - create Default PCM switch
2482 * @codec: the HDA codec
2483 * @mout: multi-out instance
2484 */
2168int snd_hda_create_spdif_share_sw(struct hda_codec *codec, 2485int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2169 struct hda_multi_out *mout) 2486 struct hda_multi_out *mout)
2170{ 2487{
2171 if (!mout->dig_out_nid) 2488 if (!mout->dig_out_nid)
2172 return 0; 2489 return 0;
2173 /* ATTENTION: here mout is passed as private_data, instead of codec */ 2490 /* ATTENTION: here mout is passed as private_data, instead of codec */
2174 return snd_hda_ctl_add(codec, 2491 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2175 snd_ctl_new1(&spdif_share_sw, mout)); 2492 snd_ctl_new1(&spdif_share_sw, mout));
2176} 2493}
2177EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw); 2494EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
2178 2495
@@ -2276,7 +2593,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
2276 if (!kctl) 2593 if (!kctl)
2277 return -ENOMEM; 2594 return -ENOMEM;
2278 kctl->private_value = nid; 2595 kctl->private_value = nid;
2279 err = snd_hda_ctl_add(codec, kctl); 2596 err = snd_hda_ctl_add(codec, nid, kctl);
2280 if (err < 0) 2597 if (err < 0)
2281 return err; 2598 return err;
2282 } 2599 }
@@ -2332,7 +2649,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2332} 2649}
2333EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); 2650EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
2334 2651
2335/* resume the all commands from the cache */ 2652/**
2653 * snd_hda_codec_resume_cache - Resume the all commands from the cache
2654 * @codec: HD-audio codec
2655 *
2656 * Execute all verbs recorded in the command caches to resume.
2657 */
2336void snd_hda_codec_resume_cache(struct hda_codec *codec) 2658void snd_hda_codec_resume_cache(struct hda_codec *codec)
2337{ 2659{
2338 struct hda_cache_head *buffer = codec->cmd_cache.buf.list; 2660 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
@@ -2452,9 +2774,11 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
2452 codec->afg ? codec->afg : codec->mfg, 2774 codec->afg ? codec->afg : codec->mfg,
2453 AC_PWRST_D3); 2775 AC_PWRST_D3);
2454#ifdef CONFIG_SND_HDA_POWER_SAVE 2776#ifdef CONFIG_SND_HDA_POWER_SAVE
2777 snd_hda_update_power_acct(codec);
2455 cancel_delayed_work(&codec->power_work); 2778 cancel_delayed_work(&codec->power_work);
2456 codec->power_on = 0; 2779 codec->power_on = 0;
2457 codec->power_transition = 0; 2780 codec->power_transition = 0;
2781 codec->power_jiffies = jiffies;
2458#endif 2782#endif
2459} 2783}
2460 2784
@@ -2756,8 +3080,12 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
2756} 3080}
2757 3081
2758/** 3082/**
2759 * snd_hda_is_supported_format - check whether the given node supports 3083 * snd_hda_is_supported_format - Check the validity of the format
2760 * the format val 3084 * @codec: HD-audio codec
3085 * @nid: NID to check
3086 * @format: the HD-audio format value to check
3087 *
3088 * Check whether the given node supports the format value.
2761 * 3089 *
2762 * Returns 1 if supported, 0 if not. 3090 * Returns 1 if supported, 0 if not.
2763 */ 3091 */
@@ -2877,51 +3205,36 @@ static int set_pcm_default_values(struct hda_codec *codec,
2877 return 0; 3205 return 0;
2878} 3206}
2879 3207
3208/* global */
3209const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
3210 "Audio", "SPDIF", "HDMI", "Modem"
3211};
3212
2880/* 3213/*
2881 * get the empty PCM device number to assign 3214 * get the empty PCM device number to assign
2882 */ 3215 */
2883static int get_empty_pcm_device(struct hda_bus *bus, int type) 3216static int get_empty_pcm_device(struct hda_bus *bus, int type)
2884{ 3217{
2885 static const char *dev_name[HDA_PCM_NTYPES] = { 3218 /* audio device indices; not linear to keep compatibility */
2886 "Audio", "SPDIF", "HDMI", "Modem" 3219 static int audio_idx[HDA_PCM_NTYPES][5] = {
2887 }; 3220 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
2888 /* starting device index for each PCM type */ 3221 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
2889 static int dev_idx[HDA_PCM_NTYPES] = { 3222 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
2890 [HDA_PCM_TYPE_AUDIO] = 0, 3223 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
2891 [HDA_PCM_TYPE_SPDIF] = 1,
2892 [HDA_PCM_TYPE_HDMI] = 3,
2893 [HDA_PCM_TYPE_MODEM] = 6
2894 }; 3224 };
2895 /* normal audio device indices; not linear to keep compatibility */ 3225 int i;
2896 static int audio_idx[4] = { 0, 2, 4, 5 }; 3226
2897 int i, dev; 3227 if (type >= HDA_PCM_NTYPES) {
2898
2899 switch (type) {
2900 case HDA_PCM_TYPE_AUDIO:
2901 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2902 dev = audio_idx[i];
2903 if (!test_bit(dev, bus->pcm_dev_bits))
2904 goto ok;
2905 }
2906 snd_printk(KERN_WARNING "Too many audio devices\n");
2907 return -EAGAIN;
2908 case HDA_PCM_TYPE_SPDIF:
2909 case HDA_PCM_TYPE_HDMI:
2910 case HDA_PCM_TYPE_MODEM:
2911 dev = dev_idx[type];
2912 if (test_bit(dev, bus->pcm_dev_bits)) {
2913 snd_printk(KERN_WARNING "%s already defined\n",
2914 dev_name[type]);
2915 return -EAGAIN;
2916 }
2917 break;
2918 default:
2919 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); 3228 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2920 return -EINVAL; 3229 return -EINVAL;
2921 } 3230 }
2922 ok: 3231
2923 set_bit(dev, bus->pcm_dev_bits); 3232 for (i = 0; audio_idx[type][i] >= 0 ; i++)
2924 return dev; 3233 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
3234 return audio_idx[type][i];
3235
3236 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
3237 return -EAGAIN;
2925} 3238}
2926 3239
2927/* 3240/*
@@ -3159,14 +3472,14 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3159 */ 3472 */
3160int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) 3473int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
3161{ 3474{
3162 int err; 3475 int err;
3163 3476
3164 for (; knew->name; knew++) { 3477 for (; knew->name; knew++) {
3165 struct snd_kcontrol *kctl; 3478 struct snd_kcontrol *kctl;
3166 kctl = snd_ctl_new1(knew, codec); 3479 kctl = snd_ctl_new1(knew, codec);
3167 if (!kctl) 3480 if (!kctl)
3168 return -ENOMEM; 3481 return -ENOMEM;
3169 err = snd_hda_ctl_add(codec, kctl); 3482 err = snd_hda_ctl_add(codec, 0, kctl);
3170 if (err < 0) { 3483 if (err < 0) {
3171 if (!codec->addr) 3484 if (!codec->addr)
3172 return err; 3485 return err;
@@ -3174,7 +3487,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
3174 if (!kctl) 3487 if (!kctl)
3175 return -ENOMEM; 3488 return -ENOMEM;
3176 kctl->id.device = codec->addr; 3489 kctl->id.device = codec->addr;
3177 err = snd_hda_ctl_add(codec, kctl); 3490 err = snd_hda_ctl_add(codec, 0, kctl);
3178 if (err < 0) 3491 if (err < 0)
3179 return err; 3492 return err;
3180 } 3493 }
@@ -3207,8 +3520,27 @@ static void hda_keep_power_on(struct hda_codec *codec)
3207{ 3520{
3208 codec->power_count++; 3521 codec->power_count++;
3209 codec->power_on = 1; 3522 codec->power_on = 1;
3523 codec->power_jiffies = jiffies;
3210} 3524}
3211 3525
3526/* update the power on/off account with the current jiffies */
3527void snd_hda_update_power_acct(struct hda_codec *codec)
3528{
3529 unsigned long delta = jiffies - codec->power_jiffies;
3530 if (codec->power_on)
3531 codec->power_on_acct += delta;
3532 else
3533 codec->power_off_acct += delta;
3534 codec->power_jiffies += delta;
3535}
3536
3537/**
3538 * snd_hda_power_up - Power-up the codec
3539 * @codec: HD-audio codec
3540 *
3541 * Increment the power-up counter and power up the hardware really when
3542 * not turned on yet.
3543 */
3212void snd_hda_power_up(struct hda_codec *codec) 3544void snd_hda_power_up(struct hda_codec *codec)
3213{ 3545{
3214 struct hda_bus *bus = codec->bus; 3546 struct hda_bus *bus = codec->bus;
@@ -3217,7 +3549,9 @@ void snd_hda_power_up(struct hda_codec *codec)
3217 if (codec->power_on || codec->power_transition) 3549 if (codec->power_on || codec->power_transition)
3218 return; 3550 return;
3219 3551
3552 snd_hda_update_power_acct(codec);
3220 codec->power_on = 1; 3553 codec->power_on = 1;
3554 codec->power_jiffies = jiffies;
3221 if (bus->ops.pm_notify) 3555 if (bus->ops.pm_notify)
3222 bus->ops.pm_notify(bus); 3556 bus->ops.pm_notify(bus);
3223 hda_call_codec_resume(codec); 3557 hda_call_codec_resume(codec);
@@ -3229,9 +3563,13 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up);
3229#define power_save(codec) \ 3563#define power_save(codec) \
3230 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) 3564 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3231 3565
3232#define power_save(codec) \ 3566/**
3233 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) 3567 * snd_hda_power_down - Power-down the codec
3234 3568 * @codec: HD-audio codec
3569 *
3570 * Decrement the power-up counter and schedules the power-off work if
3571 * the counter rearches to zero.
3572 */
3235void snd_hda_power_down(struct hda_codec *codec) 3573void snd_hda_power_down(struct hda_codec *codec)
3236{ 3574{
3237 --codec->power_count; 3575 --codec->power_count;
@@ -3245,6 +3583,19 @@ void snd_hda_power_down(struct hda_codec *codec)
3245} 3583}
3246EXPORT_SYMBOL_HDA(snd_hda_power_down); 3584EXPORT_SYMBOL_HDA(snd_hda_power_down);
3247 3585
3586/**
3587 * snd_hda_check_amp_list_power - Check the amp list and update the power
3588 * @codec: HD-audio codec
3589 * @check: the object containing an AMP list and the status
3590 * @nid: NID to check / update
3591 *
3592 * Check whether the given NID is in the amp list. If it's in the list,
3593 * check the current AMP status, and update the the power-status according
3594 * to the mute status.
3595 *
3596 * This function is supposed to be set or called from the check_power_status
3597 * patch ops.
3598 */
3248int snd_hda_check_amp_list_power(struct hda_codec *codec, 3599int snd_hda_check_amp_list_power(struct hda_codec *codec,
3249 struct hda_loopback_check *check, 3600 struct hda_loopback_check *check,
3250 hda_nid_t nid) 3601 hda_nid_t nid)
@@ -3286,6 +3637,10 @@ EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
3286/* 3637/*
3287 * Channel mode helper 3638 * Channel mode helper
3288 */ 3639 */
3640
3641/**
3642 * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
3643 */
3289int snd_hda_ch_mode_info(struct hda_codec *codec, 3644int snd_hda_ch_mode_info(struct hda_codec *codec,
3290 struct snd_ctl_elem_info *uinfo, 3645 struct snd_ctl_elem_info *uinfo,
3291 const struct hda_channel_mode *chmode, 3646 const struct hda_channel_mode *chmode,
@@ -3302,6 +3657,9 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
3302} 3657}
3303EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info); 3658EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
3304 3659
3660/**
3661 * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
3662 */
3305int snd_hda_ch_mode_get(struct hda_codec *codec, 3663int snd_hda_ch_mode_get(struct hda_codec *codec,
3306 struct snd_ctl_elem_value *ucontrol, 3664 struct snd_ctl_elem_value *ucontrol,
3307 const struct hda_channel_mode *chmode, 3665 const struct hda_channel_mode *chmode,
@@ -3320,6 +3678,9 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
3320} 3678}
3321EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get); 3679EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
3322 3680
3681/**
3682 * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
3683 */
3323int snd_hda_ch_mode_put(struct hda_codec *codec, 3684int snd_hda_ch_mode_put(struct hda_codec *codec,
3324 struct snd_ctl_elem_value *ucontrol, 3685 struct snd_ctl_elem_value *ucontrol,
3325 const struct hda_channel_mode *chmode, 3686 const struct hda_channel_mode *chmode,
@@ -3344,6 +3705,10 @@ EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
3344/* 3705/*
3345 * input MUX helper 3706 * input MUX helper
3346 */ 3707 */
3708
3709/**
3710 * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
3711 */
3347int snd_hda_input_mux_info(const struct hda_input_mux *imux, 3712int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3348 struct snd_ctl_elem_info *uinfo) 3713 struct snd_ctl_elem_info *uinfo)
3349{ 3714{
@@ -3362,6 +3727,9 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3362} 3727}
3363EXPORT_SYMBOL_HDA(snd_hda_input_mux_info); 3728EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
3364 3729
3730/**
3731 * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
3732 */
3365int snd_hda_input_mux_put(struct hda_codec *codec, 3733int snd_hda_input_mux_put(struct hda_codec *codec,
3366 const struct hda_input_mux *imux, 3734 const struct hda_input_mux *imux,
3367 struct snd_ctl_elem_value *ucontrol, 3735 struct snd_ctl_elem_value *ucontrol,
@@ -3421,8 +3789,29 @@ static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3421 } 3789 }
3422} 3790}
3423 3791
3424/* 3792/**
3425 * open the digital out in the exclusive mode 3793 * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
3794 * @bus: HD-audio bus
3795 */
3796void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3797{
3798 struct hda_codec *codec;
3799
3800 if (!bus)
3801 return;
3802 list_for_each_entry(codec, &bus->codec_list, list) {
3803#ifdef CONFIG_SND_HDA_POWER_SAVE
3804 if (!codec->power_on)
3805 continue;
3806#endif
3807 if (codec->patch_ops.reboot_notify)
3808 codec->patch_ops.reboot_notify(codec);
3809 }
3810}
3811EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
3812
3813/**
3814 * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
3426 */ 3815 */
3427int snd_hda_multi_out_dig_open(struct hda_codec *codec, 3816int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3428 struct hda_multi_out *mout) 3817 struct hda_multi_out *mout)
@@ -3437,6 +3826,9 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3437} 3826}
3438EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open); 3827EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
3439 3828
3829/**
3830 * snd_hda_multi_out_dig_prepare - prepare the digital out stream
3831 */
3440int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, 3832int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3441 struct hda_multi_out *mout, 3833 struct hda_multi_out *mout,
3442 unsigned int stream_tag, 3834 unsigned int stream_tag,
@@ -3450,6 +3842,9 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3450} 3842}
3451EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare); 3843EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
3452 3844
3845/**
3846 * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
3847 */
3453int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, 3848int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3454 struct hda_multi_out *mout) 3849 struct hda_multi_out *mout)
3455{ 3850{
@@ -3460,8 +3855,8 @@ int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3460} 3855}
3461EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup); 3856EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3462 3857
3463/* 3858/**
3464 * release the digital out 3859 * snd_hda_multi_out_dig_close - release the digital out stream
3465 */ 3860 */
3466int snd_hda_multi_out_dig_close(struct hda_codec *codec, 3861int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3467 struct hda_multi_out *mout) 3862 struct hda_multi_out *mout)
@@ -3473,8 +3868,12 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3473} 3868}
3474EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close); 3869EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
3475 3870
3476/* 3871/**
3477 * set up more restrictions for analog out 3872 * snd_hda_multi_out_analog_open - open analog outputs
3873 *
3874 * Open analog outputs and set up the hw-constraints.
3875 * If the digital outputs can be opened as slave, open the digital
3876 * outputs, too.
3478 */ 3877 */
3479int snd_hda_multi_out_analog_open(struct hda_codec *codec, 3878int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3480 struct hda_multi_out *mout, 3879 struct hda_multi_out *mout,
@@ -3519,9 +3918,11 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3519} 3918}
3520EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open); 3919EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
3521 3920
3522/* 3921/**
3523 * set up the i/o for analog out 3922 * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
3524 * when the digital out is available, copy the front out to digital out, too. 3923 *
3924 * Set up the i/o for analog out.
3925 * When the digital out is available, copy the front out to digital out, too.
3525 */ 3926 */
3526int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, 3927int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3527 struct hda_multi_out *mout, 3928 struct hda_multi_out *mout,
@@ -3578,8 +3979,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3578} 3979}
3579EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare); 3980EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
3580 3981
3581/* 3982/**
3582 * clean up the setting for analog out 3983 * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
3583 */ 3984 */
3584int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, 3985int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3585 struct hda_multi_out *mout) 3986 struct hda_multi_out *mout)
@@ -3965,8 +4366,14 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
3965 * generic arrays 4366 * generic arrays
3966 */ 4367 */
3967 4368
3968/* get a new element from the given array 4369/**
3969 * if it exceeds the pre-allocated array size, re-allocate the array 4370 * snd_array_new - get a new element from the given array
4371 * @array: the array object
4372 *
4373 * Get a new element from the given array. If it exceeds the
4374 * pre-allocated array size, re-allocate the array.
4375 *
4376 * Returns NULL if allocation failed.
3970 */ 4377 */
3971void *snd_array_new(struct snd_array *array) 4378void *snd_array_new(struct snd_array *array)
3972{ 4379{
@@ -3990,7 +4397,10 @@ void *snd_array_new(struct snd_array *array)
3990} 4397}
3991EXPORT_SYMBOL_HDA(snd_array_new); 4398EXPORT_SYMBOL_HDA(snd_array_new);
3992 4399
3993/* free the given array elements */ 4400/**
4401 * snd_array_free - free the given array elements
4402 * @array: the array object
4403 */
3994void snd_array_free(struct snd_array *array) 4404void snd_array_free(struct snd_array *array)
3995{ 4405{
3996 kfree(array->list); 4406 kfree(array->list);
@@ -4000,7 +4410,12 @@ void snd_array_free(struct snd_array *array)
4000} 4410}
4001EXPORT_SYMBOL_HDA(snd_array_free); 4411EXPORT_SYMBOL_HDA(snd_array_free);
4002 4412
4003/* 4413/**
4414 * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
4415 * @pcm: PCM caps bits
4416 * @buf: the string buffer to write
4417 * @buflen: the max buffer length
4418 *
4004 * used by hda_proc.c and hda_eld.c 4419 * used by hda_proc.c and hda_eld.c
4005 */ 4420 */
4006void snd_print_pcm_rates(int pcm, char *buf, int buflen) 4421void snd_print_pcm_rates(int pcm, char *buf, int buflen)
@@ -4019,6 +4434,14 @@ void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4019} 4434}
4020EXPORT_SYMBOL_HDA(snd_print_pcm_rates); 4435EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
4021 4436
4437/**
4438 * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
4439 * @pcm: PCM caps bits
4440 * @buf: the string buffer to write
4441 * @buflen: the max buffer length
4442 *
4443 * used by hda_proc.c and hda_eld.c
4444 */
4022void snd_print_pcm_bits(int pcm, char *buf, int buflen) 4445void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4023{ 4446{
4024 static unsigned int bits[] = { 8, 16, 20, 24, 32 }; 4447 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 99552fb5f756..2d627613aea3 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -286,6 +286,10 @@ enum {
286#define AC_PWRST_D1SUP (1<<1) 286#define AC_PWRST_D1SUP (1<<1)
287#define AC_PWRST_D2SUP (1<<2) 287#define AC_PWRST_D2SUP (1<<2)
288#define AC_PWRST_D3SUP (1<<3) 288#define AC_PWRST_D3SUP (1<<3)
289#define AC_PWRST_D3COLDSUP (1<<4)
290#define AC_PWRST_S3D3COLDSUP (1<<29)
291#define AC_PWRST_CLKSTOP (1<<30)
292#define AC_PWRST_EPSS (1U<<31)
289 293
290/* Power state values */ 294/* Power state values */
291#define AC_PWRST_SETTING (0xf<<0) 295#define AC_PWRST_SETTING (0xf<<0)
@@ -674,6 +678,7 @@ struct hda_codec_ops {
674#ifdef CONFIG_SND_HDA_POWER_SAVE 678#ifdef CONFIG_SND_HDA_POWER_SAVE
675 int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); 679 int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
676#endif 680#endif
681 void (*reboot_notify)(struct hda_codec *codec);
677}; 682};
678 683
679/* record for amp information cache */ 684/* record for amp information cache */
@@ -771,6 +776,7 @@ struct hda_codec {
771 776
772 /* beep device */ 777 /* beep device */
773 struct hda_beep *beep; 778 struct hda_beep *beep;
779 unsigned int beep_mode;
774 780
775 /* widget capabilities cache */ 781 /* widget capabilities cache */
776 unsigned int num_nodes; 782 unsigned int num_nodes;
@@ -811,6 +817,9 @@ struct hda_codec {
811 unsigned int power_transition :1; /* power-state in transition */ 817 unsigned int power_transition :1; /* power-state in transition */
812 int power_count; /* current (global) power refcount */ 818 int power_count; /* current (global) power refcount */
813 struct delayed_work power_work; /* delayed task for powerdown */ 819 struct delayed_work power_work; /* delayed task for powerdown */
820 unsigned long power_on_acct;
821 unsigned long power_off_acct;
822 unsigned long power_jiffies;
814#endif 823#endif
815 824
816 /* codec-specific additional proc output */ 825 /* codec-specific additional proc output */
@@ -910,6 +919,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
910 * Misc 919 * Misc
911 */ 920 */
912void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); 921void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
922void snd_hda_bus_reboot_notify(struct hda_bus *bus);
913 923
914/* 924/*
915 * power management 925 * power management
@@ -933,6 +943,7 @@ const char *snd_hda_get_jack_location(u32 cfg);
933void snd_hda_power_up(struct hda_codec *codec); 943void snd_hda_power_up(struct hda_codec *codec);
934void snd_hda_power_down(struct hda_codec *codec); 944void snd_hda_power_down(struct hda_codec *codec);
935#define snd_hda_codec_needs_resume(codec) codec->power_count 945#define snd_hda_codec_needs_resume(codec) codec->power_count
946void snd_hda_update_power_acct(struct hda_codec *codec);
936#else 947#else
937static inline void snd_hda_power_up(struct hda_codec *codec) {} 948static inline void snd_hda_power_up(struct hda_codec *codec) {}
938static inline void snd_hda_power_down(struct hda_codec *codec) {} 949static inline void snd_hda_power_down(struct hda_codec *codec) {}
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 9446a5abea13..4228f2fe5956 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -309,17 +309,12 @@ out_fail:
309 return -EINVAL; 309 return -EINVAL;
310} 310}
311 311
312static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
313{
314 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
315}
316
317static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid) 312static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
318{ 313{
319 int eldv; 314 int eldv;
320 int present; 315 int present;
321 316
322 present = hdmi_present_sense(codec, nid); 317 present = snd_hda_pin_sense(codec, nid);
323 eldv = (present & AC_PINSENSE_ELDV); 318 eldv = (present & AC_PINSENSE_ELDV);
324 present = (present & AC_PINSENSE_PRESENCE); 319 present = (present & AC_PINSENSE_PRESENCE);
325 320
@@ -477,6 +472,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
477 [4 ... 7] = "reserved" 472 [4 ... 7] = "reserved"
478 }; 473 };
479 474
475 snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present);
476 snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid);
480 snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); 477 snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
481 snd_iprintf(buffer, "connection_type\t\t%s\n", 478 snd_iprintf(buffer, "connection_type\t\t%s\n",
482 eld_connection_type_names[e->conn_type]); 479 eld_connection_type_names[e->conn_type]);
@@ -518,7 +515,11 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
518 * monitor_name manufacture_id product_id 515 * monitor_name manufacture_id product_id
519 * eld_version edid_version 516 * eld_version edid_version
520 */ 517 */
521 if (!strcmp(name, "connection_type")) 518 if (!strcmp(name, "monitor_present"))
519 e->monitor_present = val;
520 else if (!strcmp(name, "eld_valid"))
521 e->eld_valid = val;
522 else if (!strcmp(name, "connection_type"))
522 e->conn_type = val; 523 e->conn_type = val;
523 else if (!strcmp(name, "port_id")) 524 else if (!strcmp(name, "port_id"))
524 e->port_id = val; 525 e->port_id = val;
@@ -560,13 +561,14 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
560} 561}
561 562
562 563
563int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld) 564int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
565 int index)
564{ 566{
565 char name[32]; 567 char name[32];
566 struct snd_info_entry *entry; 568 struct snd_info_entry *entry;
567 int err; 569 int err;
568 570
569 snprintf(name, sizeof(name), "eld#%d", codec->addr); 571 snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
570 err = snd_card_proc_new(codec->bus->card, name, &entry); 572 err = snd_card_proc_new(codec->bus->card, name, &entry);
571 if (err < 0) 573 if (err < 0)
572 return err; 574 return err;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index b36f6c5a92df..092c6a7c2ff3 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -727,7 +727,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
727 if (is_loopback) 727 if (is_loopback)
728 add_input_loopback(codec, node->nid, HDA_INPUT, index); 728 add_input_loopback(codec, node->nid, HDA_INPUT, index);
729 snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); 729 snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
730 err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 730 err = snd_hda_ctl_add(codec, node->nid,
731 snd_ctl_new1(&knew, codec));
731 if (err < 0) 732 if (err < 0)
732 return err; 733 return err;
733 created = 1; 734 created = 1;
@@ -737,7 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
737 if (is_loopback) 738 if (is_loopback)
738 add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); 739 add_input_loopback(codec, node->nid, HDA_OUTPUT, 0);
739 snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); 740 snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
740 err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 741 err = snd_hda_ctl_add(codec, node->nid,
742 snd_ctl_new1(&knew, codec));
741 if (err < 0) 743 if (err < 0)
742 return err; 744 return err;
743 created = 1; 745 created = 1;
@@ -751,7 +753,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
751 (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { 753 (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
752 knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); 754 knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
753 snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); 755 snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
754 err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 756 err = snd_hda_ctl_add(codec, node->nid,
757 snd_ctl_new1(&knew, codec));
755 if (err < 0) 758 if (err < 0)
756 return err; 759 return err;
757 created = 1; 760 created = 1;
@@ -759,7 +762,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
759 (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { 762 (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
760 knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); 763 knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
761 snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); 764 snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
762 err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 765 err = snd_hda_ctl_add(codec, node->nid,
766 snd_ctl_new1(&knew, codec));
763 if (err < 0) 767 if (err < 0)
764 return err; 768 return err;
765 created = 1; 769 created = 1;
@@ -857,7 +861,7 @@ static int build_input_controls(struct hda_codec *codec)
857 } 861 }
858 862
859 /* create input MUX if multiple sources are available */ 863 /* create input MUX if multiple sources are available */
860 err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec)); 864 err = snd_hda_ctl_add(codec, 0, snd_ctl_new1(&cap_sel, codec));
861 if (err < 0) 865 if (err < 0)
862 return err; 866 return err;
863 867
@@ -875,7 +879,8 @@ static int build_input_controls(struct hda_codec *codec)
875 HDA_CODEC_VOLUME(name, adc_node->nid, 879 HDA_CODEC_VOLUME(name, adc_node->nid,
876 spec->input_mux.items[i].index, 880 spec->input_mux.items[i].index,
877 HDA_INPUT); 881 HDA_INPUT);
878 err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 882 err = snd_hda_ctl_add(codec, adc_node->nid,
883 snd_ctl_new1(&knew, codec));
879 if (err < 0) 884 if (err < 0)
880 return err; 885 return err;
881 } 886 }
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index cc24e6721d74..d24328661c6a 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -154,6 +154,44 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
154 return 0; 154 return 0;
155} 155}
156 156
157#ifdef CONFIG_SND_HDA_POWER_SAVE
158static ssize_t power_on_acct_show(struct device *dev,
159 struct device_attribute *attr,
160 char *buf)
161{
162 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
163 struct hda_codec *codec = hwdep->private_data;
164 snd_hda_update_power_acct(codec);
165 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
166}
167
168static ssize_t power_off_acct_show(struct device *dev,
169 struct device_attribute *attr,
170 char *buf)
171{
172 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
173 struct hda_codec *codec = hwdep->private_data;
174 snd_hda_update_power_acct(codec);
175 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
176}
177
178static struct device_attribute power_attrs[] = {
179 __ATTR_RO(power_on_acct),
180 __ATTR_RO(power_off_acct),
181};
182
183int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
184{
185 struct snd_hwdep *hwdep = codec->hwdep;
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(power_attrs); i++)
189 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
190 hwdep->device, &power_attrs[i]);
191 return 0;
192}
193#endif /* CONFIG_SND_HDA_POWER_SAVE */
194
157#ifdef CONFIG_SND_HDA_RECONFIG 195#ifdef CONFIG_SND_HDA_RECONFIG
158 196
159/* 197/*
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 6517f589d01d..d822bfc6cad6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -60,10 +60,14 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
60static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; 60static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
61static int probe_only[SNDRV_CARDS]; 61static int probe_only[SNDRV_CARDS];
62static int single_cmd; 62static int single_cmd;
63static int enable_msi; 63static int enable_msi = -1;
64#ifdef CONFIG_SND_HDA_PATCH_LOADER 64#ifdef CONFIG_SND_HDA_PATCH_LOADER
65static char *patch[SNDRV_CARDS]; 65static char *patch[SNDRV_CARDS];
66#endif 66#endif
67#ifdef CONFIG_SND_HDA_INPUT_BEEP
68static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
69 CONFIG_SND_HDA_INPUT_BEEP_MODE};
70#endif
67 71
68module_param_array(index, int, NULL, 0444); 72module_param_array(index, int, NULL, 0444);
69MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); 73MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -91,6 +95,11 @@ MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
91module_param_array(patch, charp, NULL, 0444); 95module_param_array(patch, charp, NULL, 0444);
92MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); 96MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
93#endif 97#endif
98#ifdef CONFIG_SND_HDA_INPUT_BEEP
99module_param_array(beep_mode, int, NULL, 0444);
100MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
101 "(0=off, 1=on, 2=mute switch on/off) (default=1).");
102#endif
94 103
95#ifdef CONFIG_SND_HDA_POWER_SAVE 104#ifdef CONFIG_SND_HDA_POWER_SAVE
96static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; 105static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
@@ -404,6 +413,7 @@ struct azx {
404 unsigned short codec_mask; 413 unsigned short codec_mask;
405 int codec_probe_mask; /* copied from probe_mask option */ 414 int codec_probe_mask; /* copied from probe_mask option */
406 struct hda_bus *bus; 415 struct hda_bus *bus;
416 unsigned int beep_mode;
407 417
408 /* CORB/RIRB */ 418 /* CORB/RIRB */
409 struct azx_rb corb; 419 struct azx_rb corb;
@@ -677,6 +687,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
677 } 687 }
678 } 688 }
679 689
690 if (!chip->polling_mode) {
691 snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
692 "switching to polling mode: last cmd=0x%08x\n",
693 chip->last_cmd[addr]);
694 chip->polling_mode = 1;
695 goto again;
696 }
697
680 if (chip->msi) { 698 if (chip->msi) {
681 snd_printk(KERN_WARNING SFX "No response from codec, " 699 snd_printk(KERN_WARNING SFX "No response from codec, "
682 "disabling MSI: last cmd=0x%08x\n", 700 "disabling MSI: last cmd=0x%08x\n",
@@ -692,14 +710,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
692 goto again; 710 goto again;
693 } 711 }
694 712
695 if (!chip->polling_mode) {
696 snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
697 "switching to polling mode: last cmd=0x%08x\n",
698 chip->last_cmd[addr]);
699 chip->polling_mode = 1;
700 goto again;
701 }
702
703 if (chip->probing) { 713 if (chip->probing) {
704 /* If this critical timeout happens during the codec probing 714 /* If this critical timeout happens during the codec probing
705 * phase, this is likely an access to a non-existing codec 715 * phase, this is likely an access to a non-existing codec
@@ -1404,6 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
1404 err = snd_hda_codec_new(chip->bus, c, &codec); 1414 err = snd_hda_codec_new(chip->bus, c, &codec);
1405 if (err < 0) 1415 if (err < 0)
1406 continue; 1416 continue;
1417 codec->beep_mode = chip->beep_mode;
1407 codecs++; 1418 codecs++;
1408 } 1419 }
1409 } 1420 }
@@ -2154,6 +2165,7 @@ static int azx_resume(struct pci_dev *pci)
2154static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) 2165static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
2155{ 2166{
2156 struct azx *chip = container_of(nb, struct azx, reboot_notifier); 2167 struct azx *chip = container_of(nb, struct azx, reboot_notifier);
2168 snd_hda_bus_reboot_notify(chip->bus);
2157 azx_stop_chip(chip); 2169 azx_stop_chip(chip);
2158 return NOTIFY_OK; 2170 return NOTIFY_OK;
2159} 2171}
@@ -2221,7 +2233,9 @@ static int azx_dev_free(struct snd_device *device)
2221static struct snd_pci_quirk position_fix_list[] __devinitdata = { 2233static struct snd_pci_quirk position_fix_list[] __devinitdata = {
2222 SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), 2234 SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
2223 SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), 2235 SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
2236 SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
2224 SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), 2237 SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
2238 SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
2225 {} 2239 {}
2226}; 2240};
2227 2241
@@ -2304,11 +2318,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
2304} 2318}
2305 2319
2306/* 2320/*
2307 * white-list for enable_msi 2321 * white/black-list for enable_msi
2308 */ 2322 */
2309static struct snd_pci_quirk msi_white_list[] __devinitdata = { 2323static struct snd_pci_quirk msi_black_list[] __devinitdata = {
2310 SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1),
2311 SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1),
2312 {} 2324 {}
2313}; 2325};
2314 2326
@@ -2316,10 +2328,12 @@ static void __devinit check_msi(struct azx *chip)
2316{ 2328{
2317 const struct snd_pci_quirk *q; 2329 const struct snd_pci_quirk *q;
2318 2330
2319 chip->msi = enable_msi; 2331 if (enable_msi >= 0) {
2320 if (chip->msi) 2332 chip->msi = !!enable_msi;
2321 return; 2333 return;
2322 q = snd_pci_quirk_lookup(chip->pci, msi_white_list); 2334 }
2335 chip->msi = 1; /* enable MSI as default */
2336 q = snd_pci_quirk_lookup(chip->pci, msi_black_list);
2323 if (q) { 2337 if (q) {
2324 printk(KERN_INFO 2338 printk(KERN_INFO
2325 "hda_intel: msi for device %04x:%04x set to %d\n", 2339 "hda_intel: msi for device %04x:%04x set to %d\n",
@@ -2578,6 +2592,10 @@ static int __devinit azx_probe(struct pci_dev *pci,
2578 goto out_free; 2592 goto out_free;
2579 card->private_data = chip; 2593 card->private_data = chip;
2580 2594
2595#ifdef CONFIG_SND_HDA_INPUT_BEEP
2596 chip->beep_mode = beep_mode[dev];
2597#endif
2598
2581 /* create codec instances */ 2599 /* create codec instances */
2582 err = azx_codec_create(chip, model[dev]); 2600 err = azx_codec_create(chip, model[dev]);
2583 if (err < 0) 2601 if (err < 0)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 5f1dcc59002b..5778ae882b83 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -23,6 +23,15 @@
23#ifndef __SOUND_HDA_LOCAL_H 23#ifndef __SOUND_HDA_LOCAL_H
24#define __SOUND_HDA_LOCAL_H 24#define __SOUND_HDA_LOCAL_H
25 25
26/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
27 * the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
28 * snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
29 *
30 * Note that the subdevice field is cleared again before the real registration
31 * in snd_hda_ctl_add(), so that this value won't appear in the outside.
32 */
33#define HDA_SUBDEV_NID_FLAG (1U << 31)
34
26/* 35/*
27 * for mixer controls 36 * for mixer controls
28 */ 37 */
@@ -33,6 +42,7 @@
33/* mono volume with index (index=0,1,...) (channel=1,2) */ 42/* mono volume with index (index=0,1,...) (channel=1,2) */
34#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 43#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
35 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 44 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
45 .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
36 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 46 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
37 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 47 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
38 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ 48 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
@@ -53,6 +63,7 @@
53/* mono mute switch with index (index=0,1,...) (channel=1,2) */ 63/* mono mute switch with index (index=0,1,...) (channel=1,2) */
54#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 64#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
55 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 65 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
66 .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
56 .info = snd_hda_mixer_amp_switch_info, \ 67 .info = snd_hda_mixer_amp_switch_info, \
57 .get = snd_hda_mixer_amp_switch_get, \ 68 .get = snd_hda_mixer_amp_switch_get, \
58 .put = snd_hda_mixer_amp_switch_put, \ 69 .put = snd_hda_mixer_amp_switch_put, \
@@ -66,6 +77,28 @@
66/* stereo mute switch */ 77/* stereo mute switch */
67#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ 78#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
68 HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) 79 HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
80#ifdef CONFIG_SND_HDA_INPUT_BEEP
81/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
82#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
83 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
84 .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
85 .info = snd_hda_mixer_amp_switch_info, \
86 .get = snd_hda_mixer_amp_switch_get, \
87 .put = snd_hda_mixer_amp_switch_put_beep, \
88 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
89#else
90/* no digital beep - just the standard one */
91#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
92 HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir)
93#endif /* CONFIG_SND_HDA_INPUT_BEEP */
94/* special beep mono mute switch */
95#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
96 HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction)
97/* special beep stereo mute switch */
98#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
99 HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction)
100
101extern const char *snd_hda_pcm_type_name[];
69 102
70int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, 103int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
71 struct snd_ctl_elem_info *uinfo); 104 struct snd_ctl_elem_info *uinfo);
@@ -81,6 +114,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
81 struct snd_ctl_elem_value *ucontrol); 114 struct snd_ctl_elem_value *ucontrol);
82int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, 115int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
83 struct snd_ctl_elem_value *ucontrol); 116 struct snd_ctl_elem_value *ucontrol);
117#ifdef CONFIG_SND_HDA_INPUT_BEEP
118int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
119 struct snd_ctl_elem_value *ucontrol);
120#endif
84/* lowlevel accessor with caching; use carefully */ 121/* lowlevel accessor with caching; use carefully */
85int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, 122int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
86 int direction, int index); 123 int direction, int index);
@@ -424,8 +461,16 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
424int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, 461int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
425 unsigned int caps); 462 unsigned int caps);
426u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); 463u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
464u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
465int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
427 466
428int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); 467struct hda_nid_item {
468 struct snd_kcontrol *kctl;
469 hda_nid_t nid;
470};
471
472int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
473 struct snd_kcontrol *kctl);
429void snd_hda_ctls_clear(struct hda_codec *codec); 474void snd_hda_ctls_clear(struct hda_codec *codec);
430 475
431/* 476/*
@@ -437,6 +482,15 @@ int snd_hda_create_hwdep(struct hda_codec *codec);
437static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } 482static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
438#endif 483#endif
439 484
485#if defined(CONFIG_SND_HDA_POWER_SAVE) && defined(CONFIG_SND_HDA_HWDEP)
486int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec);
487#else
488static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
489{
490 return 0;
491}
492#endif
493
440#ifdef CONFIG_SND_HDA_RECONFIG 494#ifdef CONFIG_SND_HDA_RECONFIG
441int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); 495int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
442#else 496#else
@@ -490,7 +544,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
490 * AMP control callbacks 544 * AMP control callbacks
491 */ 545 */
492/* retrieve parameters from private_value */ 546/* retrieve parameters from private_value */
493#define get_amp_nid(kc) ((kc)->private_value & 0xffff) 547#define get_amp_nid_(pv) ((pv) & 0xffff)
548#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
494#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) 549#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
495#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) 550#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
496#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) 551#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
@@ -516,9 +571,11 @@ struct cea_sad {
516 * ELD: EDID Like Data 571 * ELD: EDID Like Data
517 */ 572 */
518struct hdmi_eld { 573struct hdmi_eld {
574 bool monitor_present;
575 bool eld_valid;
519 int eld_size; 576 int eld_size;
520 int baseline_len; 577 int baseline_len;
521 int eld_ver; /* (eld_ver == 0) indicates invalid ELD */ 578 int eld_ver;
522 int cea_edid_ver; 579 int cea_edid_ver;
523 char monitor_name[ELD_MAX_MNL + 1]; 580 char monitor_name[ELD_MAX_MNL + 1];
524 int manufacture_id; 581 int manufacture_id;
@@ -541,11 +598,13 @@ int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
541void snd_hdmi_show_eld(struct hdmi_eld *eld); 598void snd_hdmi_show_eld(struct hdmi_eld *eld);
542 599
543#ifdef CONFIG_PROC_FS 600#ifdef CONFIG_PROC_FS
544int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld); 601int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
602 int index);
545void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld); 603void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld);
546#else 604#else
547static inline int snd_hda_eld_proc_new(struct hda_codec *codec, 605static inline int snd_hda_eld_proc_new(struct hda_codec *codec,
548 struct hdmi_eld *eld) 606 struct hdmi_eld *eld,
607 int index)
549{ 608{
550 return 0; 609 return 0;
551} 610}
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 95f24e4729f8..09476fc1ab64 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -26,6 +26,21 @@
26#include "hda_codec.h" 26#include "hda_codec.h"
27#include "hda_local.h" 27#include "hda_local.h"
28 28
29static char *bits_names(unsigned int bits, char *names[], int size)
30{
31 int i, n;
32 static char buf[128];
33
34 for (i = 0, n = 0; i < size; i++) {
35 if (bits & (1U<<i) && names[i])
36 n += snprintf(buf + n, sizeof(buf) - n, " %s",
37 names[i]);
38 }
39 buf[n] = '\0';
40
41 return buf;
42}
43
29static const char *get_wid_type_name(unsigned int wid_value) 44static const char *get_wid_type_name(unsigned int wid_value)
30{ 45{
31 static char *names[16] = { 46 static char *names[16] = {
@@ -46,6 +61,41 @@ static const char *get_wid_type_name(unsigned int wid_value)
46 return "UNKNOWN Widget"; 61 return "UNKNOWN Widget";
47} 62}
48 63
64static void print_nid_mixers(struct snd_info_buffer *buffer,
65 struct hda_codec *codec, hda_nid_t nid)
66{
67 int i;
68 struct hda_nid_item *items = codec->mixers.list;
69 struct snd_kcontrol *kctl;
70 for (i = 0; i < codec->mixers.used; i++) {
71 if (items[i].nid == nid) {
72 kctl = items[i].kctl;
73 snd_iprintf(buffer,
74 " Control: name=\"%s\", index=%i, device=%i\n",
75 kctl->id.name, kctl->id.index, kctl->id.device);
76 }
77 }
78}
79
80static void print_nid_pcms(struct snd_info_buffer *buffer,
81 struct hda_codec *codec, hda_nid_t nid)
82{
83 int pcm, type;
84 struct hda_pcm *cpcm;
85 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
86 cpcm = &codec->pcm_info[pcm];
87 for (type = 0; type < 2; type++) {
88 if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
89 continue;
90 snd_iprintf(buffer, " Device: name=\"%s\", "
91 "type=\"%s\", device=%i\n",
92 cpcm->name,
93 snd_hda_pcm_type_name[cpcm->pcm_type],
94 cpcm->pcm->device);
95 }
96 }
97}
98
49static void print_amp_caps(struct snd_info_buffer *buffer, 99static void print_amp_caps(struct snd_info_buffer *buffer,
50 struct hda_codec *codec, hda_nid_t nid, int dir) 100 struct hda_codec *codec, hda_nid_t nid, int dir)
51{ 101{
@@ -363,8 +413,24 @@ static const char *get_pwr_state(u32 state)
363static void print_power_state(struct snd_info_buffer *buffer, 413static void print_power_state(struct snd_info_buffer *buffer,
364 struct hda_codec *codec, hda_nid_t nid) 414 struct hda_codec *codec, hda_nid_t nid)
365{ 415{
416 static char *names[] = {
417 [ilog2(AC_PWRST_D0SUP)] = "D0",
418 [ilog2(AC_PWRST_D1SUP)] = "D1",
419 [ilog2(AC_PWRST_D2SUP)] = "D2",
420 [ilog2(AC_PWRST_D3SUP)] = "D3",
421 [ilog2(AC_PWRST_D3COLDSUP)] = "D3cold",
422 [ilog2(AC_PWRST_S3D3COLDSUP)] = "S3D3cold",
423 [ilog2(AC_PWRST_CLKSTOP)] = "CLKSTOP",
424 [ilog2(AC_PWRST_EPSS)] = "EPSS",
425 };
426
427 int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE);
366 int pwr = snd_hda_codec_read(codec, nid, 0, 428 int pwr = snd_hda_codec_read(codec, nid, 0,
367 AC_VERB_GET_POWER_STATE, 0); 429 AC_VERB_GET_POWER_STATE, 0);
430 if (sup)
431 snd_iprintf(buffer, " Power states: %s\n",
432 bits_names(sup, names, ARRAY_SIZE(names)));
433
368 snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", 434 snd_iprintf(buffer, " Power: setting=%s, actual=%s\n",
369 get_pwr_state(pwr & AC_PWRST_SETTING), 435 get_pwr_state(pwr & AC_PWRST_SETTING),
370 get_pwr_state((pwr & AC_PWRST_ACTUAL) >> 436 get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
@@ -457,6 +523,7 @@ static void print_gpio(struct snd_info_buffer *buffer,
457 (data & (1<<i)) ? 1 : 0, 523 (data & (1<<i)) ? 1 : 0,
458 (unsol & (1<<i)) ? 1 : 0); 524 (unsol & (1<<i)) ? 1 : 0);
459 /* FIXME: add GPO and GPI pin information */ 525 /* FIXME: add GPO and GPI pin information */
526 print_nid_mixers(buffer, codec, nid);
460} 527}
461 528
462static void print_codec_info(struct snd_info_entry *entry, 529static void print_codec_info(struct snd_info_entry *entry,
@@ -536,6 +603,9 @@ static void print_codec_info(struct snd_info_entry *entry,
536 snd_iprintf(buffer, " CP"); 603 snd_iprintf(buffer, " CP");
537 snd_iprintf(buffer, "\n"); 604 snd_iprintf(buffer, "\n");
538 605
606 print_nid_mixers(buffer, codec, nid);
607 print_nid_pcms(buffer, codec, nid);
608
539 /* volume knob is a special widget that always have connection 609 /* volume knob is a special widget that always have connection
540 * list 610 * list
541 */ 611 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2d603f6aba63..455a0494f907 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -156,15 +156,19 @@ static const char *ad_slave_sws[] = {
156 156
157static void ad198x_free_kctls(struct hda_codec *codec); 157static void ad198x_free_kctls(struct hda_codec *codec);
158 158
159#ifdef CONFIG_SND_HDA_INPUT_BEEP
159/* additional beep mixers; the actual parameters are overwritten at build */ 160/* additional beep mixers; the actual parameters are overwritten at build */
160static struct snd_kcontrol_new ad_beep_mixer[] = { 161static struct snd_kcontrol_new ad_beep_mixer[] = {
161 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), 162 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
162 HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), 163 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
163 { } /* end */ 164 { } /* end */
164}; 165};
165 166
166#define set_beep_amp(spec, nid, idx, dir) \ 167#define set_beep_amp(spec, nid, idx, dir) \
167 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ 168 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
169#else
170#define set_beep_amp(spec, nid, idx, dir) /* NOP */
171#endif
168 172
169static int ad198x_build_controls(struct hda_codec *codec) 173static int ad198x_build_controls(struct hda_codec *codec)
170{ 174{
@@ -194,6 +198,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
194 } 198 }
195 199
196 /* create beep controls if needed */ 200 /* create beep controls if needed */
201#ifdef CONFIG_SND_HDA_INPUT_BEEP
197 if (spec->beep_amp) { 202 if (spec->beep_amp) {
198 struct snd_kcontrol_new *knew; 203 struct snd_kcontrol_new *knew;
199 for (knew = ad_beep_mixer; knew->name; knew++) { 204 for (knew = ad_beep_mixer; knew->name; knew++) {
@@ -202,11 +207,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
202 if (!kctl) 207 if (!kctl)
203 return -ENOMEM; 208 return -ENOMEM;
204 kctl->private_value = spec->beep_amp; 209 kctl->private_value = spec->beep_amp;
205 err = snd_hda_ctl_add(codec, kctl); 210 err = snd_hda_ctl_add(codec,
211 get_amp_nid_(spec->beep_amp),
212 kctl);
206 if (err < 0) 213 if (err < 0)
207 return err; 214 return err;
208 } 215 }
209 } 216 }
217#endif
210 218
211 /* if we have no master control, let's create it */ 219 /* if we have no master control, let's create it */
212 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 220 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
@@ -712,10 +720,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
712static void ad1986a_automic(struct hda_codec *codec) 720static void ad1986a_automic(struct hda_codec *codec)
713{ 721{
714 unsigned int present; 722 unsigned int present;
715 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); 723 present = snd_hda_jack_detect(codec, 0x1f);
716 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ 724 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
717 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, 725 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
718 (present & AC_PINSENSE_PRESENCE) ? 0 : 2); 726 present ? 0 : 2);
719} 727}
720 728
721#define AD1986A_MIC_EVENT 0x36 729#define AD1986A_MIC_EVENT 0x36
@@ -754,10 +762,8 @@ static void ad1986a_update_hp(struct hda_codec *codec)
754static void ad1986a_hp_automute(struct hda_codec *codec) 762static void ad1986a_hp_automute(struct hda_codec *codec)
755{ 763{
756 struct ad198x_spec *spec = codec->spec; 764 struct ad198x_spec *spec = codec->spec;
757 unsigned int present;
758 765
759 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); 766 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
760 spec->jack_present = !!(present & 0x80000000);
761 if (spec->inv_jack_detect) 767 if (spec->inv_jack_detect)
762 spec->jack_present = !spec->jack_present; 768 spec->jack_present = !spec->jack_present;
763 ad1986a_update_hp(codec); 769 ad1986a_update_hp(codec);
@@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec)
1547{ 1553{
1548 unsigned int present; 1554 unsigned int present;
1549 1555
1550 present = snd_hda_codec_read(codec, 0x06, 0, 1556 present = snd_hda_jack_detect(codec, 0x06);
1551 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1552 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, 1557 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1553 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 1558 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1554} 1559}
@@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec)
1568 }; 1573 };
1569 unsigned int present; 1574 unsigned int present;
1570 1575
1571 present = snd_hda_codec_read(codec, 0x08, 0, 1576 present = snd_hda_jack_detect(codec, 0x08);
1572 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1573 if (present) 1577 if (present)
1574 snd_hda_sequence_write(codec, mic_jack_on); 1578 snd_hda_sequence_write(codec, mic_jack_on);
1575 else 1579 else
@@ -2524,7 +2528,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2524{ 2528{
2525 if ((res >> 26) != AD1988_HP_EVENT) 2529 if ((res >> 26) != AD1988_HP_EVENT)
2526 return; 2530 return;
2527 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31)) 2531 if (snd_hda_jack_detect(codec, 0x11))
2528 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 2532 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2529 else 2533 else
2530 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 2534 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
@@ -2569,6 +2573,8 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
2569 knew->name = kstrdup(name, GFP_KERNEL); 2573 knew->name = kstrdup(name, GFP_KERNEL);
2570 if (! knew->name) 2574 if (! knew->name)
2571 return -ENOMEM; 2575 return -ENOMEM;
2576 if (get_amp_nid_(val))
2577 knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
2572 knew->private_value = val; 2578 knew->private_value = val;
2573 return 0; 2579 return 0;
2574} 2580}
@@ -3768,8 +3774,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec)
3768{ 3774{
3769 unsigned int present; 3775 unsigned int present;
3770 3776
3771 present = snd_hda_codec_read(codec, 0x11, 0, 3777 present = snd_hda_jack_detect(codec, 0x11);
3772 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3773 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 3778 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3774 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 3779 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3775 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 3780 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
@@ -3781,8 +3786,7 @@ static void ad1884a_hp_automic(struct hda_codec *codec)
3781{ 3786{
3782 unsigned int present; 3787 unsigned int present;
3783 3788
3784 present = snd_hda_codec_read(codec, 0x14, 0, 3789 present = snd_hda_jack_detect(codec, 0x14);
3785 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3786 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 3790 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3787 present ? 0 : 1); 3791 present ? 0 : 1);
3788} 3792}
@@ -3817,13 +3821,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec)
3817{ 3821{
3818 unsigned int present; 3822 unsigned int present;
3819 3823
3820 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0); 3824 present = snd_hda_jack_detect(codec, 0x11);
3821 present &= AC_PINSENSE_PRESENCE; 3825 if (!present)
3822 if (!present) { 3826 present = snd_hda_jack_detect(codec, 0x12);
3823 present = snd_hda_codec_read(codec, 0x12, 0,
3824 AC_VERB_GET_PIN_SENSE, 0);
3825 present &= AC_PINSENSE_PRESENCE;
3826 }
3827 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 3827 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3828 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 3828 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3829 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 3829 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
@@ -3835,11 +3835,9 @@ static void ad1884a_laptop_automic(struct hda_codec *codec)
3835{ 3835{
3836 unsigned int idx; 3836 unsigned int idx;
3837 3837
3838 if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & 3838 if (snd_hda_jack_detect(codec, 0x14))
3839 AC_PINSENSE_PRESENCE)
3840 idx = 0; 3839 idx = 0;
3841 else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & 3840 else if (snd_hda_jack_detect(codec, 0x1c))
3842 AC_PINSENSE_PRESENCE)
3843 idx = 4; 3841 idx = 4;
3844 else 3842 else
3845 idx = 1; 3843 idx = 1;
@@ -4008,8 +4006,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4008{ 4006{
4009 unsigned int present; 4007 unsigned int present;
4010 4008
4011 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) 4009 present = snd_hda_jack_detect(codec, 0x11);
4012 & AC_PINSENSE_PRESENCE;
4013 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, 4010 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4014 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4011 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4015} 4012}
@@ -4117,14 +4114,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4117/* switch to external mic if plugged */ 4114/* switch to external mic if plugged */
4118static void ad1984a_touchsmart_automic(struct hda_codec *codec) 4115static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4119{ 4116{
4120 if (snd_hda_codec_read(codec, 0x1c, 0, 4117 if (snd_hda_jack_detect(codec, 0x1c))
4121 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) {
4122 snd_hda_codec_write(codec, 0x0c, 0, 4118 snd_hda_codec_write(codec, 0x0c, 0,
4123 AC_VERB_SET_CONNECT_SEL, 0x4); 4119 AC_VERB_SET_CONNECT_SEL, 0x4);
4124 } else { 4120 else
4125 snd_hda_codec_write(codec, 0x0c, 0, 4121 snd_hda_codec_write(codec, 0x0c, 0,
4126 AC_VERB_SET_CONNECT_SEL, 0x5); 4122 AC_VERB_SET_CONNECT_SEL, 0x5);
4127 }
4128} 4123}
4129 4124
4130 4125
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index d08353d3bb7f..af478019088e 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -144,7 +144,7 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
144 struct snd_kcontrol_new knew = 144 struct snd_kcontrol_new knew =
145 HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); 145 HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type);
146 sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); 146 sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
147 return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 147 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
148} 148}
149 149
150static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, 150static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
@@ -155,7 +155,7 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
155 struct snd_kcontrol_new knew = 155 struct snd_kcontrol_new knew =
156 HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); 156 HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type);
157 sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); 157 sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]);
158 return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); 158 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
159} 159}
160 160
161#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) 161#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 8ba306856d38..2439e84dcb21 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -500,7 +500,7 @@ static int add_mute(struct hda_codec *codec, const char *name, int index,
500 knew.private_value = pval; 500 knew.private_value = pval;
501 snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); 501 snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]);
502 *kctlp = snd_ctl_new1(&knew, codec); 502 *kctlp = snd_ctl_new1(&knew, codec);
503 return snd_hda_ctl_add(codec, *kctlp); 503 return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
504} 504}
505 505
506static int add_volume(struct hda_codec *codec, const char *name, 506static int add_volume(struct hda_codec *codec, const char *name,
@@ -513,7 +513,7 @@ static int add_volume(struct hda_codec *codec, const char *name,
513 knew.private_value = pval; 513 knew.private_value = pval;
514 snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); 514 snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]);
515 *kctlp = snd_ctl_new1(&knew, codec); 515 *kctlp = snd_ctl_new1(&knew, codec);
516 return snd_hda_ctl_add(codec, *kctlp); 516 return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
517} 517}
518 518
519static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) 519static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac)
@@ -536,14 +536,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac)
536 536
537 spec->vmaster_sw = 537 spec->vmaster_sw =
538 snd_ctl_make_virtual_master("Master Playback Switch", NULL); 538 snd_ctl_make_virtual_master("Master Playback Switch", NULL);
539 err = snd_hda_ctl_add(codec, spec->vmaster_sw); 539 err = snd_hda_ctl_add(codec, dac, spec->vmaster_sw);
540 if (err < 0) 540 if (err < 0)
541 return err; 541 return err;
542 542
543 snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); 543 snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv);
544 spec->vmaster_vol = 544 spec->vmaster_vol =
545 snd_ctl_make_virtual_master("Master Playback Volume", tlv); 545 snd_ctl_make_virtual_master("Master Playback Volume", tlv);
546 err = snd_hda_ctl_add(codec, spec->vmaster_vol); 546 err = snd_hda_ctl_add(codec, dac, spec->vmaster_vol);
547 if (err < 0) 547 if (err < 0)
548 return err; 548 return err;
549 return 0; 549 return 0;
@@ -756,13 +756,13 @@ static int build_input(struct hda_codec *codec)
756 if (!kctl) 756 if (!kctl)
757 return -ENOMEM; 757 return -ENOMEM;
758 kctl->private_value = (long)spec->capture_bind[i]; 758 kctl->private_value = (long)spec->capture_bind[i];
759 err = snd_hda_ctl_add(codec, kctl); 759 err = snd_hda_ctl_add(codec, 0, kctl);
760 if (err < 0) 760 if (err < 0)
761 return err; 761 return err;
762 } 762 }
763 763
764 if (spec->num_inputs > 1 && !spec->mic_detect) { 764 if (spec->num_inputs > 1 && !spec->mic_detect) {
765 err = snd_hda_ctl_add(codec, 765 err = snd_hda_ctl_add(codec, 0,
766 snd_ctl_new1(&cs_capture_source, codec)); 766 snd_ctl_new1(&cs_capture_source, codec));
767 if (err < 0) 767 if (err < 0)
768 return err; 768 return err;
@@ -807,7 +807,7 @@ static void cs_automute(struct hda_codec *codec)
807{ 807{
808 struct cs_spec *spec = codec->spec; 808 struct cs_spec *spec = codec->spec;
809 struct auto_pin_cfg *cfg = &spec->autocfg; 809 struct auto_pin_cfg *cfg = &spec->autocfg;
810 unsigned int caps, present, hp_present; 810 unsigned int caps, hp_present;
811 hda_nid_t nid; 811 hda_nid_t nid;
812 int i; 812 int i;
813 813
@@ -817,12 +817,7 @@ static void cs_automute(struct hda_codec *codec)
817 caps = snd_hda_query_pin_caps(codec, nid); 817 caps = snd_hda_query_pin_caps(codec, nid);
818 if (!(caps & AC_PINCAP_PRES_DETECT)) 818 if (!(caps & AC_PINCAP_PRES_DETECT))
819 continue; 819 continue;
820 if (caps & AC_PINCAP_TRIG_REQ) 820 hp_present = snd_hda_jack_detect(codec, nid);
821 snd_hda_codec_read(codec, nid, 0,
822 AC_VERB_SET_PIN_SENSE, 0);
823 present = snd_hda_codec_read(codec, nid, 0,
824 AC_VERB_GET_PIN_SENSE, 0);
825 hp_present |= (present & AC_PINSENSE_PRESENCE) != 0;
826 if (hp_present) 821 if (hp_present)
827 break; 822 break;
828 } 823 }
@@ -844,15 +839,11 @@ static void cs_automic(struct hda_codec *codec)
844 struct cs_spec *spec = codec->spec; 839 struct cs_spec *spec = codec->spec;
845 struct auto_pin_cfg *cfg = &spec->autocfg; 840 struct auto_pin_cfg *cfg = &spec->autocfg;
846 hda_nid_t nid; 841 hda_nid_t nid;
847 unsigned int caps, present; 842 unsigned int present;
848 843
849 nid = cfg->input_pins[spec->automic_idx]; 844 nid = cfg->input_pins[spec->automic_idx];
850 caps = snd_hda_query_pin_caps(codec, nid); 845 present = snd_hda_jack_detect(codec, nid);
851 if (caps & AC_PINCAP_TRIG_REQ) 846 if (present)
852 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
853 present = snd_hda_codec_read(codec, nid, 0,
854 AC_VERB_GET_PIN_SENSE, 0);
855 if (present & AC_PINSENSE_PRESENCE)
856 change_cur_input(codec, spec->automic_idx, 0); 847 change_cur_input(codec, spec->automic_idx, 0);
857 else { 848 else {
858 unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? 849 unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ?
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 780e1a72114a..85c81feb10cf 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -197,8 +197,8 @@ static struct snd_kcontrol_new cmi9880_basic_mixer[] = {
197 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), 197 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
198 HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), 198 HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
199 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), 199 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
200 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT), 200 HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT),
201 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT), 201 HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT),
202 { } /* end */ 202 { } /* end */
203}; 203};
204 204
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 905859d4f4df..a09c03c3f62b 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -397,9 +397,7 @@ static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
397 for (i = 0; i < spec->jacks.used; i++) { 397 for (i = 0; i < spec->jacks.used; i++) {
398 if (jacks->nid == nid) { 398 if (jacks->nid == nid) {
399 unsigned int present; 399 unsigned int present;
400 present = snd_hda_codec_read(codec, nid, 0, 400 present = snd_hda_jack_detect(codec, nid);
401 AC_VERB_GET_PIN_SENSE, 0) &
402 AC_PINSENSE_PRESENCE;
403 401
404 present = (present) ? jacks->type : 0 ; 402 present = (present) ? jacks->type : 0 ;
405 403
@@ -750,8 +748,7 @@ static void cxt5045_hp_automic(struct hda_codec *codec)
750 }; 748 };
751 unsigned int present; 749 unsigned int present;
752 750
753 present = snd_hda_codec_read(codec, 0x12, 0, 751 present = snd_hda_jack_detect(codec, 0x12);
754 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
755 if (present) 752 if (present)
756 snd_hda_sequence_write(codec, mic_jack_on); 753 snd_hda_sequence_write(codec, mic_jack_on);
757 else 754 else
@@ -765,8 +762,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
765 struct conexant_spec *spec = codec->spec; 762 struct conexant_spec *spec = codec->spec;
766 unsigned int bits; 763 unsigned int bits;
767 764
768 spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, 765 spec->hp_present = snd_hda_jack_detect(codec, 0x11);
769 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
770 766
771 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 767 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
772 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 768 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
@@ -1175,9 +1171,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1175 1171
1176 switch (codec->subsystem_id >> 16) { 1172 switch (codec->subsystem_id >> 16) {
1177 case 0x103c: 1173 case 0x103c:
1178 /* HP laptop has a really bad sound over 0dB on NID 0x17. 1174 case 0x1734:
1179 * Fix max PCM level to 0 dB 1175 /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB
1180 * (originall it has 0x2b steps with 0dB offset 0x14) 1176 * on NID 0x17. Fix max PCM level to 0 dB
1177 * (originally it has 0x2b steps with 0dB offset 0x14)
1181 */ 1178 */
1182 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, 1179 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1183 (0x14 << AC_AMPCAP_OFFSET_SHIFT) | 1180 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -1243,8 +1240,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
1243 struct conexant_spec *spec = codec->spec; 1240 struct conexant_spec *spec = codec->spec;
1244 unsigned int bits; 1241 unsigned int bits;
1245 1242
1246 spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, 1243 spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1247 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1248 1244
1249 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 1245 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1250 /* See the note in cxt5047_hp_master_sw_put */ 1246 /* See the note in cxt5047_hp_master_sw_put */
@@ -1267,8 +1263,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec)
1267 }; 1263 };
1268 unsigned int present; 1264 unsigned int present;
1269 1265
1270 present = snd_hda_codec_read(codec, 0x15, 0, 1266 present = snd_hda_jack_detect(codec, 0x15);
1271 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1272 if (present) 1267 if (present)
1273 snd_hda_sequence_write(codec, mic_jack_on); 1268 snd_hda_sequence_write(codec, mic_jack_on);
1274 else 1269 else
@@ -1415,16 +1410,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1415 .get = conexant_mux_enum_get, 1410 .get = conexant_mux_enum_get,
1416 .put = conexant_mux_enum_put, 1411 .put = conexant_mux_enum_put,
1417 }, 1412 },
1418 HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT), 1413 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1419 HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
1420 HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
1421 HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
1422 HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
1423 HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
1424 HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
1425 HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
1426 HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
1427 HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
1428 1414
1429 { } /* end */ 1415 { } /* end */
1430}; 1416};
@@ -1621,9 +1607,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec)
1621 1607
1622 if (spec->no_auto_mic) 1608 if (spec->no_auto_mic)
1623 return; 1609 return;
1624 present = snd_hda_codec_read(codec, 0x17, 0, 1610 present = snd_hda_jack_detect(codec, 0x17);
1625 AC_VERB_GET_PIN_SENSE, 0) &
1626 AC_PINSENSE_PRESENCE;
1627 snd_hda_codec_write(codec, 0x14, 0, 1611 snd_hda_codec_write(codec, 0x14, 0,
1628 AC_VERB_SET_CONNECT_SEL, 1612 AC_VERB_SET_CONNECT_SEL,
1629 present ? 0x01 : 0x00); 1613 present ? 0x01 : 0x00);
@@ -1638,9 +1622,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
1638 1622
1639 if (spec->no_auto_mic) 1623 if (spec->no_auto_mic)
1640 return; 1624 return;
1641 present = snd_hda_codec_read(codec, 0x18, 0, 1625 present = snd_hda_jack_detect(codec, 0x18);
1642 AC_VERB_GET_PIN_SENSE, 0) &
1643 AC_PINSENSE_PRESENCE;
1644 if (present) 1626 if (present)
1645 spec->cur_adc_idx = 1; 1627 spec->cur_adc_idx = 1;
1646 else 1628 else
@@ -1661,9 +1643,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
1661{ 1643{
1662 struct conexant_spec *spec = codec->spec; 1644 struct conexant_spec *spec = codec->spec;
1663 1645
1664 spec->hp_present = snd_hda_codec_read(codec, 0x16, 0, 1646 spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1665 AC_VERB_GET_PIN_SENSE, 0) &
1666 AC_PINSENSE_PRESENCE;
1667 cxt5051_update_speaker(codec); 1647 cxt5051_update_speaker(codec);
1668} 1648}
1669 1649
@@ -2011,8 +1991,47 @@ static void cxt5066_automic(struct hda_codec *codec)
2011 }; 1991 };
2012 unsigned int present; 1992 unsigned int present;
2013 1993
2014 present = snd_hda_codec_read(codec, 0x1a, 0, 1994 present = snd_hda_jack_detect(codec, 0x1a);
2015 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1995 if (present) {
1996 snd_printdd("CXT5066: external microphone detected\n");
1997 snd_hda_sequence_write(codec, ext_mic_present);
1998 } else {
1999 snd_printdd("CXT5066: external microphone absent\n");
2000 snd_hda_sequence_write(codec, ext_mic_absent);
2001 }
2002}
2003
2004/* toggle input of built-in digital mic and mic jack appropriately */
2005static void cxt5066_vostro_automic(struct hda_codec *codec)
2006{
2007 struct conexant_spec *spec = codec->spec;
2008 unsigned int present;
2009
2010 struct hda_verb ext_mic_present[] = {
2011 /* enable external mic, port B */
2012 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
2013
2014 /* switch to external mic input */
2015 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2016 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2017
2018 /* disable internal digital mic */
2019 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2020 {}
2021 };
2022 static struct hda_verb ext_mic_absent[] = {
2023 /* enable internal mic, port C */
2024 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2025
2026 /* switch to internal mic input */
2027 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2028
2029 /* disable external mic, port B */
2030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2031 {}
2032 };
2033
2034 present = snd_hda_jack_detect(codec, 0x1a);
2016 if (present) { 2035 if (present) {
2017 snd_printdd("CXT5066: external microphone detected\n"); 2036 snd_printdd("CXT5066: external microphone detected\n");
2018 snd_hda_sequence_write(codec, ext_mic_present); 2037 snd_hda_sequence_write(codec, ext_mic_present);
@@ -2029,12 +2048,10 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2029 unsigned int portA, portD; 2048 unsigned int portA, portD;
2030 2049
2031 /* Port A */ 2050 /* Port A */
2032 portA = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0) 2051 portA = snd_hda_jack_detect(codec, 0x19);
2033 & AC_PINSENSE_PRESENCE;
2034 2052
2035 /* Port D */ 2053 /* Port D */
2036 portD = (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) 2054 portD = snd_hda_jack_detect(codec, 0x1c);
2037 & AC_PINSENSE_PRESENCE) << 1;
2038 2055
2039 spec->hp_present = !!(portA | portD); 2056 spec->hp_present = !!(portA | portD);
2040 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2057 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
@@ -2056,6 +2073,20 @@ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2056 } 2073 }
2057} 2074}
2058 2075
2076/* unsolicited event for jack sensing */
2077static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2078{
2079 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2080 switch (res >> 26) {
2081 case CONEXANT_HP_EVENT:
2082 cxt5066_hp_automute(codec);
2083 break;
2084 case CONEXANT_MIC_EVENT:
2085 cxt5066_vostro_automic(codec);
2086 break;
2087 }
2088}
2089
2059static const struct hda_input_mux cxt5066_analog_mic_boost = { 2090static const struct hda_input_mux cxt5066_analog_mic_boost = {
2060 .num_items = 5, 2091 .num_items = 5,
2061 .items = { 2092 .items = {
@@ -2297,6 +2328,67 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2297 { } /* end */ 2328 { } /* end */
2298}; 2329};
2299 2330
2331static struct hda_verb cxt5066_init_verbs_vostro[] = {
2332 /* Port A: headphones */
2333 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2334 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2335
2336 /* Port B: external microphone */
2337 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2338
2339 /* Port C: unused */
2340 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2341
2342 /* Port D: unused */
2343 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2344
2345 /* Port E: unused, but has primary EAPD */
2346 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2347 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2348
2349 /* Port F: unused */
2350 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2351
2352 /* Port G: internal speakers */
2353 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2354 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2355
2356 /* DAC1 */
2357 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2358
2359 /* DAC2: unused */
2360 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2361
2362 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2363 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2364 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2365 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2366 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2367 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2368 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2369 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2370 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2371 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2372 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2373 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2374
2375 /* Digital microphone port */
2376 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2377
2378 /* Audio input selectors */
2379 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2380 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2381
2382 /* Disable SPDIF */
2383 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2384 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2385
2386 /* enable unsolicited events for Port A and B */
2387 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2388 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2389 { } /* end */
2390};
2391
2300static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2392static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2301 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2393 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2302 { } /* end */ 2394 { } /* end */
@@ -2318,6 +2410,7 @@ enum {
2318 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2410 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2319 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2411 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2320 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2412 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2413 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2321 CXT5066_MODELS 2414 CXT5066_MODELS
2322}; 2415};
2323 2416
@@ -2325,6 +2418,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
2325 [CXT5066_LAPTOP] = "laptop", 2418 [CXT5066_LAPTOP] = "laptop",
2326 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2419 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2327 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 2420 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2421 [CXT5066_DELL_VOSTO] = "dell-vostro"
2328}; 2422};
2329 2423
2330static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2424static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2333,6 +2427,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2333 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 2427 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2334 CXT5066_DELL_LAPTOP), 2428 CXT5066_DELL_LAPTOP),
2335 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 2429 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2430 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2336 {} 2431 {}
2337}; 2432};
2338 2433
@@ -2400,6 +2495,19 @@ static int patch_cxt5066(struct hda_codec *codec)
2400 /* input source automatically selected */ 2495 /* input source automatically selected */
2401 spec->input_mux = NULL; 2496 spec->input_mux = NULL;
2402 break; 2497 break;
2498 case CXT5066_DELL_VOSTO:
2499 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2500 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2501 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2502 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2503 spec->port_d_mode = 0;
2504
2505 /* no S/PDIF out */
2506 spec->multiout.dig_out_nid = 0;
2507
2508 /* input source automatically selected */
2509 spec->input_mux = NULL;
2510 break;
2403 } 2511 }
2404 2512
2405 return 0; 2513 return 0;
@@ -2417,6 +2525,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2417 .patch = patch_cxt5051 }, 2525 .patch = patch_cxt5051 },
2418 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 2526 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2419 .patch = patch_cxt5066 }, 2527 .patch = patch_cxt5066 },
2528 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2529 .patch = patch_cxt5066 },
2420 {} /* terminator */ 2530 {} /* terminator */
2421}; 2531};
2422 2532
@@ -2424,6 +2534,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15045");
2424MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2534MODULE_ALIAS("snd-hda-codec-id:14f15047");
2425MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2535MODULE_ALIAS("snd-hda-codec-id:14f15051");
2426MODULE_ALIAS("snd-hda-codec-id:14f15066"); 2536MODULE_ALIAS("snd-hda-codec-id:14f15066");
2537MODULE_ALIAS("snd-hda-codec-id:14f15067");
2427 2538
2428MODULE_LICENSE("GPL"); 2539MODULE_LICENSE("GPL");
2429MODULE_DESCRIPTION("Conexant HD-audio codec"); 2540MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 01a18ed475ac..928df59be5d8 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -33,15 +33,41 @@
33#include "hda_codec.h" 33#include "hda_codec.h"
34#include "hda_local.h" 34#include "hda_local.h"
35 35
36static hda_nid_t cvt_nid; /* audio converter */ 36/*
37static hda_nid_t pin_nid; /* HDMI output pin */ 37 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
38 * could support two independent pipes, each of them can be connected to one or
39 * more ports (DVI, HDMI or DisplayPort).
40 *
41 * The HDA correspondence of pipes/ports are converter/pin nodes.
42 */
43#define INTEL_HDMI_CVTS 2
44#define INTEL_HDMI_PINS 3
38 45
39#define INTEL_HDMI_EVENT_TAG 0x08 46static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
47 "INTEL HDMI 0",
48 "INTEL HDMI 1",
49};
40 50
41struct intel_hdmi_spec { 51struct intel_hdmi_spec {
42 struct hda_multi_out multiout; 52 int num_cvts;
43 struct hda_pcm pcm_rec; 53 int num_pins;
44 struct hdmi_eld sink_eld; 54 hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */
55 hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */
56
57 /*
58 * source connection for each pin
59 */
60 hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
61
62 /*
63 * HDMI sink attached to each pin
64 */
65 struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
66
67 /*
68 * export one pcm per pipe
69 */
70 struct hda_pcm pcm_rec[INTEL_HDMI_CVTS];
45}; 71};
46 72
47struct hdmi_audio_infoframe { 73struct hdmi_audio_infoframe {
@@ -184,40 +210,186 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
184{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, 210{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
185}; 211};
186 212
213
214/*
215 * HDA/HDMI auto parsing
216 */
217
218static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
219{
220 int i;
221
222 for (i = 0; nids[i]; i++)
223 if (nids[i] == nid)
224 return i;
225
226 snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
227 return -EINVAL;
228}
229
230static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
231{
232 struct intel_hdmi_spec *spec = codec->spec;
233 hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
234 int conn_len, curr;
235 int index;
236
237 if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
238 snd_printk(KERN_WARNING
239 "HDMI: pin %d wcaps %#x "
240 "does not support connection list\n",
241 pin_nid, get_wcaps(codec, pin_nid));
242 return -EINVAL;
243 }
244
245 conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
246 HDA_MAX_CONNECTIONS);
247 if (conn_len > 1)
248 curr = snd_hda_codec_read(codec, pin_nid, 0,
249 AC_VERB_GET_CONNECT_SEL, 0);
250 else
251 curr = 0;
252
253 index = hda_node_index(spec->pin, pin_nid);
254 if (index < 0)
255 return -EINVAL;
256
257 spec->pin_cvt[index] = conn_list[curr];
258
259 return 0;
260}
261
262static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
263 struct hdmi_eld *eld)
264{
265 if (!snd_hdmi_get_eld(eld, codec, pin_nid))
266 snd_hdmi_show_eld(eld);
267}
268
269static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
270 struct hdmi_eld *eld)
271{
272 int present = snd_hda_pin_sense(codec, pin_nid);
273
274 eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
275 eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
276
277 if (present & AC_PINSENSE_ELDV)
278 hdmi_get_show_eld(codec, pin_nid, eld);
279}
280
281static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
282{
283 struct intel_hdmi_spec *spec = codec->spec;
284
285 if (spec->num_pins >= INTEL_HDMI_PINS) {
286 snd_printk(KERN_WARNING
287 "HDMI: no space for pin %d \n", pin_nid);
288 return -EINVAL;
289 }
290
291 hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
292
293 spec->pin[spec->num_pins] = pin_nid;
294 spec->num_pins++;
295
296 /*
297 * It is assumed that converter nodes come first in the node list and
298 * hence have been registered and usable now.
299 */
300 return intel_hdmi_read_pin_conn(codec, pin_nid);
301}
302
303static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
304{
305 struct intel_hdmi_spec *spec = codec->spec;
306
307 if (spec->num_cvts >= INTEL_HDMI_CVTS) {
308 snd_printk(KERN_WARNING
309 "HDMI: no space for converter %d \n", nid);
310 return -EINVAL;
311 }
312
313 spec->cvt[spec->num_cvts] = nid;
314 spec->num_cvts++;
315
316 return 0;
317}
318
319static int intel_hdmi_parse_codec(struct hda_codec *codec)
320{
321 hda_nid_t nid;
322 int i, nodes;
323
324 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
325 if (!nid || nodes < 0) {
326 snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
327 return -EINVAL;
328 }
329
330 for (i = 0; i < nodes; i++, nid++) {
331 unsigned int caps;
332 unsigned int type;
333
334 caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
335 type = get_wcaps_type(caps);
336
337 if (!(caps & AC_WCAP_DIGITAL))
338 continue;
339
340 switch (type) {
341 case AC_WID_AUD_OUT:
342 if (intel_hdmi_add_cvt(codec, nid) < 0)
343 return -EINVAL;
344 break;
345 case AC_WID_PIN:
346 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
347 if (!(caps & AC_PINCAP_HDMI))
348 continue;
349 if (intel_hdmi_add_pin(codec, nid) < 0)
350 return -EINVAL;
351 break;
352 }
353 }
354
355 return 0;
356}
357
187/* 358/*
188 * HDMI routines 359 * HDMI routines
189 */ 360 */
190 361
191#ifdef BE_PARANOID 362#ifdef BE_PARANOID
192static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid, 363static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
193 int *packet_index, int *byte_index) 364 int *packet_index, int *byte_index)
194{ 365{
195 int val; 366 int val;
196 367
197 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0); 368 val = snd_hda_codec_read(codec, pin_nid, 0,
369 AC_VERB_GET_HDMI_DIP_INDEX, 0);
198 370
199 *packet_index = val >> 5; 371 *packet_index = val >> 5;
200 *byte_index = val & 0x1f; 372 *byte_index = val & 0x1f;
201} 373}
202#endif 374#endif
203 375
204static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid, 376static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
205 int packet_index, int byte_index) 377 int packet_index, int byte_index)
206{ 378{
207 int val; 379 int val;
208 380
209 val = (packet_index << 5) | (byte_index & 0x1f); 381 val = (packet_index << 5) | (byte_index & 0x1f);
210 382
211 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); 383 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
212} 384}
213 385
214static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid, 386static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
215 unsigned char val) 387 unsigned char val)
216{ 388{
217 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); 389 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
218} 390}
219 391
220static void hdmi_enable_output(struct hda_codec *codec) 392static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
221{ 393{
222 /* Unmute */ 394 /* Unmute */
223 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) 395 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
@@ -231,7 +403,8 @@ static void hdmi_enable_output(struct hda_codec *codec)
231/* 403/*
232 * Enable Audio InfoFrame Transmission 404 * Enable Audio InfoFrame Transmission
233 */ 405 */
234static void hdmi_start_infoframe_trans(struct hda_codec *codec) 406static void hdmi_start_infoframe_trans(struct hda_codec *codec,
407 hda_nid_t pin_nid)
235{ 408{
236 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); 409 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
237 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, 410 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
@@ -241,59 +414,49 @@ static void hdmi_start_infoframe_trans(struct hda_codec *codec)
241/* 414/*
242 * Disable Audio InfoFrame Transmission 415 * Disable Audio InfoFrame Transmission
243 */ 416 */
244static void hdmi_stop_infoframe_trans(struct hda_codec *codec) 417static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
418 hda_nid_t pin_nid)
245{ 419{
246 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); 420 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
247 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, 421 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
248 AC_DIPXMIT_DISABLE); 422 AC_DIPXMIT_DISABLE);
249} 423}
250 424
251static int hdmi_get_channel_count(struct hda_codec *codec) 425static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
252{ 426{
253 return 1 + snd_hda_codec_read(codec, cvt_nid, 0, 427 return 1 + snd_hda_codec_read(codec, nid, 0,
254 AC_VERB_GET_CVT_CHAN_COUNT, 0); 428 AC_VERB_GET_CVT_CHAN_COUNT, 0);
255} 429}
256 430
257static void hdmi_set_channel_count(struct hda_codec *codec, int chs) 431static void hdmi_set_channel_count(struct hda_codec *codec,
432 hda_nid_t nid, int chs)
258{ 433{
259 snd_hda_codec_write(codec, cvt_nid, 0, 434 if (chs != hdmi_get_channel_count(codec, nid))
260 AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); 435 snd_hda_codec_write(codec, nid, 0,
261 436 AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
262 if (chs != hdmi_get_channel_count(codec))
263 snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
264 chs, hdmi_get_channel_count(codec));
265} 437}
266 438
267static void hdmi_debug_channel_mapping(struct hda_codec *codec) 439static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid)
268{ 440{
269#ifdef CONFIG_SND_DEBUG_VERBOSE 441#ifdef CONFIG_SND_DEBUG_VERBOSE
270 int i; 442 int i;
271 int slot; 443 int slot;
272 444
273 for (i = 0; i < 8; i++) { 445 for (i = 0; i < 8; i++) {
274 slot = snd_hda_codec_read(codec, cvt_nid, 0, 446 slot = snd_hda_codec_read(codec, nid, 0,
275 AC_VERB_GET_HDMI_CHAN_SLOT, i); 447 AC_VERB_GET_HDMI_CHAN_SLOT, i);
276 printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", 448 printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
277 slot >> 4, slot & 0x7); 449 slot >> 4, slot & 0xf);
278 } 450 }
279#endif 451#endif
280} 452}
281 453
282static void hdmi_parse_eld(struct hda_codec *codec)
283{
284 struct intel_hdmi_spec *spec = codec->spec;
285 struct hdmi_eld *eld = &spec->sink_eld;
286
287 if (!snd_hdmi_get_eld(eld, codec, pin_nid))
288 snd_hdmi_show_eld(eld);
289}
290
291 454
292/* 455/*
293 * Audio InfoFrame routines 456 * Audio InfoFrame routines
294 */ 457 */
295 458
296static void hdmi_debug_dip_size(struct hda_codec *codec) 459static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
297{ 460{
298#ifdef CONFIG_SND_DEBUG_VERBOSE 461#ifdef CONFIG_SND_DEBUG_VERBOSE
299 int i; 462 int i;
@@ -310,7 +473,7 @@ static void hdmi_debug_dip_size(struct hda_codec *codec)
310#endif 473#endif
311} 474}
312 475
313static void hdmi_clear_dip_buffers(struct hda_codec *codec) 476static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
314{ 477{
315#ifdef BE_PARANOID 478#ifdef BE_PARANOID
316 int i, j; 479 int i, j;
@@ -339,23 +502,35 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec)
339#endif 502#endif
340} 503}
341 504
342static void hdmi_fill_audio_infoframe(struct hda_codec *codec, 505static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
343 struct hdmi_audio_infoframe *ai)
344{ 506{
345 u8 *params = (u8 *)ai; 507 u8 *bytes = (u8 *)ai;
346 u8 sum = 0; 508 u8 sum = 0;
347 int i; 509 int i;
348 510
349 hdmi_debug_dip_size(codec); 511 ai->checksum = 0;
350 hdmi_clear_dip_buffers(codec); /* be paranoid */ 512
513 for (i = 0; i < sizeof(*ai); i++)
514 sum += bytes[i];
351 515
352 for (i = 0; i < sizeof(ai); i++)
353 sum += params[i];
354 ai->checksum = - sum; 516 ai->checksum = - sum;
517}
518
519static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
520 hda_nid_t pin_nid,
521 struct hdmi_audio_infoframe *ai)
522{
523 u8 *bytes = (u8 *)ai;
524 int i;
525
526 hdmi_debug_dip_size(codec, pin_nid);
527 hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
528
529 hdmi_checksum_audio_infoframe(ai);
355 530
356 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); 531 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
357 for (i = 0; i < sizeof(ai); i++) 532 for (i = 0; i < sizeof(*ai); i++)
358 hdmi_write_dip_byte(codec, pin_nid, params[i]); 533 hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
359} 534}
360 535
361/* 536/*
@@ -386,11 +561,11 @@ static void init_channel_allocations(void)
386 * 561 *
387 * TODO: it could select the wrong CA from multiple candidates. 562 * TODO: it could select the wrong CA from multiple candidates.
388*/ 563*/
389static int hdmi_setup_channel_allocation(struct hda_codec *codec, 564static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
390 struct hdmi_audio_infoframe *ai) 565 struct hdmi_audio_infoframe *ai)
391{ 566{
392 struct intel_hdmi_spec *spec = codec->spec; 567 struct intel_hdmi_spec *spec = codec->spec;
393 struct hdmi_eld *eld = &spec->sink_eld; 568 struct hdmi_eld *eld;
394 int i; 569 int i;
395 int spk_mask = 0; 570 int spk_mask = 0;
396 int channels = 1 + (ai->CC02_CT47 & 0x7); 571 int channels = 1 + (ai->CC02_CT47 & 0x7);
@@ -402,6 +577,11 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec,
402 if (channels <= 2) 577 if (channels <= 2)
403 return 0; 578 return 0;
404 579
580 i = hda_node_index(spec->pin_cvt, nid);
581 if (i < 0)
582 return 0;
583 eld = &spec->sink_eld[i];
584
405 /* 585 /*
406 * HDMI sink's ELD info cannot always be retrieved for now, e.g. 586 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
407 * in console or for audio devices. Assume the highest speakers 587 * in console or for audio devices. Assume the highest speakers
@@ -439,8 +619,8 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec,
439 return ai->CA; 619 return ai->CA;
440} 620}
441 621
442static void hdmi_setup_channel_mapping(struct hda_codec *codec, 622static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid,
443 struct hdmi_audio_infoframe *ai) 623 struct hdmi_audio_infoframe *ai)
444{ 624{
445 int i; 625 int i;
446 626
@@ -453,17 +633,41 @@ static void hdmi_setup_channel_mapping(struct hda_codec *codec,
453 */ 633 */
454 634
455 for (i = 0; i < 8; i++) 635 for (i = 0; i < 8; i++)
456 snd_hda_codec_write(codec, cvt_nid, 0, 636 snd_hda_codec_write(codec, nid, 0,
457 AC_VERB_SET_HDMI_CHAN_SLOT, 637 AC_VERB_SET_HDMI_CHAN_SLOT,
458 (i << 4) | i); 638 (i << 4) | i);
459 639
460 hdmi_debug_channel_mapping(codec); 640 hdmi_debug_channel_mapping(codec, nid);
461} 641}
462 642
643static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
644 struct hdmi_audio_infoframe *ai)
645{
646 u8 *bytes = (u8 *)ai;
647 u8 val;
648 int i;
649
650 if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
651 != AC_DIPXMIT_BEST)
652 return false;
653
654 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
655 for (i = 0; i < sizeof(*ai); i++) {
656 val = snd_hda_codec_read(codec, pin_nid, 0,
657 AC_VERB_GET_HDMI_DIP_DATA, 0);
658 if (val != bytes[i])
659 return false;
660 }
463 661
464static void hdmi_setup_audio_infoframe(struct hda_codec *codec, 662 return true;
663}
664
665static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
465 struct snd_pcm_substream *substream) 666 struct snd_pcm_substream *substream)
466{ 667{
668 struct intel_hdmi_spec *spec = codec->spec;
669 hda_nid_t pin_nid;
670 int i;
467 struct hdmi_audio_infoframe ai = { 671 struct hdmi_audio_infoframe ai = {
468 .type = 0x84, 672 .type = 0x84,
469 .ver = 0x01, 673 .ver = 0x01,
@@ -471,11 +675,22 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
471 .CC02_CT47 = substream->runtime->channels - 1, 675 .CC02_CT47 = substream->runtime->channels - 1,
472 }; 676 };
473 677
474 hdmi_setup_channel_allocation(codec, &ai); 678 hdmi_setup_channel_allocation(codec, nid, &ai);
475 hdmi_setup_channel_mapping(codec, &ai); 679 hdmi_setup_channel_mapping(codec, nid, &ai);
476 680
477 hdmi_fill_audio_infoframe(codec, &ai); 681 for (i = 0; i < spec->num_pins; i++) {
478 hdmi_start_infoframe_trans(codec); 682 if (spec->pin_cvt[i] != nid)
683 continue;
684 if (!spec->sink_eld[i].monitor_present)
685 continue;
686
687 pin_nid = spec->pin[i];
688 if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
689 hdmi_stop_infoframe_trans(codec, pin_nid);
690 hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
691 hdmi_start_infoframe_trans(codec, pin_nid);
692 }
693 }
479} 694}
480 695
481 696
@@ -485,27 +700,39 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
485 700
486static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) 701static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
487{ 702{
703 struct intel_hdmi_spec *spec = codec->spec;
704 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
488 int pind = !!(res & AC_UNSOL_RES_PD); 705 int pind = !!(res & AC_UNSOL_RES_PD);
489 int eldv = !!(res & AC_UNSOL_RES_ELDV); 706 int eldv = !!(res & AC_UNSOL_RES_ELDV);
707 int index;
490 708
491 printk(KERN_INFO 709 printk(KERN_INFO
492 "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n", 710 "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
493 pind, eldv); 711 tag, pind, eldv);
712
713 index = hda_node_index(spec->pin, tag);
714 if (index < 0)
715 return;
716
717 spec->sink_eld[index].monitor_present = pind;
718 spec->sink_eld[index].eld_valid = eldv;
494 719
495 if (pind && eldv) { 720 if (pind && eldv) {
496 hdmi_parse_eld(codec); 721 hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
497 /* TODO: do real things about ELD */ 722 /* TODO: do real things about ELD */
498 } 723 }
499} 724}
500 725
501static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) 726static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
502{ 727{
728 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
503 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; 729 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
504 int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); 730 int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
505 int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); 731 int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
506 732
507 printk(KERN_INFO 733 printk(KERN_INFO
508 "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", 734 "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
735 tag,
509 subtag, 736 subtag,
510 cp_state, 737 cp_state,
511 cp_ready); 738 cp_ready);
@@ -520,10 +747,11 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
520 747
521static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) 748static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
522{ 749{
750 struct intel_hdmi_spec *spec = codec->spec;
523 int tag = res >> AC_UNSOL_RES_TAG_SHIFT; 751 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
524 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; 752 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
525 753
526 if (tag != INTEL_HDMI_EVENT_TAG) { 754 if (hda_node_index(spec->pin, tag) < 0) {
527 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); 755 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
528 return; 756 return;
529 } 757 }
@@ -538,24 +766,29 @@ static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
538 * Callbacks 766 * Callbacks
539 */ 767 */
540 768
541static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo, 769static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
542 struct hda_codec *codec, 770 u32 stream_tag, int format)
543 struct snd_pcm_substream *substream)
544{ 771{
545 struct intel_hdmi_spec *spec = codec->spec; 772 int tag;
546 773 int fmt;
547 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
548}
549 774
550static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo, 775 tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
551 struct hda_codec *codec, 776 fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
552 struct snd_pcm_substream *substream)
553{
554 struct intel_hdmi_spec *spec = codec->spec;
555 777
556 hdmi_stop_infoframe_trans(codec); 778 snd_printdd("hdmi_setup_stream: "
779 "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
780 nid,
781 tag == stream_tag ? "" : "new-",
782 stream_tag,
783 fmt == format ? "" : "new-",
784 format);
557 785
558 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 786 if (tag != stream_tag)
787 snd_hda_codec_write(codec, nid, 0,
788 AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
789 if (fmt != format)
790 snd_hda_codec_write(codec, nid, 0,
791 AC_VERB_SET_STREAM_FORMAT, format);
559} 792}
560 793
561static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 794static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -564,43 +797,53 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
564 unsigned int format, 797 unsigned int format,
565 struct snd_pcm_substream *substream) 798 struct snd_pcm_substream *substream)
566{ 799{
567 struct intel_hdmi_spec *spec = codec->spec; 800 hdmi_set_channel_count(codec, hinfo->nid,
568 801 substream->runtime->channels);
569 snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
570 format, substream);
571 802
572 hdmi_set_channel_count(codec, substream->runtime->channels); 803 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
573 804
574 hdmi_setup_audio_infoframe(codec, substream); 805 hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
806 return 0;
807}
575 808
809static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
810 struct hda_codec *codec,
811 struct snd_pcm_substream *substream)
812{
576 return 0; 813 return 0;
577} 814}
578 815
579static struct hda_pcm_stream intel_hdmi_pcm_playback = { 816static struct hda_pcm_stream intel_hdmi_pcm_playback = {
580 .substreams = 1, 817 .substreams = 1,
581 .channels_min = 2, 818 .channels_min = 2,
582 .channels_max = 8,
583 .ops = { 819 .ops = {
584 .open = intel_hdmi_playback_pcm_open, 820 .prepare = intel_hdmi_playback_pcm_prepare,
585 .close = intel_hdmi_playback_pcm_close, 821 .cleanup = intel_hdmi_playback_pcm_cleanup,
586 .prepare = intel_hdmi_playback_pcm_prepare
587 }, 822 },
588}; 823};
589 824
590static int intel_hdmi_build_pcms(struct hda_codec *codec) 825static int intel_hdmi_build_pcms(struct hda_codec *codec)
591{ 826{
592 struct intel_hdmi_spec *spec = codec->spec; 827 struct intel_hdmi_spec *spec = codec->spec;
593 struct hda_pcm *info = &spec->pcm_rec; 828 struct hda_pcm *info = spec->pcm_rec;
829 int i;
594 830
595 codec->num_pcms = 1; 831 codec->num_pcms = spec->num_cvts;
596 codec->pcm_info = info; 832 codec->pcm_info = info;
597 833
598 /* NID to query formats and rates and setup streams */ 834 for (i = 0; i < codec->num_pcms; i++, info++) {
599 intel_hdmi_pcm_playback.nid = cvt_nid; 835 unsigned int chans;
600 836
601 info->name = "INTEL HDMI"; 837 chans = get_wcaps(codec, spec->cvt[i]);
602 info->pcm_type = HDA_PCM_TYPE_HDMI; 838 chans = get_wcaps_channels(chans);
603 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback; 839
840 info->name = intel_hdmi_pcm_names[i];
841 info->pcm_type = HDA_PCM_TYPE_HDMI;
842 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
843 intel_hdmi_pcm_playback;
844 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
845 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
846 }
604 847
605 return 0; 848 return 0;
606} 849}
@@ -609,29 +852,39 @@ static int intel_hdmi_build_controls(struct hda_codec *codec)
609{ 852{
610 struct intel_hdmi_spec *spec = codec->spec; 853 struct intel_hdmi_spec *spec = codec->spec;
611 int err; 854 int err;
855 int i;
612 856
613 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 857 for (i = 0; i < codec->num_pcms; i++) {
614 if (err < 0) 858 err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
615 return err; 859 if (err < 0)
860 return err;
861 }
616 862
617 return 0; 863 return 0;
618} 864}
619 865
620static int intel_hdmi_init(struct hda_codec *codec) 866static int intel_hdmi_init(struct hda_codec *codec)
621{ 867{
622 hdmi_enable_output(codec); 868 struct intel_hdmi_spec *spec = codec->spec;
869 int i;
623 870
624 snd_hda_codec_write(codec, pin_nid, 0, 871 for (i = 0; spec->pin[i]; i++) {
625 AC_VERB_SET_UNSOLICITED_ENABLE, 872 hdmi_enable_output(codec, spec->pin[i]);
626 AC_USRSP_EN | INTEL_HDMI_EVENT_TAG); 873 snd_hda_codec_write(codec, spec->pin[i], 0,
874 AC_VERB_SET_UNSOLICITED_ENABLE,
875 AC_USRSP_EN | spec->pin[i]);
876 }
627 return 0; 877 return 0;
628} 878}
629 879
630static void intel_hdmi_free(struct hda_codec *codec) 880static void intel_hdmi_free(struct hda_codec *codec)
631{ 881{
632 struct intel_hdmi_spec *spec = codec->spec; 882 struct intel_hdmi_spec *spec = codec->spec;
883 int i;
884
885 for (i = 0; i < spec->num_pins; i++)
886 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
633 887
634 snd_hda_eld_proc_free(codec, &spec->sink_eld);
635 kfree(spec); 888 kfree(spec);
636} 889}
637 890
@@ -643,49 +896,38 @@ static struct hda_codec_ops intel_hdmi_patch_ops = {
643 .unsol_event = intel_hdmi_unsol_event, 896 .unsol_event = intel_hdmi_unsol_event,
644}; 897};
645 898
646static int do_patch_intel_hdmi(struct hda_codec *codec) 899static int patch_intel_hdmi(struct hda_codec *codec)
647{ 900{
648 struct intel_hdmi_spec *spec; 901 struct intel_hdmi_spec *spec;
902 int i;
649 903
650 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 904 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
651 if (spec == NULL) 905 if (spec == NULL)
652 return -ENOMEM; 906 return -ENOMEM;
653 907
654 spec->multiout.num_dacs = 0; /* no analog */
655 spec->multiout.max_channels = 8;
656 spec->multiout.dig_out_nid = cvt_nid;
657
658 codec->spec = spec; 908 codec->spec = spec;
909 if (intel_hdmi_parse_codec(codec) < 0) {
910 codec->spec = NULL;
911 kfree(spec);
912 return -EINVAL;
913 }
659 codec->patch_ops = intel_hdmi_patch_ops; 914 codec->patch_ops = intel_hdmi_patch_ops;
660 915
661 snd_hda_eld_proc_new(codec, &spec->sink_eld); 916 for (i = 0; i < spec->num_pins; i++)
917 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
662 918
663 init_channel_allocations(); 919 init_channel_allocations();
664 920
665 return 0; 921 return 0;
666} 922}
667 923
668static int patch_intel_hdmi(struct hda_codec *codec)
669{
670 cvt_nid = 0x02;
671 pin_nid = 0x03;
672 return do_patch_intel_hdmi(codec);
673}
674
675static int patch_intel_hdmi_ibexpeak(struct hda_codec *codec)
676{
677 cvt_nid = 0x02;
678 pin_nid = 0x04;
679 return do_patch_intel_hdmi(codec);
680}
681
682static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { 924static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
683 { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi }, 925 { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi },
684 { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, 926 { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
685 { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, 927 { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
686 { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, 928 { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
687 { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, 929 { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi },
688 { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi_ibexpeak }, 930 { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi },
689 { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, 931 { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
690 {} /* terminator */ 932 {} /* terminator */
691}; 933};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 70583719282b..d967836f36bb 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -961,18 +961,12 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
961static void alc_automute_pin(struct hda_codec *codec) 961static void alc_automute_pin(struct hda_codec *codec)
962{ 962{
963 struct alc_spec *spec = codec->spec; 963 struct alc_spec *spec = codec->spec;
964 unsigned int present, pincap;
965 unsigned int nid = spec->autocfg.hp_pins[0]; 964 unsigned int nid = spec->autocfg.hp_pins[0];
966 int i; 965 int i;
967 966
968 if (!nid) 967 if (!nid)
969 return; 968 return;
970 pincap = snd_hda_query_pin_caps(codec, nid); 969 spec->jack_present = snd_hda_jack_detect(codec, nid);
971 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
972 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
973 present = snd_hda_codec_read(codec, nid, 0,
974 AC_VERB_GET_PIN_SENSE, 0);
975 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
976 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { 970 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
977 nid = spec->autocfg.speaker_pins[i]; 971 nid = spec->autocfg.speaker_pins[i];
978 if (!nid) 972 if (!nid)
@@ -1012,9 +1006,7 @@ static void alc_mic_automute(struct hda_codec *codec)
1012 1006
1013 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; 1007 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1014 1008
1015 present = snd_hda_codec_read(codec, spec->ext_mic.pin, 0, 1009 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1016 AC_VERB_GET_PIN_SENSE, 0);
1017 present &= AC_PINSENSE_PRESENCE;
1018 if (present) { 1010 if (present) {
1019 alive = &spec->ext_mic; 1011 alive = &spec->ext_mic;
1020 dead = &spec->int_mic; 1012 dead = &spec->int_mic;
@@ -1402,6 +1394,17 @@ static void alc_pick_fixup(struct hda_codec *codec,
1402 add_verb(codec->spec, fix->verbs); 1394 add_verb(codec->spec, fix->verbs);
1403} 1395}
1404 1396
1397static int alc_read_coef_idx(struct hda_codec *codec,
1398 unsigned int coef_idx)
1399{
1400 unsigned int val;
1401 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1402 coef_idx);
1403 val = snd_hda_codec_read(codec, 0x20, 0,
1404 AC_VERB_GET_PROC_COEF, 0);
1405 return val;
1406}
1407
1405/* 1408/*
1406 * ALC888 1409 * ALC888
1407 */ 1410 */
@@ -1513,7 +1516,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
1513static void alc_automute_amp(struct hda_codec *codec) 1516static void alc_automute_amp(struct hda_codec *codec)
1514{ 1517{
1515 struct alc_spec *spec = codec->spec; 1518 struct alc_spec *spec = codec->spec;
1516 unsigned int val, mute, pincap; 1519 unsigned int mute;
1517 hda_nid_t nid; 1520 hda_nid_t nid;
1518 int i; 1521 int i;
1519 1522
@@ -1522,13 +1525,7 @@ static void alc_automute_amp(struct hda_codec *codec)
1522 nid = spec->autocfg.hp_pins[i]; 1525 nid = spec->autocfg.hp_pins[i];
1523 if (!nid) 1526 if (!nid)
1524 break; 1527 break;
1525 pincap = snd_hda_query_pin_caps(codec, nid); 1528 if (snd_hda_jack_detect(codec, nid)) {
1526 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
1527 snd_hda_codec_read(codec, nid, 0,
1528 AC_VERB_SET_PIN_SENSE, 0);
1529 val = snd_hda_codec_read(codec, nid, 0,
1530 AC_VERB_GET_PIN_SENSE, 0);
1531 if (val & AC_PINSENSE_PRESENCE) {
1532 spec->jack_present = 1; 1529 spec->jack_present = 1;
1533 break; 1530 break;
1534 } 1531 }
@@ -1786,6 +1783,8 @@ static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
1786 1783
1787 spec->autocfg.hp_pins[0] = 0x15; 1784 spec->autocfg.hp_pins[0] = 0x15;
1788 spec->autocfg.speaker_pins[0] = 0x14; 1785 spec->autocfg.speaker_pins[0] = 0x14;
1786 spec->autocfg.speaker_pins[1] = 0x16;
1787 spec->autocfg.speaker_pins[2] = 0x17;
1789} 1788}
1790 1789
1791static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec) 1790static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -2410,12 +2409,14 @@ static const char *alc_slave_sws[] = {
2410 2409
2411static void alc_free_kctls(struct hda_codec *codec); 2410static void alc_free_kctls(struct hda_codec *codec);
2412 2411
2412#ifdef CONFIG_SND_HDA_INPUT_BEEP
2413/* additional beep mixers; the actual parameters are overwritten at build */ 2413/* additional beep mixers; the actual parameters are overwritten at build */
2414static struct snd_kcontrol_new alc_beep_mixer[] = { 2414static struct snd_kcontrol_new alc_beep_mixer[] = {
2415 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), 2415 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
2416 HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT), 2416 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
2417 { } /* end */ 2417 { } /* end */
2418}; 2418};
2419#endif
2419 2420
2420static int alc_build_controls(struct hda_codec *codec) 2421static int alc_build_controls(struct hda_codec *codec)
2421{ 2422{
@@ -2452,6 +2453,7 @@ static int alc_build_controls(struct hda_codec *codec)
2452 return err; 2453 return err;
2453 } 2454 }
2454 2455
2456#ifdef CONFIG_SND_HDA_INPUT_BEEP
2455 /* create beep controls if needed */ 2457 /* create beep controls if needed */
2456 if (spec->beep_amp) { 2458 if (spec->beep_amp) {
2457 struct snd_kcontrol_new *knew; 2459 struct snd_kcontrol_new *knew;
@@ -2461,11 +2463,13 @@ static int alc_build_controls(struct hda_codec *codec)
2461 if (!kctl) 2463 if (!kctl)
2462 return -ENOMEM; 2464 return -ENOMEM;
2463 kctl->private_value = spec->beep_amp; 2465 kctl->private_value = spec->beep_amp;
2464 err = snd_hda_ctl_add(codec, kctl); 2466 err = snd_hda_ctl_add(codec,
2467 get_amp_nid_(spec->beep_amp), kctl);
2465 if (err < 0) 2468 if (err < 0)
2466 return err; 2469 return err;
2467 } 2470 }
2468 } 2471 }
2472#endif
2469 2473
2470 /* if we have no master control, let's create it */ 2474 /* if we have no master control, let's create it */
2471 if (!spec->no_analog && 2475 if (!spec->no_analog &&
@@ -2779,8 +2783,7 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec)
2779 unsigned int present; 2783 unsigned int present;
2780 unsigned char bits; 2784 unsigned char bits;
2781 2785
2782 present = snd_hda_codec_read(codec, 0x18, 0, 2786 present = snd_hda_jack_detect(codec, 0x18);
2783 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2784 bits = present ? HDA_AMP_MUTE : 0; 2787 bits = present ? HDA_AMP_MUTE : 0;
2785 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); 2788 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
2786} 2789}
@@ -3480,7 +3483,7 @@ static int alc_build_pcms(struct hda_codec *codec)
3480 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog), 3483 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
3481 "%s Analog", codec->chip_name); 3484 "%s Analog", codec->chip_name);
3482 info->name = spec->stream_name_analog; 3485 info->name = spec->stream_name_analog;
3483 3486
3484 if (spec->stream_analog_playback) { 3487 if (spec->stream_analog_playback) {
3485 if (snd_BUG_ON(!spec->multiout.dac_nids)) 3488 if (snd_BUG_ON(!spec->multiout.dac_nids))
3486 return -EINVAL; 3489 return -EINVAL;
@@ -4322,10 +4325,26 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
4322 knew->name = kstrdup(name, GFP_KERNEL); 4325 knew->name = kstrdup(name, GFP_KERNEL);
4323 if (!knew->name) 4326 if (!knew->name)
4324 return -ENOMEM; 4327 return -ENOMEM;
4328 if (get_amp_nid_(val))
4329 knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
4325 knew->private_value = val; 4330 knew->private_value = val;
4326 return 0; 4331 return 0;
4327} 4332}
4328 4333
4334static int add_control_with_pfx(struct alc_spec *spec, int type,
4335 const char *pfx, const char *dir,
4336 const char *sfx, unsigned long val)
4337{
4338 char name[32];
4339 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
4340 return add_control(spec, type, name, val);
4341}
4342
4343#define add_pb_vol_ctrl(spec, type, pfx, val) \
4344 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
4345#define add_pb_sw_ctrl(spec, type, pfx, val) \
4346 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
4347
4329#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 4348#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
4330#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 4349#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
4331#define alc880_is_multi_pin(nid) ((nid) >= 0x18) 4350#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
@@ -4379,7 +4398,6 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
4379static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, 4398static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4380 const struct auto_pin_cfg *cfg) 4399 const struct auto_pin_cfg *cfg)
4381{ 4400{
4382 char name[32];
4383 static const char *chname[4] = { 4401 static const char *chname[4] = {
4384 "Front", "Surround", NULL /*CLFE*/, "Side" 4402 "Front", "Surround", NULL /*CLFE*/, "Side"
4385 }; 4403 };
@@ -4392,26 +4410,26 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4392 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); 4410 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
4393 if (i == 2) { 4411 if (i == 2) {
4394 /* Center/LFE */ 4412 /* Center/LFE */
4395 err = add_control(spec, ALC_CTL_WIDGET_VOL, 4413 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4396 "Center Playback Volume", 4414 "Center",
4397 HDA_COMPOSE_AMP_VAL(nid, 1, 0, 4415 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
4398 HDA_OUTPUT)); 4416 HDA_OUTPUT));
4399 if (err < 0) 4417 if (err < 0)
4400 return err; 4418 return err;
4401 err = add_control(spec, ALC_CTL_WIDGET_VOL, 4419 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4402 "LFE Playback Volume", 4420 "LFE",
4403 HDA_COMPOSE_AMP_VAL(nid, 2, 0, 4421 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
4404 HDA_OUTPUT)); 4422 HDA_OUTPUT));
4405 if (err < 0) 4423 if (err < 0)
4406 return err; 4424 return err;
4407 err = add_control(spec, ALC_CTL_BIND_MUTE, 4425 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4408 "Center Playback Switch", 4426 "Center",
4409 HDA_COMPOSE_AMP_VAL(nid, 1, 2, 4427 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
4410 HDA_INPUT)); 4428 HDA_INPUT));
4411 if (err < 0) 4429 if (err < 0)
4412 return err; 4430 return err;
4413 err = add_control(spec, ALC_CTL_BIND_MUTE, 4431 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4414 "LFE Playback Switch", 4432 "LFE",
4415 HDA_COMPOSE_AMP_VAL(nid, 2, 2, 4433 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
4416 HDA_INPUT)); 4434 HDA_INPUT));
4417 if (err < 0) 4435 if (err < 0)
@@ -4423,14 +4441,12 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4423 pfx = "Speaker"; 4441 pfx = "Speaker";
4424 else 4442 else
4425 pfx = chname[i]; 4443 pfx = chname[i];
4426 sprintf(name, "%s Playback Volume", pfx); 4444 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
4427 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
4428 HDA_COMPOSE_AMP_VAL(nid, 3, 0, 4445 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
4429 HDA_OUTPUT)); 4446 HDA_OUTPUT));
4430 if (err < 0) 4447 if (err < 0)
4431 return err; 4448 return err;
4432 sprintf(name, "%s Playback Switch", pfx); 4449 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
4433 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4434 HDA_COMPOSE_AMP_VAL(nid, 3, 2, 4450 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
4435 HDA_INPUT)); 4451 HDA_INPUT));
4436 if (err < 0) 4452 if (err < 0)
@@ -4446,7 +4462,6 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4446{ 4462{
4447 hda_nid_t nid; 4463 hda_nid_t nid;
4448 int err; 4464 int err;
4449 char name[32];
4450 4465
4451 if (!pin) 4466 if (!pin)
4452 return 0; 4467 return 0;
@@ -4460,21 +4475,18 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4460 spec->multiout.extra_out_nid[0] = nid; 4475 spec->multiout.extra_out_nid[0] = nid;
4461 /* control HP volume/switch on the output mixer amp */ 4476 /* control HP volume/switch on the output mixer amp */
4462 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); 4477 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
4463 sprintf(name, "%s Playback Volume", pfx); 4478 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
4464 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
4465 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); 4479 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
4466 if (err < 0) 4480 if (err < 0)
4467 return err; 4481 return err;
4468 sprintf(name, "%s Playback Switch", pfx); 4482 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
4469 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4470 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 4483 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
4471 if (err < 0) 4484 if (err < 0)
4472 return err; 4485 return err;
4473 } else if (alc880_is_multi_pin(pin)) { 4486 } else if (alc880_is_multi_pin(pin)) {
4474 /* set manual connection */ 4487 /* set manual connection */
4475 /* we have only a switch on HP-out PIN */ 4488 /* we have only a switch on HP-out PIN */
4476 sprintf(name, "%s Playback Switch", pfx); 4489 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
4477 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
4478 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 4490 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4479 if (err < 0) 4491 if (err < 0)
4480 return err; 4492 return err;
@@ -4487,16 +4499,13 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
4487 const char *ctlname, 4499 const char *ctlname,
4488 int idx, hda_nid_t mix_nid) 4500 int idx, hda_nid_t mix_nid)
4489{ 4501{
4490 char name[32];
4491 int err; 4502 int err;
4492 4503
4493 sprintf(name, "%s Playback Volume", ctlname); 4504 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
4494 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
4495 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 4505 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4496 if (err < 0) 4506 if (err < 0)
4497 return err; 4507 return err;
4498 sprintf(name, "%s Playback Switch", ctlname); 4508 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
4499 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
4500 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 4509 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4501 if (err < 0) 4510 if (err < 0)
4502 return err; 4511 return err;
@@ -4773,8 +4782,12 @@ static void set_capture_mixer(struct hda_codec *codec)
4773 } 4782 }
4774} 4783}
4775 4784
4785#ifdef CONFIG_SND_HDA_INPUT_BEEP
4776#define set_beep_amp(spec, nid, idx, dir) \ 4786#define set_beep_amp(spec, nid, idx, dir) \
4777 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) 4787 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
4788#else
4789#define set_beep_amp(spec, nid, idx, dir) /* NOP */
4790#endif
4778 4791
4779/* 4792/*
4780 * OK, here we have finally the patch for ALC880 4793 * OK, here we have finally the patch for ALC880
@@ -5087,11 +5100,8 @@ static struct hda_verb alc260_hp_unsol_verbs[] = {
5087static void alc260_hp_automute(struct hda_codec *codec) 5100static void alc260_hp_automute(struct hda_codec *codec)
5088{ 5101{
5089 struct alc_spec *spec = codec->spec; 5102 struct alc_spec *spec = codec->spec;
5090 unsigned int present;
5091 5103
5092 present = snd_hda_codec_read(codec, 0x10, 0, 5104 spec->jack_present = snd_hda_jack_detect(codec, 0x10);
5093 AC_VERB_GET_PIN_SENSE, 0);
5094 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
5095 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11); 5105 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
5096} 5106}
5097 5107
@@ -5156,11 +5166,8 @@ static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
5156static void alc260_hp_3013_automute(struct hda_codec *codec) 5166static void alc260_hp_3013_automute(struct hda_codec *codec)
5157{ 5167{
5158 struct alc_spec *spec = codec->spec; 5168 struct alc_spec *spec = codec->spec;
5159 unsigned int present;
5160 5169
5161 present = snd_hda_codec_read(codec, 0x15, 0, 5170 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
5162 AC_VERB_GET_PIN_SENSE, 0);
5163 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
5164 alc260_hp_master_update(codec, 0x15, 0x10, 0x11); 5171 alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
5165} 5172}
5166 5173
@@ -5173,12 +5180,8 @@ static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
5173 5180
5174static void alc260_hp_3012_automute(struct hda_codec *codec) 5181static void alc260_hp_3012_automute(struct hda_codec *codec)
5175{ 5182{
5176 unsigned int present, bits; 5183 unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
5177
5178 present = snd_hda_codec_read(codec, 0x10, 0,
5179 AC_VERB_GET_PIN_SENSE, 0) & AC_PINSENSE_PRESENCE;
5180 5184
5181 bits = present ? 0 : PIN_OUT;
5182 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 5185 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5183 bits); 5186 bits);
5184 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 5187 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
@@ -5748,8 +5751,7 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec)
5748 unsigned int present; 5751 unsigned int present;
5749 5752
5750 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ 5753 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
5751 present = snd_hda_codec_read(codec, 0x0f, 0, 5754 present = snd_hda_jack_detect(codec, 0x0f);
5752 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5753 if (present) { 5755 if (present) {
5754 snd_hda_codec_write_cache(codec, 0x01, 0, 5756 snd_hda_codec_write_cache(codec, 0x01, 0,
5755 AC_VERB_SET_GPIO_DATA, 1); 5757 AC_VERB_SET_GPIO_DATA, 1);
@@ -5989,7 +5991,6 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
5989{ 5991{
5990 hda_nid_t nid_vol; 5992 hda_nid_t nid_vol;
5991 unsigned long vol_val, sw_val; 5993 unsigned long vol_val, sw_val;
5992 char name[32];
5993 int err; 5994 int err;
5994 5995
5995 if (nid >= 0x0f && nid < 0x11) { 5996 if (nid >= 0x0f && nid < 0x11) {
@@ -6009,14 +6010,12 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
6009 6010
6010 if (!(*vol_bits & (1 << nid_vol))) { 6011 if (!(*vol_bits & (1 << nid_vol))) {
6011 /* first control for the volume widget */ 6012 /* first control for the volume widget */
6012 snprintf(name, sizeof(name), "%s Playback Volume", pfx); 6013 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
6013 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
6014 if (err < 0) 6014 if (err < 0)
6015 return err; 6015 return err;
6016 *vol_bits |= (1 << nid_vol); 6016 *vol_bits |= (1 << nid_vol);
6017 } 6017 }
6018 snprintf(name, sizeof(name), "%s Playback Switch", pfx); 6018 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
6019 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
6020 if (err < 0) 6019 if (err < 0)
6021 return err; 6020 return err;
6022 return 1; 6021 return 1;
@@ -7336,8 +7335,8 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = {
7336 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), 7335 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
7337 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), 7336 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
7338 /* FIXME: this looks suspicious... 7337 /* FIXME: this looks suspicious...
7339 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), 7338 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
7340 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), 7339 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
7341 */ 7340 */
7342 { } /* end */ 7341 { } /* end */
7343}; 7342};
@@ -8184,12 +8183,8 @@ static void alc883_mitac_setup(struct hda_codec *codec)
8184/* 8183/*
8185static void alc883_mitac_mic_automute(struct hda_codec *codec) 8184static void alc883_mitac_mic_automute(struct hda_codec *codec)
8186{ 8185{
8187 unsigned int present; 8186 unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
8188 unsigned char bits;
8189 8187
8190 present = snd_hda_codec_read(codec, 0x18, 0,
8191 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8192 bits = present ? HDA_AMP_MUTE : 0;
8193 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); 8188 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
8194} 8189}
8195*/ 8190*/
@@ -8411,10 +8406,8 @@ static struct hda_channel_mode alc888_3st_hp_modes[3] = {
8411/* toggle front-jack and RCA according to the hp-jack state */ 8406/* toggle front-jack and RCA according to the hp-jack state */
8412static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) 8407static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
8413{ 8408{
8414 unsigned int present; 8409 unsigned int present = snd_hda_jack_detect(codec, 0x1b);
8415 8410
8416 present = snd_hda_codec_read(codec, 0x1b, 0,
8417 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8418 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 8411 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8419 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 8412 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8420 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8413 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
@@ -8424,10 +8417,8 @@ static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
8424/* toggle RCA according to the front-jack state */ 8417/* toggle RCA according to the front-jack state */
8425static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) 8418static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
8426{ 8419{
8427 unsigned int present; 8420 unsigned int present = snd_hda_jack_detect(codec, 0x14);
8428 8421
8429 present = snd_hda_codec_read(codec, 0x14, 0,
8430 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8431 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8422 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8432 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 8423 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8433} 8424}
@@ -8468,8 +8459,7 @@ static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
8468{ 8459{
8469 unsigned int present; 8460 unsigned int present;
8470 8461
8471 present = snd_hda_codec_read(codec, 0x18, 0, 8462 present = snd_hda_jack_detect(codec, 0x18);
8472 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8473 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, 8463 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
8474 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 8464 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8475} 8465}
@@ -8520,24 +8510,16 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
8520 8510
8521static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 8511static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
8522{ 8512{
8523 unsigned int present; 8513 int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
8524 unsigned char bits;
8525 8514
8526 present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
8527 & AC_PINSENSE_PRESENCE;
8528 bits = present ? HDA_AMP_MUTE : 0;
8529 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8515 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8530 HDA_AMP_MUTE, bits); 8516 HDA_AMP_MUTE, bits);
8531} 8517}
8532 8518
8533static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) 8519static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
8534{ 8520{
8535 unsigned int present; 8521 int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
8536 unsigned char bits;
8537 8522
8538 present = snd_hda_codec_read(codec, 0x1b, 0,
8539 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
8540 bits = present ? HDA_AMP_MUTE : 0;
8541 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8523 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8542 HDA_AMP_MUTE, bits); 8524 HDA_AMP_MUTE, bits);
8543 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 8525 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
@@ -8688,8 +8670,7 @@ static void alc889A_mb31_automute(struct hda_codec *codec)
8688 /* Mute only in 2ch or 4ch mode */ 8670 /* Mute only in 2ch or 4ch mode */
8689 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0) 8671 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
8690 == 0x00) { 8672 == 0x00) {
8691 present = snd_hda_codec_read(codec, 0x15, 0, 8673 present = snd_hda_jack_detect(codec, 0x15);
8692 AC_VERB_GET_PIN_SENSE, 0) & AC_PINSENSE_PRESENCE;
8693 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 8674 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8694 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 8675 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8695 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 8676 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
@@ -10032,10 +10013,8 @@ static void alc262_hp_master_update(struct hda_codec *codec)
10032static void alc262_hp_bpc_automute(struct hda_codec *codec) 10013static void alc262_hp_bpc_automute(struct hda_codec *codec)
10033{ 10014{
10034 struct alc_spec *spec = codec->spec; 10015 struct alc_spec *spec = codec->spec;
10035 unsigned int presence; 10016
10036 presence = snd_hda_codec_read(codec, 0x1b, 0, 10017 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
10037 AC_VERB_GET_PIN_SENSE, 0);
10038 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);
10039 alc262_hp_master_update(codec); 10018 alc262_hp_master_update(codec);
10040} 10019}
10041 10020
@@ -10049,10 +10028,8 @@ static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
10049static void alc262_hp_wildwest_automute(struct hda_codec *codec) 10028static void alc262_hp_wildwest_automute(struct hda_codec *codec)
10050{ 10029{
10051 struct alc_spec *spec = codec->spec; 10030 struct alc_spec *spec = codec->spec;
10052 unsigned int presence; 10031
10053 presence = snd_hda_codec_read(codec, 0x15, 0, 10032 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
10054 AC_VERB_GET_PIN_SENSE, 0);
10055 spec->jack_present = !!(presence & AC_PINSENSE_PRESENCE);
10056 alc262_hp_master_update(codec); 10033 alc262_hp_master_update(codec);
10057} 10034}
10058 10035
@@ -10286,13 +10263,8 @@ static void alc262_hippo_automute(struct hda_codec *codec)
10286{ 10263{
10287 struct alc_spec *spec = codec->spec; 10264 struct alc_spec *spec = codec->spec;
10288 hda_nid_t hp_nid = spec->autocfg.hp_pins[0]; 10265 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
10289 unsigned int present;
10290 10266
10291 /* need to execute and sync at first */ 10267 spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
10292 snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0);
10293 present = snd_hda_codec_read(codec, hp_nid, 0,
10294 AC_VERB_GET_PIN_SENSE, 0);
10295 spec->jack_present = (present & 0x80000000) != 0;
10296 alc262_hippo_master_update(codec); 10268 alc262_hippo_master_update(codec);
10297} 10269}
10298 10270
@@ -10618,21 +10590,8 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
10618 unsigned int mute; 10590 unsigned int mute;
10619 10591
10620 if (force || !spec->sense_updated) { 10592 if (force || !spec->sense_updated) {
10621 unsigned int present; 10593 spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
10622 /* need to execute and sync at first */ 10594 snd_hda_jack_detect(codec, 0x1b);
10623 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
10624 /* check laptop HP jack */
10625 present = snd_hda_codec_read(codec, 0x14, 0,
10626 AC_VERB_GET_PIN_SENSE, 0);
10627 /* need to execute and sync at first */
10628 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
10629 /* check docking HP jack */
10630 present |= snd_hda_codec_read(codec, 0x1b, 0,
10631 AC_VERB_GET_PIN_SENSE, 0);
10632 if (present & AC_PINSENSE_PRESENCE)
10633 spec->jack_present = 1;
10634 else
10635 spec->jack_present = 0;
10636 spec->sense_updated = 1; 10595 spec->sense_updated = 1;
10637 } 10596 }
10638 /* unmute internal speaker only if both HPs are unplugged and 10597 /* unmute internal speaker only if both HPs are unplugged and
@@ -10677,12 +10636,7 @@ static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
10677 unsigned int mute; 10636 unsigned int mute;
10678 10637
10679 if (force || !spec->sense_updated) { 10638 if (force || !spec->sense_updated) {
10680 unsigned int present_int_hp; 10639 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
10681 /* need to execute and sync at first */
10682 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
10683 present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
10684 AC_VERB_GET_PIN_SENSE, 0);
10685 spec->jack_present = (present_int_hp & 0x80000000) != 0;
10686 spec->sense_updated = 1; 10640 spec->sense_updated = 1;
10687 } 10641 }
10688 if (spec->jack_present) { 10642 if (spec->jack_present) {
@@ -10874,12 +10828,7 @@ static void alc262_ultra_automute(struct hda_codec *codec)
10874 mute = 0; 10828 mute = 0;
10875 /* auto-mute only when HP is used as HP */ 10829 /* auto-mute only when HP is used as HP */
10876 if (!spec->cur_mux[0]) { 10830 if (!spec->cur_mux[0]) {
10877 unsigned int present; 10831 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
10878 /* need to execute and sync at first */
10879 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
10880 present = snd_hda_codec_read(codec, 0x15, 0,
10881 AC_VERB_GET_PIN_SENSE, 0);
10882 spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
10883 if (spec->jack_present) 10832 if (spec->jack_present)
10884 mute = HDA_AMP_MUTE; 10833 mute = HDA_AMP_MUTE;
10885 } 10834 }
@@ -10956,7 +10905,6 @@ static int alc262_check_volbit(hda_nid_t nid)
10956static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, 10905static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
10957 const char *pfx, int *vbits) 10906 const char *pfx, int *vbits)
10958{ 10907{
10959 char name[32];
10960 unsigned long val; 10908 unsigned long val;
10961 int vbit; 10909 int vbit;
10962 10910
@@ -10966,28 +10914,25 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
10966 if (*vbits & vbit) /* a volume control for this mixer already there */ 10914 if (*vbits & vbit) /* a volume control for this mixer already there */
10967 return 0; 10915 return 0;
10968 *vbits |= vbit; 10916 *vbits |= vbit;
10969 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
10970 if (vbit == 2) 10917 if (vbit == 2)
10971 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); 10918 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
10972 else 10919 else
10973 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); 10920 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
10974 return add_control(spec, ALC_CTL_WIDGET_VOL, name, val); 10921 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
10975} 10922}
10976 10923
10977static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, 10924static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
10978 const char *pfx) 10925 const char *pfx)
10979{ 10926{
10980 char name[32];
10981 unsigned long val; 10927 unsigned long val;
10982 10928
10983 if (!nid) 10929 if (!nid)
10984 return 0; 10930 return 0;
10985 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
10986 if (nid == 0x16) 10931 if (nid == 0x16)
10987 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); 10932 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
10988 else 10933 else
10989 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 10934 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
10990 return add_control(spec, ALC_CTL_WIDGET_MUTE, name, val); 10935 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
10991} 10936}
10992 10937
10993/* add playback controls from the parsed DAC table */ 10938/* add playback controls from the parsed DAC table */
@@ -11463,8 +11408,10 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
11463 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06), 11408 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
11464 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO), 11409 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
11465 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO), 11410 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
11411#if 0 /* disable the quirk since model=auto works better in recent versions */
11466 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO", 11412 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
11467 ALC262_SONY_ASSAMD), 11413 ALC262_SONY_ASSAMD),
11414#endif
11468 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", 11415 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
11469 ALC262_TOSHIBA_RX1), 11416 ALC262_TOSHIBA_RX1),
11470 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), 11417 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
@@ -11923,10 +11870,7 @@ static void alc268_acer_automute(struct hda_codec *codec, int force)
11923 unsigned int mute; 11870 unsigned int mute;
11924 11871
11925 if (force || !spec->sense_updated) { 11872 if (force || !spec->sense_updated) {
11926 unsigned int present; 11873 spec->jack_present = snd_hda_jack_detect(codec, 0x14);
11927 present = snd_hda_codec_read(codec, 0x14, 0,
11928 AC_VERB_GET_PIN_SENSE, 0);
11929 spec->jack_present = (present & 0x80000000) != 0;
11930 spec->sense_updated = 1; 11874 spec->sense_updated = 1;
11931 } 11875 }
11932 if (spec->jack_present) 11876 if (spec->jack_present)
@@ -12045,8 +11989,7 @@ static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
12045 unsigned int present; 11989 unsigned int present;
12046 unsigned char bits; 11990 unsigned char bits;
12047 11991
12048 present = snd_hda_codec_read(codec, 0x15, 0, 11992 present = snd_hda_jack_detect(codec, 0x15);
12049 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
12050 bits = present ? AMP_IN_MUTE(0) : 0; 11993 bits = present ? AMP_IN_MUTE(0) : 0;
12051 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0, 11994 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
12052 AMP_IN_MUTE(0), bits); 11995 AMP_IN_MUTE(0), bits);
@@ -12327,11 +12270,9 @@ static struct snd_kcontrol_new alc268_test_mixer[] = {
12327static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, 12270static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
12328 const char *ctlname, int idx) 12271 const char *ctlname, int idx)
12329{ 12272{
12330 char name[32];
12331 hda_nid_t dac; 12273 hda_nid_t dac;
12332 int err; 12274 int err;
12333 12275
12334 sprintf(name, "%s Playback Volume", ctlname);
12335 switch (nid) { 12276 switch (nid) {
12336 case 0x14: 12277 case 0x14:
12337 case 0x16: 12278 case 0x16:
@@ -12345,7 +12286,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
12345 } 12286 }
12346 if (spec->multiout.dac_nids[0] != dac && 12287 if (spec->multiout.dac_nids[0] != dac &&
12347 spec->multiout.dac_nids[1] != dac) { 12288 spec->multiout.dac_nids[1] != dac) {
12348 err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 12289 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
12349 HDA_COMPOSE_AMP_VAL(dac, 3, idx, 12290 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
12350 HDA_OUTPUT)); 12291 HDA_OUTPUT));
12351 if (err < 0) 12292 if (err < 0)
@@ -12353,12 +12294,11 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
12353 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; 12294 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
12354 } 12295 }
12355 12296
12356 sprintf(name, "%s Playback Switch", ctlname);
12357 if (nid != 0x16) 12297 if (nid != 0x16)
12358 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 12298 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
12359 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); 12299 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
12360 else /* mono */ 12300 else /* mono */
12361 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 12301 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
12362 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT)); 12302 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
12363 if (err < 0) 12303 if (err < 0)
12364 return err; 12304 return err;
@@ -12388,8 +12328,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
12388 12328
12389 nid = cfg->speaker_pins[0]; 12329 nid = cfg->speaker_pins[0];
12390 if (nid == 0x1d) { 12330 if (nid == 0x1d) {
12391 err = add_control(spec, ALC_CTL_WIDGET_VOL, 12331 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
12392 "Speaker Playback Volume",
12393 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 12332 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
12394 if (err < 0) 12333 if (err < 0)
12395 return err; 12334 return err;
@@ -12407,8 +12346,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
12407 12346
12408 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2]; 12347 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
12409 if (nid == 0x16) { 12348 if (nid == 0x16) {
12410 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 12349 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
12411 "Mono Playback Switch",
12412 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT)); 12350 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
12413 if (err < 0) 12351 if (err < 0)
12414 return err; 12352 return err;
@@ -13034,8 +12972,7 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
13034 unsigned int present; 12972 unsigned int present;
13035 unsigned char bits; 12973 unsigned char bits;
13036 12974
13037 present = snd_hda_codec_read(codec, 0x15, 0, 12975 present = snd_hda_jack_detect(codec, 0x15);
13038 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13039 bits = present ? AMP_IN_MUTE(0) : 0; 12976 bits = present ? AMP_IN_MUTE(0) : 0;
13040 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 12977 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
13041 AMP_IN_MUTE(0), bits); 12978 AMP_IN_MUTE(0), bits);
@@ -13060,12 +12997,10 @@ static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
13060 unsigned char bits; 12997 unsigned char bits;
13061 12998
13062 /* Check laptop headphone socket */ 12999 /* Check laptop headphone socket */
13063 present = snd_hda_codec_read(codec, 0x15, 0, 13000 present = snd_hda_jack_detect(codec, 0x15);
13064 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13065 13001
13066 /* Check port replicator headphone socket */ 13002 /* Check port replicator headphone socket */
13067 present |= snd_hda_codec_read(codec, 0x1a, 0, 13003 present |= snd_hda_jack_detect(codec, 0x1a);
13068 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13069 13004
13070 bits = present ? AMP_IN_MUTE(0) : 0; 13005 bits = present ? AMP_IN_MUTE(0) : 0;
13071 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 13006 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
@@ -13089,11 +13024,8 @@ static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
13089 unsigned int present_laptop; 13024 unsigned int present_laptop;
13090 unsigned int present_dock; 13025 unsigned int present_dock;
13091 13026
13092 present_laptop = snd_hda_codec_read(codec, 0x18, 0, 13027 present_laptop = snd_hda_jack_detect(codec, 0x18);
13093 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 13028 present_dock = snd_hda_jack_detect(codec, 0x1b);
13094
13095 present_dock = snd_hda_codec_read(codec, 0x1b, 0,
13096 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13097 13029
13098 /* Laptop mic port overrides dock mic port, design decision */ 13030 /* Laptop mic port overrides dock mic port, design decision */
13099 if (present_dock) 13031 if (present_dock)
@@ -13178,8 +13110,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
13178 unsigned int present; 13110 unsigned int present;
13179 unsigned char bits; 13111 unsigned char bits;
13180 13112
13181 present = snd_hda_codec_read(codec, 0x15, 0, 13113 present = snd_hda_jack_detect(codec, 0x15);
13182 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
13183 bits = present ? AMP_IN_MUTE(0) : 0; 13114 bits = present ? AMP_IN_MUTE(0) : 0;
13184 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 13115 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
13185 AMP_IN_MUTE(0), bits); 13116 AMP_IN_MUTE(0), bits);
@@ -13525,6 +13456,15 @@ static int patch_alc269(struct hda_codec *codec)
13525 13456
13526 alc_fix_pll_init(codec, 0x20, 0x04, 15); 13457 alc_fix_pll_init(codec, 0x20, 0x04, 15);
13527 13458
13459 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
13460 kfree(codec->chip_name);
13461 codec->chip_name = kstrdup("ALC259", GFP_KERNEL);
13462 if (!codec->chip_name) {
13463 alc_free(codec);
13464 return -ENOMEM;
13465 }
13466 }
13467
13528 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, 13468 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
13529 alc269_models, 13469 alc269_models,
13530 alc269_cfg_tbl); 13470 alc269_cfg_tbl);
@@ -14157,10 +14097,8 @@ static struct hda_verb alc861_toshiba_init_verbs[] = {
14157/* toggle speaker-output according to the hp-jack state */ 14097/* toggle speaker-output according to the hp-jack state */
14158static void alc861_toshiba_automute(struct hda_codec *codec) 14098static void alc861_toshiba_automute(struct hda_codec *codec)
14159{ 14099{
14160 unsigned int present; 14100 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
14161 14101
14162 present = snd_hda_codec_read(codec, 0x0f, 0,
14163 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
14164 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0, 14102 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
14165 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 14103 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
14166 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3, 14104 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
@@ -14260,9 +14198,7 @@ static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
14260static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx, 14198static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
14261 hda_nid_t nid, unsigned int chs) 14199 hda_nid_t nid, unsigned int chs)
14262{ 14200{
14263 char name[32]; 14201 return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx,
14264 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
14265 return add_control(codec->spec, ALC_CTL_WIDGET_MUTE, name,
14266 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); 14202 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
14267} 14203}
14268 14204
@@ -14627,6 +14563,27 @@ static struct alc_config_preset alc861_presets[] = {
14627 }, 14563 },
14628}; 14564};
14629 14565
14566/* Pin config fixes */
14567enum {
14568 PINFIX_FSC_AMILO_PI1505,
14569};
14570
14571static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = {
14572 { 0x0b, 0x0221101f }, /* HP */
14573 { 0x0f, 0x90170310 }, /* speaker */
14574 { }
14575};
14576
14577static const struct alc_fixup alc861_fixups[] = {
14578 [PINFIX_FSC_AMILO_PI1505] = {
14579 .pins = alc861_fsc_amilo_pi1505_pinfix
14580 },
14581};
14582
14583static struct snd_pci_quirk alc861_fixup_tbl[] = {
14584 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
14585 {}
14586};
14630 14587
14631static int patch_alc861(struct hda_codec *codec) 14588static int patch_alc861(struct hda_codec *codec)
14632{ 14589{
@@ -14650,6 +14607,8 @@ static int patch_alc861(struct hda_codec *codec)
14650 board_config = ALC861_AUTO; 14607 board_config = ALC861_AUTO;
14651 } 14608 }
14652 14609
14610 alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups);
14611
14653 if (board_config == ALC861_AUTO) { 14612 if (board_config == ALC861_AUTO) {
14654 /* automatic parse from the BIOS config */ 14613 /* automatic parse from the BIOS config */
14655 err = alc861_parse_auto_config(codec); 14614 err = alc861_parse_auto_config(codec);
@@ -15067,9 +15026,9 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
15067 unsigned int present; 15026 unsigned int present;
15068 unsigned char bits; 15027 unsigned char bits;
15069 15028
15070 present = snd_hda_codec_read(codec, 0x18, 0, 15029 present = snd_hda_jack_detect(codec, 0x18);
15071 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
15072 bits = present ? HDA_AMP_MUTE : 0; 15030 bits = present ? HDA_AMP_MUTE : 0;
15031
15073 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, 15032 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
15074 HDA_AMP_MUTE, bits); 15033 HDA_AMP_MUTE, bits);
15075} 15034}
@@ -15386,7 +15345,6 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
15386static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, 15345static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
15387 const struct auto_pin_cfg *cfg) 15346 const struct auto_pin_cfg *cfg)
15388{ 15347{
15389 char name[32];
15390 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; 15348 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
15391 hda_nid_t nid_v, nid_s; 15349 hda_nid_t nid_v, nid_s;
15392 int i, err; 15350 int i, err;
@@ -15403,26 +15361,26 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
15403 15361
15404 if (i == 2) { 15362 if (i == 2) {
15405 /* Center/LFE */ 15363 /* Center/LFE */
15406 err = add_control(spec, ALC_CTL_WIDGET_VOL, 15364 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
15407 "Center Playback Volume", 15365 "Center",
15408 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, 15366 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
15409 HDA_OUTPUT)); 15367 HDA_OUTPUT));
15410 if (err < 0) 15368 if (err < 0)
15411 return err; 15369 return err;
15412 err = add_control(spec, ALC_CTL_WIDGET_VOL, 15370 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
15413 "LFE Playback Volume", 15371 "LFE",
15414 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, 15372 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
15415 HDA_OUTPUT)); 15373 HDA_OUTPUT));
15416 if (err < 0) 15374 if (err < 0)
15417 return err; 15375 return err;
15418 err = add_control(spec, ALC_CTL_BIND_MUTE, 15376 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
15419 "Center Playback Switch", 15377 "Center",
15420 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, 15378 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
15421 HDA_INPUT)); 15379 HDA_INPUT));
15422 if (err < 0) 15380 if (err < 0)
15423 return err; 15381 return err;
15424 err = add_control(spec, ALC_CTL_BIND_MUTE, 15382 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
15425 "LFE Playback Switch", 15383 "LFE",
15426 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, 15384 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
15427 HDA_INPUT)); 15385 HDA_INPUT));
15428 if (err < 0) 15386 if (err < 0)
@@ -15437,8 +15395,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
15437 pfx = "PCM"; 15395 pfx = "PCM";
15438 } else 15396 } else
15439 pfx = chname[i]; 15397 pfx = chname[i];
15440 sprintf(name, "%s Playback Volume", pfx); 15398 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
15441 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
15442 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, 15399 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
15443 HDA_OUTPUT)); 15400 HDA_OUTPUT));
15444 if (err < 0) 15401 if (err < 0)
@@ -15446,8 +15403,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
15446 if (cfg->line_outs == 1 && 15403 if (cfg->line_outs == 1 &&
15447 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 15404 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
15448 pfx = "Speaker"; 15405 pfx = "Speaker";
15449 sprintf(name, "%s Playback Switch", pfx); 15406 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
15450 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
15451 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, 15407 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
15452 HDA_INPUT)); 15408 HDA_INPUT));
15453 if (err < 0) 15409 if (err < 0)
@@ -15465,7 +15421,6 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
15465{ 15421{
15466 hda_nid_t nid_v, nid_s; 15422 hda_nid_t nid_v, nid_s;
15467 int err; 15423 int err;
15468 char name[32];
15469 15424
15470 if (!pin) 15425 if (!pin)
15471 return 0; 15426 return 0;
@@ -15483,21 +15438,18 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
15483 nid_s = alc861vd_idx_to_mixer_switch( 15438 nid_s = alc861vd_idx_to_mixer_switch(
15484 alc880_fixed_pin_idx(pin)); 15439 alc880_fixed_pin_idx(pin));
15485 15440
15486 sprintf(name, "%s Playback Volume", pfx); 15441 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
15487 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
15488 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); 15442 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
15489 if (err < 0) 15443 if (err < 0)
15490 return err; 15444 return err;
15491 sprintf(name, "%s Playback Switch", pfx); 15445 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
15492 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
15493 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); 15446 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
15494 if (err < 0) 15447 if (err < 0)
15495 return err; 15448 return err;
15496 } else if (alc880_is_multi_pin(pin)) { 15449 } else if (alc880_is_multi_pin(pin)) {
15497 /* set manual connection */ 15450 /* set manual connection */
15498 /* we have only a switch on HP-out PIN */ 15451 /* we have only a switch on HP-out PIN */
15499 sprintf(name, "%s Playback Switch", pfx); 15452 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
15500 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
15501 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 15453 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
15502 if (err < 0) 15454 if (err < 0)
15503 return err; 15455 return err;
@@ -16387,9 +16339,9 @@ static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
16387 unsigned int present; 16339 unsigned int present;
16388 unsigned char bits; 16340 unsigned char bits;
16389 16341
16390 present = snd_hda_codec_read(codec, 0x14, 0, 16342 present = snd_hda_jack_detect(codec, 0x14);
16391 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
16392 bits = present ? HDA_AMP_MUTE : 0; 16343 bits = present ? HDA_AMP_MUTE : 0;
16344
16393 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 16345 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
16394 HDA_AMP_MUTE, bits); 16346 HDA_AMP_MUTE, bits);
16395} 16347}
@@ -16399,9 +16351,9 @@ static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
16399 unsigned int present; 16351 unsigned int present;
16400 unsigned char bits; 16352 unsigned char bits;
16401 16353
16402 present = snd_hda_codec_read(codec, 0x1b, 0, 16354 present = snd_hda_jack_detect(codec, 0x1b);
16403 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
16404 bits = present ? HDA_AMP_MUTE : 0; 16355 bits = present ? HDA_AMP_MUTE : 0;
16356
16405 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 16357 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
16406 HDA_AMP_MUTE, bits); 16358 HDA_AMP_MUTE, bits);
16407 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 16359 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
@@ -16460,9 +16412,7 @@ static void alc663_m51va_speaker_automute(struct hda_codec *codec)
16460 unsigned int present; 16412 unsigned int present;
16461 unsigned char bits; 16413 unsigned char bits;
16462 16414
16463 present = snd_hda_codec_read(codec, 0x21, 0, 16415 present = snd_hda_jack_detect(codec, 0x21);
16464 AC_VERB_GET_PIN_SENSE, 0)
16465 & AC_PINSENSE_PRESENCE;
16466 bits = present ? HDA_AMP_MUTE : 0; 16416 bits = present ? HDA_AMP_MUTE : 0;
16467 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 16417 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
16468 AMP_IN_MUTE(0), bits); 16418 AMP_IN_MUTE(0), bits);
@@ -16475,9 +16425,7 @@ static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
16475 unsigned int present; 16425 unsigned int present;
16476 unsigned char bits; 16426 unsigned char bits;
16477 16427
16478 present = snd_hda_codec_read(codec, 0x21, 0, 16428 present = snd_hda_jack_detect(codec, 0x21);
16479 AC_VERB_GET_PIN_SENSE, 0)
16480 & AC_PINSENSE_PRESENCE;
16481 bits = present ? HDA_AMP_MUTE : 0; 16429 bits = present ? HDA_AMP_MUTE : 0;
16482 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 16430 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
16483 AMP_IN_MUTE(0), bits); 16431 AMP_IN_MUTE(0), bits);
@@ -16494,9 +16442,7 @@ static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
16494 unsigned int present; 16442 unsigned int present;
16495 unsigned char bits; 16443 unsigned char bits;
16496 16444
16497 present = snd_hda_codec_read(codec, 0x15, 0, 16445 present = snd_hda_jack_detect(codec, 0x15);
16498 AC_VERB_GET_PIN_SENSE, 0)
16499 & AC_PINSENSE_PRESENCE;
16500 bits = present ? HDA_AMP_MUTE : 0; 16446 bits = present ? HDA_AMP_MUTE : 0;
16501 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 16447 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
16502 AMP_IN_MUTE(0), bits); 16448 AMP_IN_MUTE(0), bits);
@@ -16513,9 +16459,7 @@ static void alc662_f5z_speaker_automute(struct hda_codec *codec)
16513 unsigned int present; 16459 unsigned int present;
16514 unsigned char bits; 16460 unsigned char bits;
16515 16461
16516 present = snd_hda_codec_read(codec, 0x1b, 0, 16462 present = snd_hda_jack_detect(codec, 0x1b);
16517 AC_VERB_GET_PIN_SENSE, 0)
16518 & AC_PINSENSE_PRESENCE;
16519 bits = present ? 0 : PIN_OUT; 16463 bits = present ? 0 : PIN_OUT;
16520 snd_hda_codec_write(codec, 0x14, 0, 16464 snd_hda_codec_write(codec, 0x14, 0,
16521 AC_VERB_SET_PIN_WIDGET_CONTROL, bits); 16465 AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
@@ -16525,12 +16469,8 @@ static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
16525{ 16469{
16526 unsigned int present1, present2; 16470 unsigned int present1, present2;
16527 16471
16528 present1 = snd_hda_codec_read(codec, 0x21, 0, 16472 present1 = snd_hda_jack_detect(codec, 0x21);
16529 AC_VERB_GET_PIN_SENSE, 0) 16473 present2 = snd_hda_jack_detect(codec, 0x15);
16530 & AC_PINSENSE_PRESENCE;
16531 present2 = snd_hda_codec_read(codec, 0x15, 0,
16532 AC_VERB_GET_PIN_SENSE, 0)
16533 & AC_PINSENSE_PRESENCE;
16534 16474
16535 if (present1 || present2) { 16475 if (present1 || present2) {
16536 snd_hda_codec_write_cache(codec, 0x14, 0, 16476 snd_hda_codec_write_cache(codec, 0x14, 0,
@@ -16545,12 +16485,8 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
16545{ 16485{
16546 unsigned int present1, present2; 16486 unsigned int present1, present2;
16547 16487
16548 present1 = snd_hda_codec_read(codec, 0x1b, 0, 16488 present1 = snd_hda_jack_detect(codec, 0x1b);
16549 AC_VERB_GET_PIN_SENSE, 0) 16489 present2 = snd_hda_jack_detect(codec, 0x15);
16550 & AC_PINSENSE_PRESENCE;
16551 present2 = snd_hda_codec_read(codec, 0x15, 0,
16552 AC_VERB_GET_PIN_SENSE, 0)
16553 & AC_PINSENSE_PRESENCE;
16554 16490
16555 if (present1 || present2) { 16491 if (present1 || present2) {
16556 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, 16492 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
@@ -16710,9 +16646,7 @@ static void alc663_g71v_hp_automute(struct hda_codec *codec)
16710 unsigned int present; 16646 unsigned int present;
16711 unsigned char bits; 16647 unsigned char bits;
16712 16648
16713 present = snd_hda_codec_read(codec, 0x21, 0, 16649 present = snd_hda_jack_detect(codec, 0x21);
16714 AC_VERB_GET_PIN_SENSE, 0)
16715 & AC_PINSENSE_PRESENCE;
16716 bits = present ? HDA_AMP_MUTE : 0; 16650 bits = present ? HDA_AMP_MUTE : 0;
16717 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 16651 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
16718 HDA_AMP_MUTE, bits); 16652 HDA_AMP_MUTE, bits);
@@ -16725,9 +16659,7 @@ static void alc663_g71v_front_automute(struct hda_codec *codec)
16725 unsigned int present; 16659 unsigned int present;
16726 unsigned char bits; 16660 unsigned char bits;
16727 16661
16728 present = snd_hda_codec_read(codec, 0x15, 0, 16662 present = snd_hda_jack_detect(codec, 0x15);
16729 AC_VERB_GET_PIN_SENSE, 0)
16730 & AC_PINSENSE_PRESENCE;
16731 bits = present ? HDA_AMP_MUTE : 0; 16663 bits = present ? HDA_AMP_MUTE : 0;
16732 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 16664 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
16733 HDA_AMP_MUTE, bits); 16665 HDA_AMP_MUTE, bits);
@@ -17264,21 +17196,17 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
17264 return 0; 17196 return 0;
17265} 17197}
17266 17198
17267static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, 17199static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
17268 hda_nid_t nid, unsigned int chs) 17200 hda_nid_t nid, unsigned int chs)
17269{ 17201{
17270 char name[32]; 17202 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
17271 sprintf(name, "%s Playback Volume", pfx);
17272 return add_control(spec, ALC_CTL_WIDGET_VOL, name,
17273 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); 17203 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
17274} 17204}
17275 17205
17276static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, 17206static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
17277 hda_nid_t nid, unsigned int chs) 17207 hda_nid_t nid, unsigned int chs)
17278{ 17208{
17279 char name[32]; 17209 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
17280 sprintf(name, "%s Playback Switch", pfx);
17281 return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17282 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); 17210 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
17283} 17211}
17284 17212
@@ -17356,13 +17284,11 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
17356 return 0; 17284 return 0;
17357 nid = alc662_look_for_dac(codec, pin); 17285 nid = alc662_look_for_dac(codec, pin);
17358 if (!nid) { 17286 if (!nid) {
17359 char name[32];
17360 /* the corresponding DAC is already occupied */ 17287 /* the corresponding DAC is already occupied */
17361 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) 17288 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
17362 return 0; /* no way */ 17289 return 0; /* no way */
17363 /* create a switch only */ 17290 /* create a switch only */
17364 sprintf(name, "%s Playback Switch", pfx); 17291 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
17365 return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17366 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 17292 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17367 } 17293 }
17368 17294
@@ -17538,6 +17464,15 @@ static int patch_alc662(struct hda_codec *codec)
17538 17464
17539 alc_fix_pll_init(codec, 0x20, 0x04, 15); 17465 alc_fix_pll_init(codec, 0x20, 0x04, 15);
17540 17466
17467 if (alc_read_coef_idx(codec, 0)==0x8020){
17468 kfree(codec->chip_name);
17469 codec->chip_name = kstrdup("ALC661", GFP_KERNEL);
17470 if (!codec->chip_name) {
17471 alc_free(codec);
17472 return -ENOMEM;
17473 }
17474 }
17475
17541 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 17476 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
17542 alc662_models, 17477 alc662_models,
17543 alc662_cfg_tbl); 17478 alc662_cfg_tbl);
@@ -17604,6 +17539,20 @@ static int patch_alc662(struct hda_codec *codec)
17604 return 0; 17539 return 0;
17605} 17540}
17606 17541
17542static int patch_alc888(struct hda_codec *codec)
17543{
17544 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
17545 kfree(codec->chip_name);
17546 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
17547 if (!codec->chip_name) {
17548 alc_free(codec);
17549 return -ENOMEM;
17550 }
17551 return patch_alc662(codec);
17552 }
17553 return patch_alc882(codec);
17554}
17555
17607/* 17556/*
17608 * patch entries 17557 * patch entries
17609 */ 17558 */
@@ -17635,8 +17584,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
17635 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 }, 17584 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
17636 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", 17585 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
17637 .patch = patch_alc882 }, 17586 .patch = patch_alc882 },
17638 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 }, 17587 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
17639 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, 17588 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
17589 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
17640 {} /* terminator */ 17590 {} /* terminator */
17641}; 17591};
17642 17592
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 86de305fc9f2..6b0bc040c3b1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -93,6 +93,7 @@ enum {
93 STAC_92HD83XXX_REF, 93 STAC_92HD83XXX_REF,
94 STAC_92HD83XXX_PWR_REF, 94 STAC_92HD83XXX_PWR_REF,
95 STAC_DELL_S14, 95 STAC_DELL_S14,
96 STAC_92HD83XXX_HP,
96 STAC_92HD83XXX_MODELS 97 STAC_92HD83XXX_MODELS
97}; 98};
98 99
@@ -1085,7 +1086,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1085 if (!spec->auto_mic && spec->num_dmuxes > 0 && 1086 if (!spec->auto_mic && spec->num_dmuxes > 0 &&
1086 snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { 1087 snd_hda_get_bool_hint(codec, "separate_dmux") == 1) {
1087 stac_dmux_mixer.count = spec->num_dmuxes; 1088 stac_dmux_mixer.count = spec->num_dmuxes;
1088 err = snd_hda_ctl_add(codec, 1089 err = snd_hda_ctl_add(codec, 0,
1089 snd_ctl_new1(&stac_dmux_mixer, codec)); 1090 snd_ctl_new1(&stac_dmux_mixer, codec));
1090 if (err < 0) 1091 if (err < 0)
1091 return err; 1092 return err;
@@ -1101,7 +1102,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1101 spec->spdif_mute = 1; 1102 spec->spdif_mute = 1;
1102 } 1103 }
1103 stac_smux_mixer.count = spec->num_smuxes; 1104 stac_smux_mixer.count = spec->num_smuxes;
1104 err = snd_hda_ctl_add(codec, 1105 err = snd_hda_ctl_add(codec, 0,
1105 snd_ctl_new1(&stac_smux_mixer, codec)); 1106 snd_ctl_new1(&stac_smux_mixer, codec));
1106 if (err < 0) 1107 if (err < 0)
1107 return err; 1108 return err;
@@ -1624,6 +1625,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
1624 [STAC_92HD83XXX_REF] = "ref", 1625 [STAC_92HD83XXX_REF] = "ref",
1625 [STAC_92HD83XXX_PWR_REF] = "mic-ref", 1626 [STAC_92HD83XXX_PWR_REF] = "mic-ref",
1626 [STAC_DELL_S14] = "dell-s14", 1627 [STAC_DELL_S14] = "dell-s14",
1628 [STAC_92HD83XXX_HP] = "hp",
1627}; 1629};
1628 1630
1629static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { 1631static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1634,6 +1636,8 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
1634 "DFI LanParty", STAC_92HD83XXX_REF), 1636 "DFI LanParty", STAC_92HD83XXX_REF),
1635 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, 1637 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
1636 "unknown Dell", STAC_DELL_S14), 1638 "unknown Dell", STAC_DELL_S14),
1639 SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
1640 "HP", STAC_92HD83XXX_HP),
1637 {} /* terminator */ 1641 {} /* terminator */
1638}; 1642};
1639 1643
@@ -2648,6 +2652,7 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
2648enum { 2652enum {
2649 STAC_CTL_WIDGET_VOL, 2653 STAC_CTL_WIDGET_VOL,
2650 STAC_CTL_WIDGET_MUTE, 2654 STAC_CTL_WIDGET_MUTE,
2655 STAC_CTL_WIDGET_MUTE_BEEP,
2651 STAC_CTL_WIDGET_MONO_MUX, 2656 STAC_CTL_WIDGET_MONO_MUX,
2652 STAC_CTL_WIDGET_HP_SWITCH, 2657 STAC_CTL_WIDGET_HP_SWITCH,
2653 STAC_CTL_WIDGET_IO_SWITCH, 2658 STAC_CTL_WIDGET_IO_SWITCH,
@@ -2658,6 +2663,7 @@ enum {
2658static struct snd_kcontrol_new stac92xx_control_templates[] = { 2663static struct snd_kcontrol_new stac92xx_control_templates[] = {
2659 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2664 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2660 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2665 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2666 HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0),
2661 STAC_MONO_MUX, 2667 STAC_MONO_MUX,
2662 STAC_CODEC_HP_SWITCH(NULL), 2668 STAC_CODEC_HP_SWITCH(NULL),
2663 STAC_CODEC_IO_SWITCH(NULL, 0), 2669 STAC_CODEC_IO_SWITCH(NULL, 0),
@@ -2669,7 +2675,8 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
2669static struct snd_kcontrol_new * 2675static struct snd_kcontrol_new *
2670stac_control_new(struct sigmatel_spec *spec, 2676stac_control_new(struct sigmatel_spec *spec,
2671 struct snd_kcontrol_new *ktemp, 2677 struct snd_kcontrol_new *ktemp,
2672 const char *name) 2678 const char *name,
2679 hda_nid_t nid)
2673{ 2680{
2674 struct snd_kcontrol_new *knew; 2681 struct snd_kcontrol_new *knew;
2675 2682
@@ -2685,6 +2692,8 @@ stac_control_new(struct sigmatel_spec *spec,
2685 spec->kctls.alloced--; 2692 spec->kctls.alloced--;
2686 return NULL; 2693 return NULL;
2687 } 2694 }
2695 if (nid)
2696 knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
2688 return knew; 2697 return knew;
2689} 2698}
2690 2699
@@ -2693,7 +2702,8 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
2693 int idx, const char *name, 2702 int idx, const char *name,
2694 unsigned long val) 2703 unsigned long val)
2695{ 2704{
2696 struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); 2705 struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name,
2706 get_amp_nid_(val));
2697 if (!knew) 2707 if (!knew)
2698 return -ENOMEM; 2708 return -ENOMEM;
2699 knew->index = idx; 2709 knew->index = idx;
@@ -2764,7 +2774,7 @@ static int stac92xx_add_input_source(struct sigmatel_spec *spec)
2764 if (!spec->num_adcs || imux->num_items <= 1) 2774 if (!spec->num_adcs || imux->num_items <= 1)
2765 return 0; /* no need for input source control */ 2775 return 0; /* no need for input source control */
2766 knew = stac_control_new(spec, &stac_input_src_temp, 2776 knew = stac_control_new(spec, &stac_input_src_temp,
2767 stac_input_src_temp.name); 2777 stac_input_src_temp.name, 0);
2768 if (!knew) 2778 if (!knew)
2769 return -ENOMEM; 2779 return -ENOMEM;
2770 knew->count = spec->num_adcs; 2780 knew->count = spec->num_adcs;
@@ -3221,12 +3231,15 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
3221{ 3231{
3222 struct sigmatel_spec *spec = codec->spec; 3232 struct sigmatel_spec *spec = codec->spec;
3223 u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); 3233 u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
3224 int err; 3234 int err, type = STAC_CTL_WIDGET_MUTE_BEEP;
3235
3236 if (spec->anabeep_nid == nid)
3237 type = STAC_CTL_WIDGET_MUTE;
3225 3238
3226 /* check for mute support for the the amp */ 3239 /* check for mute support for the the amp */
3227 if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { 3240 if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) {
3228 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, 3241 err = stac92xx_add_control(spec, type,
3229 "PC Beep Playback Switch", 3242 "Beep Playback Switch",
3230 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); 3243 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT));
3231 if (err < 0) 3244 if (err < 0)
3232 return err; 3245 return err;
@@ -3235,7 +3248,7 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
3235 /* check to see if there is volume support for the amp */ 3248 /* check to see if there is volume support for the amp */
3236 if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { 3249 if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) {
3237 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, 3250 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL,
3238 "PC Beep Playback Volume", 3251 "Beep Playback Volume",
3239 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); 3252 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT));
3240 if (err < 0) 3253 if (err < 0)
3241 return err; 3254 return err;
@@ -3258,12 +3271,7 @@ static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
3258 struct snd_ctl_elem_value *ucontrol) 3271 struct snd_ctl_elem_value *ucontrol)
3259{ 3272{
3260 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3273 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3261 int enabled = !!ucontrol->value.integer.value[0]; 3274 return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]);
3262 if (codec->beep->enabled != enabled) {
3263 codec->beep->enabled = enabled;
3264 return 1;
3265 }
3266 return 0;
3267} 3275}
3268 3276
3269static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { 3277static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
@@ -3276,7 +3284,7 @@ static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
3276static int stac92xx_beep_switch_ctl(struct hda_codec *codec) 3284static int stac92xx_beep_switch_ctl(struct hda_codec *codec)
3277{ 3285{
3278 return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl, 3286 return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl,
3279 0, "PC Beep Playback Switch", 0); 3287 0, "Beep Playback Switch", 0);
3280} 3288}
3281#endif 3289#endif
3282 3290
@@ -3631,6 +3639,26 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
3631 } 3639 }
3632} 3640}
3633 3641
3642static int is_dual_headphones(struct hda_codec *codec)
3643{
3644 struct sigmatel_spec *spec = codec->spec;
3645 int i, valid_hps;
3646
3647 if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT ||
3648 spec->autocfg.hp_outs <= 1)
3649 return 0;
3650 valid_hps = 0;
3651 for (i = 0; i < spec->autocfg.hp_outs; i++) {
3652 hda_nid_t nid = spec->autocfg.hp_pins[i];
3653 unsigned int cfg = snd_hda_codec_get_pincfg(codec, nid);
3654 if (get_defcfg_location(cfg) & AC_JACK_LOC_SEPARATE)
3655 continue;
3656 valid_hps++;
3657 }
3658 return (valid_hps > 1);
3659}
3660
3661
3634static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) 3662static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
3635{ 3663{
3636 struct sigmatel_spec *spec = codec->spec; 3664 struct sigmatel_spec *spec = codec->spec;
@@ -3647,8 +3675,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3647 /* If we have no real line-out pin and multiple hp-outs, HPs should 3675 /* If we have no real line-out pin and multiple hp-outs, HPs should
3648 * be set up as multi-channel outputs. 3676 * be set up as multi-channel outputs.
3649 */ 3677 */
3650 if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && 3678 if (is_dual_headphones(codec)) {
3651 spec->autocfg.hp_outs > 1) {
3652 /* Copy hp_outs to line_outs, backup line_outs in 3679 /* Copy hp_outs to line_outs, backup line_outs in
3653 * speaker_outs so that the following routines can handle 3680 * speaker_outs so that the following routines can handle
3654 * HP pins as primary outputs. 3681 * HP pins as primary outputs.
@@ -4329,6 +4356,28 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
4329 snd_array_free(&spec->kctls); 4356 snd_array_free(&spec->kctls);
4330} 4357}
4331 4358
4359static void stac92xx_shutup(struct hda_codec *codec)
4360{
4361 struct sigmatel_spec *spec = codec->spec;
4362 int i;
4363 hda_nid_t nid;
4364
4365 /* reset each pin before powering down DAC/ADC to avoid click noise */
4366 nid = codec->start_nid;
4367 for (i = 0; i < codec->num_nodes; i++, nid++) {
4368 unsigned int wcaps = get_wcaps(codec, nid);
4369 unsigned int wid_type = get_wcaps_type(wcaps);
4370 if (wid_type == AC_WID_PIN)
4371 snd_hda_codec_read(codec, nid, 0,
4372 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
4373 }
4374
4375 if (spec->eapd_mask)
4376 stac_gpio_set(codec, spec->gpio_mask,
4377 spec->gpio_dir, spec->gpio_data &
4378 ~spec->eapd_mask);
4379}
4380
4332static void stac92xx_free(struct hda_codec *codec) 4381static void stac92xx_free(struct hda_codec *codec)
4333{ 4382{
4334 struct sigmatel_spec *spec = codec->spec; 4383 struct sigmatel_spec *spec = codec->spec;
@@ -4336,6 +4385,7 @@ static void stac92xx_free(struct hda_codec *codec)
4336 if (! spec) 4385 if (! spec)
4337 return; 4386 return;
4338 4387
4388 stac92xx_shutup(codec);
4339 stac92xx_free_jacks(codec); 4389 stac92xx_free_jacks(codec);
4340 snd_array_free(&spec->events); 4390 snd_array_free(&spec->events);
4341 4391
@@ -4386,12 +4436,16 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
4386 pin_ctl & ~flag); 4436 pin_ctl & ~flag);
4387} 4437}
4388 4438
4389static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) 4439static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
4390{ 4440{
4391 if (!nid) 4441 if (!nid)
4392 return 0; 4442 return 0;
4393 if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) 4443 /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
4394 & (1 << 31)) 4444 * codecs behave wrongly when SET_PIN_SENSE is triggered, although
4445 * the pincap gives TRIG_REQ bit.
4446 */
4447 if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
4448 AC_PINSENSE_PRESENCE)
4395 return 1; 4449 return 1;
4396 return 0; 4450 return 0;
4397} 4451}
@@ -4791,28 +4845,28 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
4791 4845
4792 return 0; 4846 return 0;
4793} 4847}
4794#endif
4795 4848
4796static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) 4849static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec,
4850 hda_nid_t nid)
4797{ 4851{
4798 struct sigmatel_spec *spec = codec->spec; 4852 struct sigmatel_spec *spec = codec->spec;
4799 int i;
4800 hda_nid_t nid;
4801 4853
4802 /* reset each pin before powering down DAC/ADC to avoid click noise */ 4854 if (nid != 0x13)
4803 nid = codec->start_nid; 4855 return 0;
4804 for (i = 0; i < codec->num_nodes; i++, nid++) { 4856 if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE)
4805 unsigned int wcaps = get_wcaps(codec, nid); 4857 spec->gpio_data |= spec->gpio_led; /* mute LED on */
4806 unsigned int wid_type = get_wcaps_type(wcaps); 4858 else
4807 if (wid_type == AC_WID_PIN) 4859 spec->gpio_data &= ~spec->gpio_led; /* mute LED off */
4808 snd_hda_codec_read(codec, nid, 0, 4860 stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
4809 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
4810 }
4811 4861
4812 if (spec->eapd_mask) 4862 return 0;
4813 stac_gpio_set(codec, spec->gpio_mask, 4863}
4814 spec->gpio_dir, spec->gpio_data & 4864
4815 ~spec->eapd_mask); 4865#endif
4866
4867static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
4868{
4869 stac92xx_shutup(codec);
4816 return 0; 4870 return 0;
4817} 4871}
4818#endif 4872#endif
@@ -4827,6 +4881,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
4827 .suspend = stac92xx_suspend, 4881 .suspend = stac92xx_suspend,
4828 .resume = stac92xx_resume, 4882 .resume = stac92xx_resume,
4829#endif 4883#endif
4884 .reboot_notify = stac92xx_shutup,
4830}; 4885};
4831 4886
4832static int patch_stac9200(struct hda_codec *codec) 4887static int patch_stac9200(struct hda_codec *codec)
@@ -5172,6 +5227,22 @@ again:
5172 break; 5227 break;
5173 } 5228 }
5174 5229
5230 codec->patch_ops = stac92xx_patch_ops;
5231
5232 if (spec->board_config == STAC_92HD83XXX_HP)
5233 spec->gpio_led = 0x01;
5234
5235#ifdef CONFIG_SND_HDA_POWER_SAVE
5236 if (spec->gpio_led) {
5237 spec->gpio_mask |= spec->gpio_led;
5238 spec->gpio_dir |= spec->gpio_led;
5239 spec->gpio_data |= spec->gpio_led;
5240 /* register check_power_status callback. */
5241 codec->patch_ops.check_power_status =
5242 idt92hd83xxx_hp_check_power_status;
5243 }
5244#endif
5245
5175 err = stac92xx_parse_auto_config(codec, 0x1d, 0); 5246 err = stac92xx_parse_auto_config(codec, 0x1d, 0);
5176 if (!err) { 5247 if (!err) {
5177 if (spec->board_config < 0) { 5248 if (spec->board_config < 0) {
@@ -5207,8 +5278,6 @@ again:
5207 snd_hda_codec_write_cache(codec, nid, 0, 5278 snd_hda_codec_write_cache(codec, nid, 0,
5208 AC_VERB_SET_CONNECT_SEL, num_dacs); 5279 AC_VERB_SET_CONNECT_SEL, num_dacs);
5209 5280
5210 codec->patch_ops = stac92xx_patch_ops;
5211
5212 codec->proc_widget_hook = stac92hd_proc_hook; 5281 codec->proc_widget_hook = stac92hd_proc_hook;
5213 5282
5214 return 0; 5283 return 0;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index ee89db90c9b6..b70e26ad263f 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1,10 +1,10 @@
1/* 1/*
2 * Universal Interface for Intel High Definition Audio Codec 2 * Universal Interface for Intel High Definition Audio Codec
3 * 3 *
4 * HD audio interface patch for VIA VT1702/VT1708/VT1709 codec 4 * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
5 * 5 *
6 * Copyright (c) 2006-2008 Lydia Wang <lydiawang@viatech.com> 6 * (C) 2006-2009 VIA Technology, Inc.
7 * Takashi Iwai <tiwai@suse.de> 7 * (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
8 * 8 *
9 * This driver is free software; you can redistribute it and/or modify 9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -22,21 +22,27 @@
22 */ 22 */
23 23
24/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */ 24/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25/* */ 25/* */
26/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */ 26/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
27/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */ 27/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
28/* 2006-08-02 Lydia Wang Add support to VT1709 codec */ 28/* 2006-08-02 Lydia Wang Add support to VT1709 codec */
29/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */ 29/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
30/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */ 30/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
31/* 2007-09-17 Lydia Wang Add VT1708B codec support */ 31/* 2007-09-17 Lydia Wang Add VT1708B codec support */
32/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */ 32/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
33/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */ 33/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
34/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */ 34/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
35/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ 35/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
36/* 2008-04-09 Lydia Wang Add Independent HP feature */ 36/* 2008-04-09 Lydia Wang Add Independent HP feature */
37/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */ 37/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
38/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */ 38/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
39/* */ 39/* 2009-02-16 Logan Li Add support for VT1718S */
40/* 2009-03-13 Logan Li Add support for VT1716S */
41/* 2009-04-14 Lydai Wang Add support for VT1828S and VT2020 */
42/* 2009-07-08 Lydia Wang Add support for VT2002P */
43/* 2009-07-21 Lydia Wang Add support for VT1812 */
44/* 2009-09-19 Lydia Wang Add support for VT1818S */
45/* */
40/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 46/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 47
42 48
@@ -76,14 +82,6 @@
76#define VT1702_HP_NID 0x17 82#define VT1702_HP_NID 0x17
77#define VT1702_DIGOUT_NID 0x11 83#define VT1702_DIGOUT_NID 0x11
78 84
79#define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
80#define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
81#define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
82#define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
83#define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
84#define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397)
85#define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398)
86
87enum VIA_HDA_CODEC { 85enum VIA_HDA_CODEC {
88 UNKNOWN = -1, 86 UNKNOWN = -1,
89 VT1708, 87 VT1708,
@@ -92,12 +90,76 @@ enum VIA_HDA_CODEC {
92 VT1708B_8CH, 90 VT1708B_8CH,
93 VT1708B_4CH, 91 VT1708B_4CH,
94 VT1708S, 92 VT1708S,
93 VT1708BCE,
95 VT1702, 94 VT1702,
95 VT1718S,
96 VT1716S,
97 VT2002P,
98 VT1812,
96 CODEC_TYPES, 99 CODEC_TYPES,
97}; 100};
98 101
99static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id) 102struct via_spec {
103 /* codec parameterization */
104 struct snd_kcontrol_new *mixers[6];
105 unsigned int num_mixers;
106
107 struct hda_verb *init_verbs[5];
108 unsigned int num_iverbs;
109
110 char *stream_name_analog;
111 struct hda_pcm_stream *stream_analog_playback;
112 struct hda_pcm_stream *stream_analog_capture;
113
114 char *stream_name_digital;
115 struct hda_pcm_stream *stream_digital_playback;
116 struct hda_pcm_stream *stream_digital_capture;
117
118 /* playback */
119 struct hda_multi_out multiout;
120 hda_nid_t slave_dig_outs[2];
121
122 /* capture */
123 unsigned int num_adc_nids;
124 hda_nid_t *adc_nids;
125 hda_nid_t mux_nids[3];
126 hda_nid_t dig_in_nid;
127 hda_nid_t dig_in_pin;
128
129 /* capture source */
130 const struct hda_input_mux *input_mux;
131 unsigned int cur_mux[3];
132
133 /* PCM information */
134 struct hda_pcm pcm_rec[3];
135
136 /* dynamic controls, init_verbs and input_mux */
137 struct auto_pin_cfg autocfg;
138 struct snd_array kctls;
139 struct hda_input_mux private_imux[2];
140 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
141
142 /* HP mode source */
143 const struct hda_input_mux *hp_mux;
144 unsigned int hp_independent_mode;
145 unsigned int hp_independent_mode_index;
146 unsigned int smart51_enabled;
147 unsigned int dmic_enabled;
148 enum VIA_HDA_CODEC codec_type;
149
150 /* work to check hp jack state */
151 struct hda_codec *codec;
152 struct delayed_work vt1708_hp_work;
153 int vt1708_jack_detectect;
154 int vt1708_hp_present;
155#ifdef CONFIG_SND_HDA_POWER_SAVE
156 struct hda_loopback_check loopback;
157#endif
158};
159
160static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
100{ 161{
162 u32 vendor_id = codec->vendor_id;
101 u16 ven_id = vendor_id >> 16; 163 u16 ven_id = vendor_id >> 16;
102 u16 dev_id = vendor_id & 0xffff; 164 u16 dev_id = vendor_id & 0xffff;
103 enum VIA_HDA_CODEC codec_type; 165 enum VIA_HDA_CODEC codec_type;
@@ -111,9 +173,11 @@ static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id)
111 codec_type = VT1709_10CH; 173 codec_type = VT1709_10CH;
112 else if (dev_id >= 0xe714 && dev_id <= 0xe717) 174 else if (dev_id >= 0xe714 && dev_id <= 0xe717)
113 codec_type = VT1709_6CH; 175 codec_type = VT1709_6CH;
114 else if (dev_id >= 0xe720 && dev_id <= 0xe723) 176 else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
115 codec_type = VT1708B_8CH; 177 codec_type = VT1708B_8CH;
116 else if (dev_id >= 0xe724 && dev_id <= 0xe727) 178 if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
179 codec_type = VT1708BCE;
180 } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
117 codec_type = VT1708B_4CH; 181 codec_type = VT1708B_4CH;
118 else if ((dev_id & 0xfff) == 0x397 182 else if ((dev_id & 0xfff) == 0x397
119 && (dev_id >> 12) < 8) 183 && (dev_id >> 12) < 8)
@@ -121,6 +185,19 @@ static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id)
121 else if ((dev_id & 0xfff) == 0x398 185 else if ((dev_id & 0xfff) == 0x398
122 && (dev_id >> 12) < 8) 186 && (dev_id >> 12) < 8)
123 codec_type = VT1702; 187 codec_type = VT1702;
188 else if ((dev_id & 0xfff) == 0x428
189 && (dev_id >> 12) < 8)
190 codec_type = VT1718S;
191 else if (dev_id == 0x0433 || dev_id == 0xa721)
192 codec_type = VT1716S;
193 else if (dev_id == 0x0441 || dev_id == 0x4441)
194 codec_type = VT1718S;
195 else if (dev_id == 0x0438 || dev_id == 0x4438)
196 codec_type = VT2002P;
197 else if (dev_id == 0x0448)
198 codec_type = VT1812;
199 else if (dev_id == 0x0440)
200 codec_type = VT1708S;
124 else 201 else
125 codec_type = UNKNOWN; 202 codec_type = UNKNOWN;
126 return codec_type; 203 return codec_type;
@@ -128,10 +205,16 @@ static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id)
128 205
129#define VIA_HP_EVENT 0x01 206#define VIA_HP_EVENT 0x01
130#define VIA_GPIO_EVENT 0x02 207#define VIA_GPIO_EVENT 0x02
208#define VIA_JACK_EVENT 0x04
209#define VIA_MONO_EVENT 0x08
210#define VIA_SPEAKER_EVENT 0x10
211#define VIA_BIND_HP_EVENT 0x20
131 212
132enum { 213enum {
133 VIA_CTL_WIDGET_VOL, 214 VIA_CTL_WIDGET_VOL,
134 VIA_CTL_WIDGET_MUTE, 215 VIA_CTL_WIDGET_MUTE,
216 VIA_CTL_WIDGET_ANALOG_MUTE,
217 VIA_CTL_WIDGET_BIND_PIN_MUTE,
135}; 218};
136 219
137enum { 220enum {
@@ -141,99 +224,162 @@ enum {
141 AUTO_SEQ_SIDE 224 AUTO_SEQ_SIDE
142}; 225};
143 226
144/* Some VT1708S based boards gets the micboost setting wrong, so we have 227static void analog_low_current_mode(struct hda_codec *codec, int stream_idle);
145 * to apply some brute-force and re-write the TLV's by software. */ 228static void set_jack_power_state(struct hda_codec *codec);
146static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag, 229static int is_aa_path_mute(struct hda_codec *codec);
147 unsigned int size, unsigned int __user *_tlv) 230
231static void vt1708_start_hp_work(struct via_spec *spec)
148{ 232{
149 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 233 if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
150 hda_nid_t nid = get_amp_nid(kcontrol); 234 return;
235 snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
236 !spec->vt1708_jack_detectect);
237 if (!delayed_work_pending(&spec->vt1708_hp_work))
238 schedule_delayed_work(&spec->vt1708_hp_work,
239 msecs_to_jiffies(100));
240}
151 241
152 if (get_codec_type(codec->vendor_id) == VT1708S 242static void vt1708_stop_hp_work(struct via_spec *spec)
153 && (nid == 0x1a || nid == 0x1e)) { 243{
154 if (size < 4 * sizeof(unsigned int)) 244 if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
155 return -ENOMEM; 245 return;
156 if (put_user(1, _tlv)) /* SNDRV_CTL_TLVT_DB_SCALE */ 246 if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1
157 return -EFAULT; 247 && !is_aa_path_mute(spec->codec))
158 if (put_user(2 * sizeof(unsigned int), _tlv + 1)) 248 return;
159 return -EFAULT; 249 snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
160 if (put_user(0, _tlv + 2)) /* offset = 0 */ 250 !spec->vt1708_jack_detectect);
161 return -EFAULT; 251 cancel_delayed_work(&spec->vt1708_hp_work);
162 if (put_user(1000, _tlv + 3)) /* step size = 10 dB */ 252 flush_scheduled_work();
163 return -EFAULT;
164 }
165 return 0;
166} 253}
167 254
168static int mic_boost_volume_info(struct snd_kcontrol *kcontrol, 255
169 struct snd_ctl_elem_info *uinfo) 256static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
257 struct snd_ctl_elem_value *ucontrol)
170{ 258{
259 int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
171 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 260 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
172 hda_nid_t nid = get_amp_nid(kcontrol);
173 261
174 if (get_codec_type(codec->vendor_id) == VT1708S 262 set_jack_power_state(codec);
175 && (nid == 0x1a || nid == 0x1e)) { 263 analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1);
176 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 264 if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
177 uinfo->count = 2; 265 if (is_aa_path_mute(codec))
178 uinfo->value.integer.min = 0; 266 vt1708_start_hp_work(codec->spec);
179 uinfo->value.integer.max = 3; 267 else
268 vt1708_stop_hp_work(codec->spec);
180 } 269 }
181 return 0; 270 return change;
182} 271}
183 272
184static struct snd_kcontrol_new vt1708_control_templates[] = { 273/* modify .put = snd_hda_mixer_amp_switch_put */
185 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 274#define ANALOG_INPUT_MUTE \
186 HDA_CODEC_MUTE(NULL, 0, 0, 0), 275 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
187}; 276 .name = NULL, \
188 277 .index = 0, \
189 278 .info = snd_hda_mixer_amp_switch_info, \
190struct via_spec { 279 .get = snd_hda_mixer_amp_switch_get, \
191 /* codec parameterization */ 280 .put = analog_input_switch_put, \
192 struct snd_kcontrol_new *mixers[3]; 281 .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) }
193 unsigned int num_mixers;
194 282
195 struct hda_verb *init_verbs[5]; 283static void via_hp_bind_automute(struct hda_codec *codec);
196 unsigned int num_iverbs;
197 284
198 char *stream_name_analog; 285static int bind_pin_switch_put(struct snd_kcontrol *kcontrol,
199 struct hda_pcm_stream *stream_analog_playback; 286 struct snd_ctl_elem_value *ucontrol)
200 struct hda_pcm_stream *stream_analog_capture; 287{
201 288 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
202 char *stream_name_digital; 289 struct via_spec *spec = codec->spec;
203 struct hda_pcm_stream *stream_digital_playback; 290 int i;
204 struct hda_pcm_stream *stream_digital_capture; 291 int change = 0;
205
206 /* playback */
207 struct hda_multi_out multiout;
208 hda_nid_t slave_dig_outs[2];
209
210 /* capture */
211 unsigned int num_adc_nids;
212 hda_nid_t *adc_nids;
213 hda_nid_t mux_nids[3];
214 hda_nid_t dig_in_nid;
215 hda_nid_t dig_in_pin;
216 292
217 /* capture source */ 293 long *valp = ucontrol->value.integer.value;
218 const struct hda_input_mux *input_mux; 294 int lmute, rmute;
219 unsigned int cur_mux[3]; 295 if (strstr(kcontrol->id.name, "Switch") == NULL) {
296 snd_printd("Invalid control!\n");
297 return change;
298 }
299 change = snd_hda_mixer_amp_switch_put(kcontrol,
300 ucontrol);
301 /* Get mute value */
302 lmute = *valp ? 0 : HDA_AMP_MUTE;
303 valp++;
304 rmute = *valp ? 0 : HDA_AMP_MUTE;
305
306 /* Set hp pins */
307 if (!spec->hp_independent_mode) {
308 for (i = 0; i < spec->autocfg.hp_outs; i++) {
309 snd_hda_codec_amp_update(
310 codec, spec->autocfg.hp_pins[i],
311 0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
312 lmute);
313 snd_hda_codec_amp_update(
314 codec, spec->autocfg.hp_pins[i],
315 1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
316 rmute);
317 }
318 }
220 319
221 /* PCM information */ 320 if (!lmute && !rmute) {
222 struct hda_pcm pcm_rec[3]; 321 /* Line Outs */
322 for (i = 0; i < spec->autocfg.line_outs; i++)
323 snd_hda_codec_amp_stereo(
324 codec, spec->autocfg.line_out_pins[i],
325 HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
326 /* Speakers */
327 for (i = 0; i < spec->autocfg.speaker_outs; i++)
328 snd_hda_codec_amp_stereo(
329 codec, spec->autocfg.speaker_pins[i],
330 HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
331 /* unmute */
332 via_hp_bind_automute(codec);
223 333
224 /* dynamic controls, init_verbs and input_mux */ 334 } else {
225 struct auto_pin_cfg autocfg; 335 if (lmute) {
226 struct snd_array kctls; 336 /* Mute all left channels */
227 struct hda_input_mux private_imux[2]; 337 for (i = 1; i < spec->autocfg.line_outs; i++)
228 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 338 snd_hda_codec_amp_update(
339 codec,
340 spec->autocfg.line_out_pins[i],
341 0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
342 lmute);
343 for (i = 0; i < spec->autocfg.speaker_outs; i++)
344 snd_hda_codec_amp_update(
345 codec,
346 spec->autocfg.speaker_pins[i],
347 0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
348 lmute);
349 }
350 if (rmute) {
351 /* mute all right channels */
352 for (i = 1; i < spec->autocfg.line_outs; i++)
353 snd_hda_codec_amp_update(
354 codec,
355 spec->autocfg.line_out_pins[i],
356 1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
357 rmute);
358 for (i = 0; i < spec->autocfg.speaker_outs; i++)
359 snd_hda_codec_amp_update(
360 codec,
361 spec->autocfg.speaker_pins[i],
362 1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
363 rmute);
364 }
365 }
366 return change;
367}
229 368
230 /* HP mode source */ 369#define BIND_PIN_MUTE \
231 const struct hda_input_mux *hp_mux; 370 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
232 unsigned int hp_independent_mode; 371 .name = NULL, \
372 .index = 0, \
373 .info = snd_hda_mixer_amp_switch_info, \
374 .get = snd_hda_mixer_amp_switch_get, \
375 .put = bind_pin_switch_put, \
376 .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) }
233 377
234#ifdef CONFIG_SND_HDA_POWER_SAVE 378static struct snd_kcontrol_new via_control_templates[] = {
235 struct hda_loopback_check loopback; 379 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
236#endif 380 HDA_CODEC_MUTE(NULL, 0, 0, 0),
381 ANALOG_INPUT_MUTE,
382 BIND_PIN_MUTE,
237}; 383};
238 384
239static hda_nid_t vt1708_adc_nids[2] = { 385static hda_nid_t vt1708_adc_nids[2] = {
@@ -261,6 +407,27 @@ static hda_nid_t vt1702_adc_nids[3] = {
261 0x12, 0x20, 0x1F 407 0x12, 0x20, 0x1F
262}; 408};
263 409
410static hda_nid_t vt1718S_adc_nids[2] = {
411 /* ADC1-2 */
412 0x10, 0x11
413};
414
415static hda_nid_t vt1716S_adc_nids[2] = {
416 /* ADC1-2 */
417 0x13, 0x14
418};
419
420static hda_nid_t vt2002P_adc_nids[2] = {
421 /* ADC1-2 */
422 0x10, 0x11
423};
424
425static hda_nid_t vt1812_adc_nids[2] = {
426 /* ADC1-2 */
427 0x10, 0x11
428};
429
430
264/* add dynamic controls */ 431/* add dynamic controls */
265static int via_add_control(struct via_spec *spec, int type, const char *name, 432static int via_add_control(struct via_spec *spec, int type, const char *name,
266 unsigned long val) 433 unsigned long val)
@@ -271,10 +438,12 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
271 knew = snd_array_new(&spec->kctls); 438 knew = snd_array_new(&spec->kctls);
272 if (!knew) 439 if (!knew)
273 return -ENOMEM; 440 return -ENOMEM;
274 *knew = vt1708_control_templates[type]; 441 *knew = via_control_templates[type];
275 knew->name = kstrdup(name, GFP_KERNEL); 442 knew->name = kstrdup(name, GFP_KERNEL);
276 if (!knew->name) 443 if (!knew->name)
277 return -ENOMEM; 444 return -ENOMEM;
445 if (get_amp_nid_(val))
446 knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
278 knew->private_value = val; 447 knew->private_value = val;
279 return 0; 448 return 0;
280} 449}
@@ -293,8 +462,8 @@ static void via_free_kctls(struct hda_codec *codec)
293} 462}
294 463
295/* create input playback/capture controls for the given pin */ 464/* create input playback/capture controls for the given pin */
296static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, 465static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
297 const char *ctlname, int idx, int mix_nid) 466 int idx, int mix_nid)
298{ 467{
299 char name[32]; 468 char name[32];
300 int err; 469 int err;
@@ -305,7 +474,7 @@ static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
305 if (err < 0) 474 if (err < 0)
306 return err; 475 return err;
307 sprintf(name, "%s Playback Switch", ctlname); 476 sprintf(name, "%s Playback Switch", ctlname);
308 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, 477 err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name,
309 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 478 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
310 if (err < 0) 479 if (err < 0)
311 return err; 480 return err;
@@ -322,7 +491,7 @@ static void via_auto_set_output_and_unmute(struct hda_codec *codec,
322 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 491 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
323 AMP_OUT_UNMUTE); 492 AMP_OUT_UNMUTE);
324 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD) 493 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
325 snd_hda_codec_write(codec, nid, 0, 494 snd_hda_codec_write(codec, nid, 0,
326 AC_VERB_SET_EAPD_BTLENABLE, 0x02); 495 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
327} 496}
328 497
@@ -343,10 +512,13 @@ static void via_auto_init_hp_out(struct hda_codec *codec)
343{ 512{
344 struct via_spec *spec = codec->spec; 513 struct via_spec *spec = codec->spec;
345 hda_nid_t pin; 514 hda_nid_t pin;
515 int i;
346 516
347 pin = spec->autocfg.hp_pins[0]; 517 for (i = 0; i < spec->autocfg.hp_outs; i++) {
348 if (pin) /* connect to front */ 518 pin = spec->autocfg.hp_pins[i];
349 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 519 if (pin) /* connect to front */
520 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
521 }
350} 522}
351 523
352static void via_auto_init_analog_input(struct hda_codec *codec) 524static void via_auto_init_analog_input(struct hda_codec *codec)
@@ -364,6 +536,502 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
364 536
365 } 537 }
366} 538}
539
540static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
541
542static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
543 unsigned int *affected_parm)
544{
545 unsigned parm;
546 unsigned def_conf = snd_hda_codec_get_pincfg(codec, nid);
547 unsigned no_presence = (def_conf & AC_DEFCFG_MISC)
548 >> AC_DEFCFG_MISC_SHIFT
549 & AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */
550 unsigned present = snd_hda_jack_detect(codec, nid);
551 struct via_spec *spec = codec->spec;
552 if ((spec->smart51_enabled && is_smart51_pins(spec, nid))
553 || ((no_presence || present)
554 && get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) {
555 *affected_parm = AC_PWRST_D0; /* if it's connected */
556 parm = AC_PWRST_D0;
557 } else
558 parm = AC_PWRST_D3;
559
560 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
561}
562
563static void set_jack_power_state(struct hda_codec *codec)
564{
565 struct via_spec *spec = codec->spec;
566 int imux_is_smixer;
567 unsigned int parm;
568
569 if (spec->codec_type == VT1702) {
570 imux_is_smixer = snd_hda_codec_read(
571 codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
572 /* inputs */
573 /* PW 1/2/5 (14h/15h/18h) */
574 parm = AC_PWRST_D3;
575 set_pin_power_state(codec, 0x14, &parm);
576 set_pin_power_state(codec, 0x15, &parm);
577 set_pin_power_state(codec, 0x18, &parm);
578 if (imux_is_smixer)
579 parm = AC_PWRST_D0; /* SW0 = stereo mixer (idx 3) */
580 /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
581 snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
582 parm);
583 snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE,
584 parm);
585 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
586 parm);
587 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE,
588 parm);
589
590 /* outputs */
591 /* PW 3/4 (16h/17h) */
592 parm = AC_PWRST_D3;
593 set_pin_power_state(codec, 0x16, &parm);
594 set_pin_power_state(codec, 0x17, &parm);
595 /* MW0 (1ah), AOW 0/1 (10h/1dh) */
596 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
597 imux_is_smixer ? AC_PWRST_D0 : parm);
598 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
599 parm);
600 snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE,
601 parm);
602 } else if (spec->codec_type == VT1708B_8CH
603 || spec->codec_type == VT1708B_4CH
604 || spec->codec_type == VT1708S) {
605 /* SW0 (17h) = stereo mixer */
606 int is_8ch = spec->codec_type != VT1708B_4CH;
607 imux_is_smixer = snd_hda_codec_read(
608 codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
609 == ((spec->codec_type == VT1708S) ? 5 : 0);
610 /* inputs */
611 /* PW 1/2/5 (1ah/1bh/1eh) */
612 parm = AC_PWRST_D3;
613 set_pin_power_state(codec, 0x1a, &parm);
614 set_pin_power_state(codec, 0x1b, &parm);
615 set_pin_power_state(codec, 0x1e, &parm);
616 if (imux_is_smixer)
617 parm = AC_PWRST_D0;
618 /* SW0 (17h), AIW 0/1 (13h/14h) */
619 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
620 parm);
621 snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
622 parm);
623 snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
624 parm);
625
626 /* outputs */
627 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
628 parm = AC_PWRST_D3;
629 set_pin_power_state(codec, 0x19, &parm);
630 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
631 parm);
632 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
633 parm);
634
635 /* PW6 (22h), SW2 (26h), AOW2 (24h) */
636 if (is_8ch) {
637 parm = AC_PWRST_D3;
638 set_pin_power_state(codec, 0x22, &parm);
639 snd_hda_codec_write(codec, 0x26, 0,
640 AC_VERB_SET_POWER_STATE, parm);
641 snd_hda_codec_write(codec, 0x24, 0,
642 AC_VERB_SET_POWER_STATE, parm);
643 }
644
645 /* PW 3/4/7 (1ch/1dh/23h) */
646 parm = AC_PWRST_D3;
647 /* force to D0 for internal Speaker */
648 set_pin_power_state(codec, 0x1c, &parm);
649 set_pin_power_state(codec, 0x1d, &parm);
650 if (is_8ch)
651 set_pin_power_state(codec, 0x23, &parm);
652 /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
653 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
654 imux_is_smixer ? AC_PWRST_D0 : parm);
655 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
656 parm);
657 if (is_8ch) {
658 snd_hda_codec_write(codec, 0x25, 0,
659 AC_VERB_SET_POWER_STATE, parm);
660 snd_hda_codec_write(codec, 0x27, 0,
661 AC_VERB_SET_POWER_STATE, parm);
662 }
663 } else if (spec->codec_type == VT1718S) {
664 /* MUX6 (1eh) = stereo mixer */
665 imux_is_smixer = snd_hda_codec_read(
666 codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
667 /* inputs */
668 /* PW 5/6/7 (29h/2ah/2bh) */
669 parm = AC_PWRST_D3;
670 set_pin_power_state(codec, 0x29, &parm);
671 set_pin_power_state(codec, 0x2a, &parm);
672 set_pin_power_state(codec, 0x2b, &parm);
673 if (imux_is_smixer)
674 parm = AC_PWRST_D0;
675 /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
676 snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE,
677 parm);
678 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
679 parm);
680 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
681 parm);
682 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
683 parm);
684
685 /* outputs */
686 /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
687 parm = AC_PWRST_D3;
688 set_pin_power_state(codec, 0x27, &parm);
689 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
690 parm);
691 snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE,
692 parm);
693
694 /* PW2 (26h), AOW2 (ah) */
695 parm = AC_PWRST_D3;
696 set_pin_power_state(codec, 0x26, &parm);
697 snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE,
698 parm);
699
700 /* PW0/1 (24h/25h) */
701 parm = AC_PWRST_D3;
702 set_pin_power_state(codec, 0x24, &parm);
703 set_pin_power_state(codec, 0x25, &parm);
704 if (!spec->hp_independent_mode) /* check for redirected HP */
705 set_pin_power_state(codec, 0x28, &parm);
706 snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE,
707 parm);
708 snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE,
709 parm);
710 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
711 snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
712 imux_is_smixer ? AC_PWRST_D0 : parm);
713 if (spec->hp_independent_mode) {
714 /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
715 parm = AC_PWRST_D3;
716 set_pin_power_state(codec, 0x28, &parm);
717 snd_hda_codec_write(codec, 0x1b, 0,
718 AC_VERB_SET_POWER_STATE, parm);
719 snd_hda_codec_write(codec, 0x34, 0,
720 AC_VERB_SET_POWER_STATE, parm);
721 snd_hda_codec_write(codec, 0xc, 0,
722 AC_VERB_SET_POWER_STATE, parm);
723 }
724 } else if (spec->codec_type == VT1716S) {
725 unsigned int mono_out, present;
726 /* SW0 (17h) = stereo mixer */
727 imux_is_smixer = snd_hda_codec_read(
728 codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
729 /* inputs */
730 /* PW 1/2/5 (1ah/1bh/1eh) */
731 parm = AC_PWRST_D3;
732 set_pin_power_state(codec, 0x1a, &parm);
733 set_pin_power_state(codec, 0x1b, &parm);
734 set_pin_power_state(codec, 0x1e, &parm);
735 if (imux_is_smixer)
736 parm = AC_PWRST_D0;
737 /* SW0 (17h), AIW0(13h) */
738 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
739 parm);
740 snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
741 parm);
742
743 parm = AC_PWRST_D3;
744 set_pin_power_state(codec, 0x1e, &parm);
745 /* PW11 (22h) */
746 if (spec->dmic_enabled)
747 set_pin_power_state(codec, 0x22, &parm);
748 else
749 snd_hda_codec_write(
750 codec, 0x22, 0,
751 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
752
753 /* SW2(26h), AIW1(14h) */
754 snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE,
755 parm);
756 snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
757 parm);
758
759 /* outputs */
760 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
761 parm = AC_PWRST_D3;
762 set_pin_power_state(codec, 0x19, &parm);
763 /* Smart 5.1 PW2(1bh) */
764 if (spec->smart51_enabled)
765 set_pin_power_state(codec, 0x1b, &parm);
766 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
767 parm);
768 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
769 parm);
770
771 /* PW7 (23h), SW3 (27h), AOW3 (25h) */
772 parm = AC_PWRST_D3;
773 set_pin_power_state(codec, 0x23, &parm);
774 /* Smart 5.1 PW1(1ah) */
775 if (spec->smart51_enabled)
776 set_pin_power_state(codec, 0x1a, &parm);
777 snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE,
778 parm);
779
780 /* Smart 5.1 PW5(1eh) */
781 if (spec->smart51_enabled)
782 set_pin_power_state(codec, 0x1e, &parm);
783 snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE,
784 parm);
785
786 /* Mono out */
787 /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
788 present = snd_hda_jack_detect(codec, 0x1c);
789 if (present)
790 mono_out = 0;
791 else {
792 present = snd_hda_jack_detect(codec, 0x1d);
793 if (!spec->hp_independent_mode && present)
794 mono_out = 0;
795 else
796 mono_out = 1;
797 }
798 parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
799 snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE,
800 parm);
801 snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE,
802 parm);
803 snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE,
804 parm);
805
806 /* PW 3/4 (1ch/1dh) */
807 parm = AC_PWRST_D3;
808 set_pin_power_state(codec, 0x1c, &parm);
809 set_pin_power_state(codec, 0x1d, &parm);
810 /* HP Independent Mode, power on AOW3 */
811 if (spec->hp_independent_mode)
812 snd_hda_codec_write(codec, 0x25, 0,
813 AC_VERB_SET_POWER_STATE, parm);
814
815 /* force to D0 for internal Speaker */
816 /* MW0 (16h), AOW0 (10h) */
817 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
818 imux_is_smixer ? AC_PWRST_D0 : parm);
819 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
820 mono_out ? AC_PWRST_D0 : parm);
821 } else if (spec->codec_type == VT2002P) {
822 unsigned int present;
823 /* MUX9 (1eh) = stereo mixer */
824 imux_is_smixer = snd_hda_codec_read(
825 codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
826 /* inputs */
827 /* PW 5/6/7 (29h/2ah/2bh) */
828 parm = AC_PWRST_D3;
829 set_pin_power_state(codec, 0x29, &parm);
830 set_pin_power_state(codec, 0x2a, &parm);
831 set_pin_power_state(codec, 0x2b, &parm);
832 if (imux_is_smixer)
833 parm = AC_PWRST_D0;
834 /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
835 snd_hda_codec_write(codec, 0x1e, 0,
836 AC_VERB_SET_POWER_STATE, parm);
837 snd_hda_codec_write(codec, 0x1f, 0,
838 AC_VERB_SET_POWER_STATE, parm);
839 snd_hda_codec_write(codec, 0x10, 0,
840 AC_VERB_SET_POWER_STATE, parm);
841 snd_hda_codec_write(codec, 0x11, 0,
842 AC_VERB_SET_POWER_STATE, parm);
843
844 /* outputs */
845 /* AOW0 (8h)*/
846 snd_hda_codec_write(codec, 0x8, 0,
847 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
848
849 /* PW4 (26h), MW4 (1ch), MUX4(37h) */
850 parm = AC_PWRST_D3;
851 set_pin_power_state(codec, 0x26, &parm);
852 snd_hda_codec_write(codec, 0x1c, 0,
853 AC_VERB_SET_POWER_STATE, parm);
854 snd_hda_codec_write(codec, 0x37,
855 0, AC_VERB_SET_POWER_STATE, parm);
856
857 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
858 parm = AC_PWRST_D3;
859 set_pin_power_state(codec, 0x25, &parm);
860 snd_hda_codec_write(codec, 0x19, 0,
861 AC_VERB_SET_POWER_STATE, parm);
862 snd_hda_codec_write(codec, 0x35, 0,
863 AC_VERB_SET_POWER_STATE, parm);
864 if (spec->hp_independent_mode) {
865 snd_hda_codec_write(codec, 0x9, 0,
866 AC_VERB_SET_POWER_STATE, parm);
867 }
868
869 /* Class-D */
870 /* PW0 (24h), MW0(18h), MUX0(34h) */
871 present = snd_hda_jack_detect(codec, 0x25);
872 parm = AC_PWRST_D3;
873 set_pin_power_state(codec, 0x24, &parm);
874 if (present) {
875 snd_hda_codec_write(
876 codec, 0x18, 0,
877 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
878 snd_hda_codec_write(
879 codec, 0x34, 0,
880 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
881 } else {
882 snd_hda_codec_write(
883 codec, 0x18, 0,
884 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
885 snd_hda_codec_write(
886 codec, 0x34, 0,
887 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
888 }
889
890 /* Mono Out */
891 /* PW15 (31h), MW8(17h), MUX8(3bh) */
892 present = snd_hda_jack_detect(codec, 0x26);
893 parm = AC_PWRST_D3;
894 set_pin_power_state(codec, 0x31, &parm);
895 if (present) {
896 snd_hda_codec_write(
897 codec, 0x17, 0,
898 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
899 snd_hda_codec_write(
900 codec, 0x3b, 0,
901 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
902 } else {
903 snd_hda_codec_write(
904 codec, 0x17, 0,
905 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
906 snd_hda_codec_write(
907 codec, 0x3b, 0,
908 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
909 }
910
911 /* MW9 (21h) */
912 if (imux_is_smixer || !is_aa_path_mute(codec))
913 snd_hda_codec_write(
914 codec, 0x21, 0,
915 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
916 else
917 snd_hda_codec_write(
918 codec, 0x21, 0,
919 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
920 } else if (spec->codec_type == VT1812) {
921 unsigned int present;
922 /* MUX10 (1eh) = stereo mixer */
923 imux_is_smixer = snd_hda_codec_read(
924 codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
925 /* inputs */
926 /* PW 5/6/7 (29h/2ah/2bh) */
927 parm = AC_PWRST_D3;
928 set_pin_power_state(codec, 0x29, &parm);
929 set_pin_power_state(codec, 0x2a, &parm);
930 set_pin_power_state(codec, 0x2b, &parm);
931 if (imux_is_smixer)
932 parm = AC_PWRST_D0;
933 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
934 snd_hda_codec_write(codec, 0x1e, 0,
935 AC_VERB_SET_POWER_STATE, parm);
936 snd_hda_codec_write(codec, 0x1f, 0,
937 AC_VERB_SET_POWER_STATE, parm);
938 snd_hda_codec_write(codec, 0x10, 0,
939 AC_VERB_SET_POWER_STATE, parm);
940 snd_hda_codec_write(codec, 0x11, 0,
941 AC_VERB_SET_POWER_STATE, parm);
942
943 /* outputs */
944 /* AOW0 (8h)*/
945 snd_hda_codec_write(codec, 0x8, 0,
946 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
947
948 /* PW4 (28h), MW4 (18h), MUX4(38h) */
949 parm = AC_PWRST_D3;
950 set_pin_power_state(codec, 0x28, &parm);
951 snd_hda_codec_write(codec, 0x18, 0,
952 AC_VERB_SET_POWER_STATE, parm);
953 snd_hda_codec_write(codec, 0x38, 0,
954 AC_VERB_SET_POWER_STATE, parm);
955
956 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
957 parm = AC_PWRST_D3;
958 set_pin_power_state(codec, 0x25, &parm);
959 snd_hda_codec_write(codec, 0x15, 0,
960 AC_VERB_SET_POWER_STATE, parm);
961 snd_hda_codec_write(codec, 0x35, 0,
962 AC_VERB_SET_POWER_STATE, parm);
963 if (spec->hp_independent_mode) {
964 snd_hda_codec_write(codec, 0x9, 0,
965 AC_VERB_SET_POWER_STATE, parm);
966 }
967
968 /* Internal Speaker */
969 /* PW0 (24h), MW0(14h), MUX0(34h) */
970 present = snd_hda_jack_detect(codec, 0x25);
971 parm = AC_PWRST_D3;
972 set_pin_power_state(codec, 0x24, &parm);
973 if (present) {
974 snd_hda_codec_write(codec, 0x14, 0,
975 AC_VERB_SET_POWER_STATE,
976 AC_PWRST_D3);
977 snd_hda_codec_write(codec, 0x34, 0,
978 AC_VERB_SET_POWER_STATE,
979 AC_PWRST_D3);
980 } else {
981 snd_hda_codec_write(codec, 0x14, 0,
982 AC_VERB_SET_POWER_STATE,
983 AC_PWRST_D0);
984 snd_hda_codec_write(codec, 0x34, 0,
985 AC_VERB_SET_POWER_STATE,
986 AC_PWRST_D0);
987 }
988 /* Mono Out */
989 /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
990 present = snd_hda_jack_detect(codec, 0x28);
991 parm = AC_PWRST_D3;
992 set_pin_power_state(codec, 0x31, &parm);
993 if (present) {
994 snd_hda_codec_write(codec, 0x1c, 0,
995 AC_VERB_SET_POWER_STATE,
996 AC_PWRST_D3);
997 snd_hda_codec_write(codec, 0x3c, 0,
998 AC_VERB_SET_POWER_STATE,
999 AC_PWRST_D3);
1000 snd_hda_codec_write(codec, 0x3e, 0,
1001 AC_VERB_SET_POWER_STATE,
1002 AC_PWRST_D3);
1003 } else {
1004 snd_hda_codec_write(codec, 0x1c, 0,
1005 AC_VERB_SET_POWER_STATE,
1006 AC_PWRST_D0);
1007 snd_hda_codec_write(codec, 0x3c, 0,
1008 AC_VERB_SET_POWER_STATE,
1009 AC_PWRST_D0);
1010 snd_hda_codec_write(codec, 0x3e, 0,
1011 AC_VERB_SET_POWER_STATE,
1012 AC_PWRST_D0);
1013 }
1014
1015 /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
1016 parm = AC_PWRST_D3;
1017 set_pin_power_state(codec, 0x33, &parm);
1018 snd_hda_codec_write(codec, 0x1d, 0,
1019 AC_VERB_SET_POWER_STATE, parm);
1020 snd_hda_codec_write(codec, 0x3d, 0,
1021 AC_VERB_SET_POWER_STATE, parm);
1022
1023 /* MW9 (21h) */
1024 if (imux_is_smixer || !is_aa_path_mute(codec))
1025 snd_hda_codec_write(
1026 codec, 0x21, 0,
1027 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
1028 else
1029 snd_hda_codec_write(
1030 codec, 0x21, 0,
1031 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
1032 }
1033}
1034
367/* 1035/*
368 * input MUX handling 1036 * input MUX handling
369 */ 1037 */
@@ -395,6 +1063,14 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
395 1063
396 if (!spec->mux_nids[adc_idx]) 1064 if (!spec->mux_nids[adc_idx])
397 return -EINVAL; 1065 return -EINVAL;
1066 /* switch to D0 beofre change index */
1067 if (snd_hda_codec_read(codec, spec->mux_nids[adc_idx], 0,
1068 AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
1069 snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
1070 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
1071 /* update jack power state */
1072 set_jack_power_state(codec);
1073
398 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 1074 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
399 spec->mux_nids[adc_idx], 1075 spec->mux_nids[adc_idx],
400 &spec->cur_mux[adc_idx]); 1076 &spec->cur_mux[adc_idx]);
@@ -413,16 +1089,74 @@ static int via_independent_hp_get(struct snd_kcontrol *kcontrol,
413{ 1089{
414 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1090 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
415 struct via_spec *spec = codec->spec; 1091 struct via_spec *spec = codec->spec;
416 hda_nid_t nid = spec->autocfg.hp_pins[0]; 1092 hda_nid_t nid;
417 unsigned int pinsel = snd_hda_codec_read(codec, nid, 0, 1093 unsigned int pinsel;
418 AC_VERB_GET_CONNECT_SEL, 1094
419 0x00); 1095 switch (spec->codec_type) {
420 1096 case VT1718S:
1097 nid = 0x34;
1098 break;
1099 case VT2002P:
1100 nid = 0x35;
1101 break;
1102 case VT1812:
1103 nid = 0x3d;
1104 break;
1105 default:
1106 nid = spec->autocfg.hp_pins[0];
1107 break;
1108 }
1109 /* use !! to translate conn sel 2 for VT1718S */
1110 pinsel = !!snd_hda_codec_read(codec, nid, 0,
1111 AC_VERB_GET_CONNECT_SEL,
1112 0x00);
421 ucontrol->value.enumerated.item[0] = pinsel; 1113 ucontrol->value.enumerated.item[0] = pinsel;
422 1114
423 return 0; 1115 return 0;
424} 1116}
425 1117
1118static void activate_ctl(struct hda_codec *codec, const char *name, int active)
1119{
1120 struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
1121 if (ctl) {
1122 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1123 ctl->vd[0].access |= active
1124 ? 0 : SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1125 snd_ctl_notify(codec->bus->card,
1126 SNDRV_CTL_EVENT_MASK_VALUE, &ctl->id);
1127 }
1128}
1129
1130static int update_side_mute_status(struct hda_codec *codec)
1131{
1132 /* mute side channel */
1133 struct via_spec *spec = codec->spec;
1134 unsigned int parm = spec->hp_independent_mode
1135 ? AMP_OUT_MUTE : AMP_OUT_UNMUTE;
1136 hda_nid_t sw3;
1137
1138 switch (spec->codec_type) {
1139 case VT1708:
1140 sw3 = 0x1b;
1141 break;
1142 case VT1709_10CH:
1143 sw3 = 0x29;
1144 break;
1145 case VT1708B_8CH:
1146 case VT1708S:
1147 sw3 = 0x27;
1148 break;
1149 default:
1150 sw3 = 0;
1151 break;
1152 }
1153
1154 if (sw3)
1155 snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1156 parm);
1157 return 0;
1158}
1159
426static int via_independent_hp_put(struct snd_kcontrol *kcontrol, 1160static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
427 struct snd_ctl_elem_value *ucontrol) 1161 struct snd_ctl_elem_value *ucontrol)
428{ 1162{
@@ -430,47 +1164,46 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
430 struct via_spec *spec = codec->spec; 1164 struct via_spec *spec = codec->spec;
431 hda_nid_t nid = spec->autocfg.hp_pins[0]; 1165 hda_nid_t nid = spec->autocfg.hp_pins[0];
432 unsigned int pinsel = ucontrol->value.enumerated.item[0]; 1166 unsigned int pinsel = ucontrol->value.enumerated.item[0];
433 unsigned int con_nid = snd_hda_codec_read(codec, nid, 0, 1167 /* Get Independent Mode index of headphone pin widget */
434 AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 1168 spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel
435 1169 ? 1 : 0;
436 if (con_nid == spec->multiout.hp_nid) { 1170
437 if (pinsel == 0) { 1171 switch (spec->codec_type) {
438 if (!spec->hp_independent_mode) { 1172 case VT1718S:
439 if (spec->multiout.num_dacs > 1) 1173 nid = 0x34;
440 spec->multiout.num_dacs -= 1; 1174 pinsel = pinsel ? 2 : 0; /* indep HP use AOW4 (index 2) */
441 spec->hp_independent_mode = 1; 1175 spec->multiout.num_dacs = 4;
442 } 1176 break;
443 } else if (pinsel == 1) { 1177 case VT2002P:
444 if (spec->hp_independent_mode) { 1178 nid = 0x35;
445 if (spec->multiout.num_dacs > 1) 1179 break;
446 spec->multiout.num_dacs += 1; 1180 case VT1812:
447 spec->hp_independent_mode = 0; 1181 nid = 0x3d;
448 } 1182 break;
449 } 1183 default:
450 } else { 1184 nid = spec->autocfg.hp_pins[0];
451 if (pinsel == 0) { 1185 break;
452 if (spec->hp_independent_mode) { 1186 }
453 if (spec->multiout.num_dacs > 1) 1187 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel);
454 spec->multiout.num_dacs += 1; 1188
455 spec->hp_independent_mode = 0; 1189 if (spec->multiout.hp_nid && spec->multiout.hp_nid
456 } 1190 != spec->multiout.dac_nids[HDA_FRONT])
457 } else if (pinsel == 1) { 1191 snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid,
458 if (!spec->hp_independent_mode) { 1192 0, 0, 0);
459 if (spec->multiout.num_dacs > 1) 1193
460 spec->multiout.num_dacs -= 1; 1194 update_side_mute_status(codec);
461 spec->hp_independent_mode = 1; 1195 /* update HP volume/swtich active state */
462 } 1196 if (spec->codec_type == VT1708S
463 } 1197 || spec->codec_type == VT1702
1198 || spec->codec_type == VT1718S
1199 || spec->codec_type == VT1716S
1200 || spec->codec_type == VT2002P
1201 || spec->codec_type == VT1812) {
1202 activate_ctl(codec, "Headphone Playback Volume",
1203 spec->hp_independent_mode);
1204 activate_ctl(codec, "Headphone Playback Switch",
1205 spec->hp_independent_mode);
464 } 1206 }
465 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
466 pinsel);
467
468 if (spec->multiout.hp_nid &&
469 spec->multiout.hp_nid != spec->multiout.dac_nids[HDA_FRONT])
470 snd_hda_codec_setup_stream(codec,
471 spec->multiout.hp_nid,
472 0, 0, 0);
473
474 return 0; 1207 return 0;
475} 1208}
476 1209
@@ -486,6 +1219,175 @@ static struct snd_kcontrol_new via_hp_mixer[] = {
486 { } /* end */ 1219 { } /* end */
487}; 1220};
488 1221
1222static void notify_aa_path_ctls(struct hda_codec *codec)
1223{
1224 int i;
1225 struct snd_ctl_elem_id id;
1226 const char *labels[] = {"Mic", "Front Mic", "Line"};
1227
1228 memset(&id, 0, sizeof(id));
1229 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1230 for (i = 0; i < ARRAY_SIZE(labels); i++) {
1231 sprintf(id.name, "%s Playback Volume", labels[i]);
1232 snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
1233 &id);
1234 }
1235}
1236
1237static void mute_aa_path(struct hda_codec *codec, int mute)
1238{
1239 struct via_spec *spec = codec->spec;
1240 hda_nid_t nid_mixer;
1241 int start_idx;
1242 int end_idx;
1243 int i;
1244 /* get nid of MW0 and start & end index */
1245 switch (spec->codec_type) {
1246 case VT1708:
1247 nid_mixer = 0x17;
1248 start_idx = 2;
1249 end_idx = 4;
1250 break;
1251 case VT1709_10CH:
1252 case VT1709_6CH:
1253 nid_mixer = 0x18;
1254 start_idx = 2;
1255 end_idx = 4;
1256 break;
1257 case VT1708B_8CH:
1258 case VT1708B_4CH:
1259 case VT1708S:
1260 case VT1716S:
1261 nid_mixer = 0x16;
1262 start_idx = 2;
1263 end_idx = 4;
1264 break;
1265 default:
1266 return;
1267 }
1268 /* check AA path's mute status */
1269 for (i = start_idx; i <= end_idx; i++) {
1270 int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE;
1271 snd_hda_codec_amp_stereo(codec, nid_mixer, HDA_INPUT, i,
1272 HDA_AMP_MUTE, val);
1273 }
1274}
1275static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
1276{
1277 int res = 0;
1278 int index;
1279 for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) {
1280 if (pin == spec->autocfg.input_pins[index]) {
1281 res = 1;
1282 break;
1283 }
1284 }
1285 return res;
1286}
1287
1288static int via_smart51_info(struct snd_kcontrol *kcontrol,
1289 struct snd_ctl_elem_info *uinfo)
1290{
1291 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1292 uinfo->count = 1;
1293 uinfo->value.integer.min = 0;
1294 uinfo->value.integer.max = 1;
1295 return 0;
1296}
1297
1298static int via_smart51_get(struct snd_kcontrol *kcontrol,
1299 struct snd_ctl_elem_value *ucontrol)
1300{
1301 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1302 struct via_spec *spec = codec->spec;
1303 int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
1304 int on = 1;
1305 int i;
1306
1307 for (i = 0; i < ARRAY_SIZE(index); i++) {
1308 hda_nid_t nid = spec->autocfg.input_pins[index[i]];
1309 if (nid) {
1310 int ctl =
1311 snd_hda_codec_read(codec, nid, 0,
1312 AC_VERB_GET_PIN_WIDGET_CONTROL,
1313 0);
1314 if (i == AUTO_PIN_FRONT_MIC
1315 && spec->hp_independent_mode
1316 && spec->codec_type != VT1718S)
1317 continue; /* ignore FMic for independent HP */
1318 if (ctl & AC_PINCTL_IN_EN
1319 && !(ctl & AC_PINCTL_OUT_EN))
1320 on = 0;
1321 }
1322 }
1323 *ucontrol->value.integer.value = on;
1324 return 0;
1325}
1326
1327static int via_smart51_put(struct snd_kcontrol *kcontrol,
1328 struct snd_ctl_elem_value *ucontrol)
1329{
1330 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1331 struct via_spec *spec = codec->spec;
1332 int out_in = *ucontrol->value.integer.value
1333 ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
1334 int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
1335 int i;
1336
1337 for (i = 0; i < ARRAY_SIZE(index); i++) {
1338 hda_nid_t nid = spec->autocfg.input_pins[index[i]];
1339 if (i == AUTO_PIN_FRONT_MIC
1340 && spec->hp_independent_mode
1341 && spec->codec_type != VT1718S)
1342 continue; /* don't retask FMic for independent HP */
1343 if (nid) {
1344 unsigned int parm = snd_hda_codec_read(
1345 codec, nid, 0,
1346 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1347 parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
1348 parm |= out_in;
1349 snd_hda_codec_write(codec, nid, 0,
1350 AC_VERB_SET_PIN_WIDGET_CONTROL,
1351 parm);
1352 if (out_in == AC_PINCTL_OUT_EN) {
1353 mute_aa_path(codec, 1);
1354 notify_aa_path_ctls(codec);
1355 }
1356 if (spec->codec_type == VT1718S)
1357 snd_hda_codec_amp_stereo(
1358 codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
1359 HDA_AMP_UNMUTE);
1360 }
1361 if (i == AUTO_PIN_FRONT_MIC) {
1362 if (spec->codec_type == VT1708S
1363 || spec->codec_type == VT1716S) {
1364 /* input = index 1 (AOW3) */
1365 snd_hda_codec_write(
1366 codec, nid, 0,
1367 AC_VERB_SET_CONNECT_SEL, 1);
1368 snd_hda_codec_amp_stereo(
1369 codec, nid, HDA_OUTPUT,
1370 0, HDA_AMP_MUTE, HDA_AMP_UNMUTE);
1371 }
1372 }
1373 }
1374 spec->smart51_enabled = *ucontrol->value.integer.value;
1375 set_jack_power_state(codec);
1376 return 1;
1377}
1378
1379static struct snd_kcontrol_new via_smart51_mixer[] = {
1380 {
1381 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1382 .name = "Smart 5.1",
1383 .count = 1,
1384 .info = via_smart51_info,
1385 .get = via_smart51_get,
1386 .put = via_smart51_put,
1387 },
1388 {} /* end */
1389};
1390
489/* capture mixer elements */ 1391/* capture mixer elements */
490static struct snd_kcontrol_new vt1708_capture_mixer[] = { 1392static struct snd_kcontrol_new vt1708_capture_mixer[] = {
491 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT), 1393 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
@@ -506,6 +1408,112 @@ static struct snd_kcontrol_new vt1708_capture_mixer[] = {
506 }, 1408 },
507 { } /* end */ 1409 { } /* end */
508}; 1410};
1411
1412/* check AA path's mute statue */
1413static int is_aa_path_mute(struct hda_codec *codec)
1414{
1415 int mute = 1;
1416 hda_nid_t nid_mixer;
1417 int start_idx;
1418 int end_idx;
1419 int i;
1420 struct via_spec *spec = codec->spec;
1421 /* get nid of MW0 and start & end index */
1422 switch (spec->codec_type) {
1423 case VT1708B_8CH:
1424 case VT1708B_4CH:
1425 case VT1708S:
1426 case VT1716S:
1427 nid_mixer = 0x16;
1428 start_idx = 2;
1429 end_idx = 4;
1430 break;
1431 case VT1702:
1432 nid_mixer = 0x1a;
1433 start_idx = 1;
1434 end_idx = 3;
1435 break;
1436 case VT1718S:
1437 nid_mixer = 0x21;
1438 start_idx = 1;
1439 end_idx = 3;
1440 break;
1441 case VT2002P:
1442 case VT1812:
1443 nid_mixer = 0x21;
1444 start_idx = 0;
1445 end_idx = 2;
1446 break;
1447 default:
1448 return 0;
1449 }
1450 /* check AA path's mute status */
1451 for (i = start_idx; i <= end_idx; i++) {
1452 unsigned int con_list = snd_hda_codec_read(
1453 codec, nid_mixer, 0, AC_VERB_GET_CONNECT_LIST, i/4*4);
1454 int shift = 8 * (i % 4);
1455 hda_nid_t nid_pin = (con_list & (0xff << shift)) >> shift;
1456 unsigned int defconf = snd_hda_codec_get_pincfg(codec, nid_pin);
1457 if (get_defcfg_connect(defconf) == AC_JACK_PORT_COMPLEX) {
1458 /* check mute status while the pin is connected */
1459 int mute_l = snd_hda_codec_amp_read(codec, nid_mixer, 0,
1460 HDA_INPUT, i) >> 7;
1461 int mute_r = snd_hda_codec_amp_read(codec, nid_mixer, 1,
1462 HDA_INPUT, i) >> 7;
1463 if (!mute_l || !mute_r) {
1464 mute = 0;
1465 break;
1466 }
1467 }
1468 }
1469 return mute;
1470}
1471
1472/* enter/exit analog low-current mode */
1473static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
1474{
1475 struct via_spec *spec = codec->spec;
1476 static int saved_stream_idle = 1; /* saved stream idle status */
1477 int enable = is_aa_path_mute(codec);
1478 unsigned int verb = 0;
1479 unsigned int parm = 0;
1480
1481 if (stream_idle == -1) /* stream status did not change */
1482 enable = enable && saved_stream_idle;
1483 else {
1484 enable = enable && stream_idle;
1485 saved_stream_idle = stream_idle;
1486 }
1487
1488 /* decide low current mode's verb & parameter */
1489 switch (spec->codec_type) {
1490 case VT1708B_8CH:
1491 case VT1708B_4CH:
1492 verb = 0xf70;
1493 parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
1494 break;
1495 case VT1708S:
1496 case VT1718S:
1497 case VT1716S:
1498 verb = 0xf73;
1499 parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
1500 break;
1501 case VT1702:
1502 verb = 0xf73;
1503 parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
1504 break;
1505 case VT2002P:
1506 case VT1812:
1507 verb = 0xf93;
1508 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
1509 break;
1510 default:
1511 return; /* other codecs are not supported */
1512 }
1513 /* send verb */
1514 snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
1515}
1516
509/* 1517/*
510 * generic initialization of ADC, input mixers and output mixers 1518 * generic initialization of ADC, input mixers and output mixers
511 */ 1519 */
@@ -534,9 +1542,9 @@ static struct hda_verb vt1708_volume_init_verbs[] = {
534 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1542 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
535 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1543 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
536 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 1544 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
537 1545
538 /* Setup default input to PW4 */ 1546 /* Setup default input MW0 to PW4 */
539 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, 1547 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
540 /* PW9 Output enable */ 1548 /* PW9 Output enable */
541 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 1549 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
542 { } 1550 { }
@@ -547,30 +1555,13 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
547 struct snd_pcm_substream *substream) 1555 struct snd_pcm_substream *substream)
548{ 1556{
549 struct via_spec *spec = codec->spec; 1557 struct via_spec *spec = codec->spec;
1558 int idle = substream->pstr->substream_opened == 1
1559 && substream->ref_count == 0;
1560 analog_low_current_mode(codec, idle);
550 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 1561 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
551 hinfo); 1562 hinfo);
552} 1563}
553 1564
554static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
555 struct hda_codec *codec,
556 unsigned int stream_tag,
557 unsigned int format,
558 struct snd_pcm_substream *substream)
559{
560 struct via_spec *spec = codec->spec;
561 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
562 stream_tag, format, substream);
563}
564
565static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
566 struct hda_codec *codec,
567 struct snd_pcm_substream *substream)
568{
569 struct via_spec *spec = codec->spec;
570 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
571}
572
573
574static void playback_multi_pcm_prep_0(struct hda_codec *codec, 1565static void playback_multi_pcm_prep_0(struct hda_codec *codec,
575 unsigned int stream_tag, 1566 unsigned int stream_tag,
576 unsigned int format, 1567 unsigned int format,
@@ -615,8 +1606,8 @@ static void playback_multi_pcm_prep_0(struct hda_codec *codec,
615 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 1606 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
616 0, format); 1607 0, format);
617 1608
618 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] && 1609 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]
619 !spec->hp_independent_mode) 1610 && !spec->hp_independent_mode)
620 /* headphone out will just decode front left/right (stereo) */ 1611 /* headphone out will just decode front left/right (stereo) */
621 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 1612 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
622 0, format); 1613 0, format);
@@ -658,7 +1649,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
658 snd_hda_codec_setup_stream(codec, mout->hp_nid, 1649 snd_hda_codec_setup_stream(codec, mout->hp_nid,
659 stream_tag, 0, format); 1650 stream_tag, 0, format);
660 } 1651 }
661 1652 vt1708_start_hp_work(spec);
662 return 0; 1653 return 0;
663} 1654}
664 1655
@@ -698,7 +1689,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
698 snd_hda_codec_setup_stream(codec, mout->hp_nid, 1689 snd_hda_codec_setup_stream(codec, mout->hp_nid,
699 0, 0, 0); 1690 0, 0, 0);
700 } 1691 }
701 1692 vt1708_stop_hp_work(spec);
702 return 0; 1693 return 0;
703} 1694}
704 1695
@@ -779,7 +1770,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_playback = {
779}; 1770};
780 1771
781static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { 1772static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
782 .substreams = 1, 1773 .substreams = 2,
783 .channels_min = 2, 1774 .channels_min = 2,
784 .channels_max = 8, 1775 .channels_max = 8,
785 .nid = 0x10, /* NID to query formats and rates */ 1776 .nid = 0x10, /* NID to query formats and rates */
@@ -790,8 +1781,8 @@ static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
790 .formats = SNDRV_PCM_FMTBIT_S16_LE, 1781 .formats = SNDRV_PCM_FMTBIT_S16_LE,
791 .ops = { 1782 .ops = {
792 .open = via_playback_pcm_open, 1783 .open = via_playback_pcm_open,
793 .prepare = via_playback_pcm_prepare, 1784 .prepare = via_playback_multi_pcm_prepare,
794 .cleanup = via_playback_pcm_cleanup 1785 .cleanup = via_playback_multi_pcm_cleanup
795 }, 1786 },
796}; 1787};
797 1788
@@ -853,6 +1844,11 @@ static int via_build_controls(struct hda_codec *codec)
853 if (err < 0) 1844 if (err < 0)
854 return err; 1845 return err;
855 } 1846 }
1847
1848 /* init power states */
1849 set_jack_power_state(codec);
1850 analog_low_current_mode(codec, 1);
1851
856 via_free_kctls(codec); /* no longer needed */ 1852 via_free_kctls(codec); /* no longer needed */
857 return 0; 1853 return 0;
858} 1854}
@@ -866,8 +1862,10 @@ static int via_build_pcms(struct hda_codec *codec)
866 codec->pcm_info = info; 1862 codec->pcm_info = info;
867 1863
868 info->name = spec->stream_name_analog; 1864 info->name = spec->stream_name_analog;
869 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); 1865 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
870 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 1866 *(spec->stream_analog_playback);
1867 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
1868 spec->multiout.dac_nids[0];
871 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 1869 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
872 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 1870 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
873 1871
@@ -904,20 +1902,58 @@ static void via_free(struct hda_codec *codec)
904 return; 1902 return;
905 1903
906 via_free_kctls(codec); 1904 via_free_kctls(codec);
1905 vt1708_stop_hp_work(spec);
907 kfree(codec->spec); 1906 kfree(codec->spec);
908} 1907}
909 1908
910/* mute internal speaker if HP is plugged */ 1909/* mute internal speaker if HP is plugged */
911static void via_hp_automute(struct hda_codec *codec) 1910static void via_hp_automute(struct hda_codec *codec)
912{ 1911{
913 unsigned int present; 1912 unsigned int present = 0;
914 struct via_spec *spec = codec->spec; 1913 struct via_spec *spec = codec->spec;
915 1914
916 present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0, 1915 present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
917 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1916
918 snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0], 1917 if (!spec->hp_independent_mode) {
919 HDA_OUTPUT, 0, HDA_AMP_MUTE, 1918 struct snd_ctl_elem_id id;
920 present ? HDA_AMP_MUTE : 0); 1919 /* auto mute */
1920 snd_hda_codec_amp_stereo(
1921 codec, spec->autocfg.line_out_pins[0], HDA_OUTPUT, 0,
1922 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1923 /* notify change */
1924 memset(&id, 0, sizeof(id));
1925 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1926 strcpy(id.name, "Front Playback Switch");
1927 snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
1928 &id);
1929 }
1930}
1931
1932/* mute mono out if HP or Line out is plugged */
1933static void via_mono_automute(struct hda_codec *codec)
1934{
1935 unsigned int hp_present, lineout_present;
1936 struct via_spec *spec = codec->spec;
1937
1938 if (spec->codec_type != VT1716S)
1939 return;
1940
1941 lineout_present = snd_hda_jack_detect(codec,
1942 spec->autocfg.line_out_pins[0]);
1943
1944 /* Mute Mono Out if Line Out is plugged */
1945 if (lineout_present) {
1946 snd_hda_codec_amp_stereo(
1947 codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_MUTE);
1948 return;
1949 }
1950
1951 hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
1952
1953 if (!spec->hp_independent_mode)
1954 snd_hda_codec_amp_stereo(
1955 codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE,
1956 hp_present ? HDA_AMP_MUTE : 0);
921} 1957}
922 1958
923static void via_gpio_control(struct hda_codec *codec) 1959static void via_gpio_control(struct hda_codec *codec)
@@ -968,15 +2004,83 @@ static void via_gpio_control(struct hda_codec *codec)
968 } 2004 }
969} 2005}
970 2006
2007/* mute Internal-Speaker if HP is plugged */
2008static void via_speaker_automute(struct hda_codec *codec)
2009{
2010 unsigned int hp_present;
2011 struct via_spec *spec = codec->spec;
2012
2013 if (spec->codec_type != VT2002P && spec->codec_type != VT1812)
2014 return;
2015
2016 hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
2017
2018 if (!spec->hp_independent_mode) {
2019 struct snd_ctl_elem_id id;
2020 snd_hda_codec_amp_stereo(
2021 codec, spec->autocfg.speaker_pins[0], HDA_OUTPUT, 0,
2022 HDA_AMP_MUTE, hp_present ? HDA_AMP_MUTE : 0);
2023 /* notify change */
2024 memset(&id, 0, sizeof(id));
2025 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2026 strcpy(id.name, "Speaker Playback Switch");
2027 snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
2028 &id);
2029 }
2030}
2031
2032/* mute line-out and internal speaker if HP is plugged */
2033static void via_hp_bind_automute(struct hda_codec *codec)
2034{
2035 /* use long instead of int below just to avoid an internal compiler
2036 * error with gcc 4.0.x
2037 */
2038 unsigned long hp_present, present = 0;
2039 struct via_spec *spec = codec->spec;
2040 int i;
2041
2042 if (!spec->autocfg.hp_pins[0] || !spec->autocfg.line_out_pins[0])
2043 return;
2044
2045 hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
2046
2047 present = snd_hda_jack_detect(codec, spec->autocfg.line_out_pins[0]);
2048
2049 if (!spec->hp_independent_mode) {
2050 /* Mute Line-Outs */
2051 for (i = 0; i < spec->autocfg.line_outs; i++)
2052 snd_hda_codec_amp_stereo(
2053 codec, spec->autocfg.line_out_pins[i],
2054 HDA_OUTPUT, 0,
2055 HDA_AMP_MUTE, hp_present ? HDA_AMP_MUTE : 0);
2056 if (hp_present)
2057 present = hp_present;
2058 }
2059 /* Speakers */
2060 for (i = 0; i < spec->autocfg.speaker_outs; i++)
2061 snd_hda_codec_amp_stereo(
2062 codec, spec->autocfg.speaker_pins[i], HDA_OUTPUT, 0,
2063 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
2064}
2065
2066
971/* unsolicited event for jack sensing */ 2067/* unsolicited event for jack sensing */
972static void via_unsol_event(struct hda_codec *codec, 2068static void via_unsol_event(struct hda_codec *codec,
973 unsigned int res) 2069 unsigned int res)
974{ 2070{
975 res >>= 26; 2071 res >>= 26;
976 if (res == VIA_HP_EVENT) 2072 if (res & VIA_HP_EVENT)
977 via_hp_automute(codec); 2073 via_hp_automute(codec);
978 else if (res == VIA_GPIO_EVENT) 2074 if (res & VIA_GPIO_EVENT)
979 via_gpio_control(codec); 2075 via_gpio_control(codec);
2076 if (res & VIA_JACK_EVENT)
2077 set_jack_power_state(codec);
2078 if (res & VIA_MONO_EVENT)
2079 via_mono_automute(codec);
2080 if (res & VIA_SPEAKER_EVENT)
2081 via_speaker_automute(codec);
2082 if (res & VIA_BIND_HP_EVENT)
2083 via_hp_bind_automute(codec);
980} 2084}
981 2085
982static int via_init(struct hda_codec *codec) 2086static int via_init(struct hda_codec *codec)
@@ -986,6 +2090,10 @@ static int via_init(struct hda_codec *codec)
986 for (i = 0; i < spec->num_iverbs; i++) 2090 for (i = 0; i < spec->num_iverbs; i++)
987 snd_hda_sequence_write(codec, spec->init_verbs[i]); 2091 snd_hda_sequence_write(codec, spec->init_verbs[i]);
988 2092
2093 spec->codec_type = get_codec_type(codec);
2094 if (spec->codec_type == VT1708BCE)
2095 spec->codec_type = VT1708S; /* VT1708BCE & VT1708S are almost
2096 same */
989 /* Lydia Add for EAPD enable */ 2097 /* Lydia Add for EAPD enable */
990 if (!spec->dig_in_nid) { /* No Digital In connection */ 2098 if (!spec->dig_in_nid) { /* No Digital In connection */
991 if (spec->dig_in_pin) { 2099 if (spec->dig_in_pin) {
@@ -1003,8 +2111,17 @@ static int via_init(struct hda_codec *codec)
1003 if (spec->slave_dig_outs[0]) 2111 if (spec->slave_dig_outs[0])
1004 codec->slave_dig_outs = spec->slave_dig_outs; 2112 codec->slave_dig_outs = spec->slave_dig_outs;
1005 2113
1006 return 0; 2114 return 0;
2115}
2116
2117#ifdef SND_HDA_NEEDS_RESUME
2118static int via_suspend(struct hda_codec *codec, pm_message_t state)
2119{
2120 struct via_spec *spec = codec->spec;
2121 vt1708_stop_hp_work(spec);
2122 return 0;
1007} 2123}
2124#endif
1008 2125
1009#ifdef CONFIG_SND_HDA_POWER_SAVE 2126#ifdef CONFIG_SND_HDA_POWER_SAVE
1010static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) 2127static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
@@ -1021,6 +2138,9 @@ static struct hda_codec_ops via_patch_ops = {
1021 .build_pcms = via_build_pcms, 2138 .build_pcms = via_build_pcms,
1022 .init = via_init, 2139 .init = via_init,
1023 .free = via_free, 2140 .free = via_free,
2141#ifdef SND_HDA_NEEDS_RESUME
2142 .suspend = via_suspend,
2143#endif
1024#ifdef CONFIG_SND_HDA_POWER_SAVE 2144#ifdef CONFIG_SND_HDA_POWER_SAVE
1025 .check_power_status = via_check_power_status, 2145 .check_power_status = via_check_power_status,
1026#endif 2146#endif
@@ -1036,8 +2156,8 @@ static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
1036 spec->multiout.num_dacs = cfg->line_outs; 2156 spec->multiout.num_dacs = cfg->line_outs;
1037 2157
1038 spec->multiout.dac_nids = spec->private_dac_nids; 2158 spec->multiout.dac_nids = spec->private_dac_nids;
1039 2159
1040 for(i = 0; i < 4; i++) { 2160 for (i = 0; i < 4; i++) {
1041 nid = cfg->line_out_pins[i]; 2161 nid = cfg->line_out_pins[i];
1042 if (nid) { 2162 if (nid) {
1043 /* config dac list */ 2163 /* config dac list */
@@ -1067,7 +2187,7 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
1067{ 2187{
1068 char name[32]; 2188 char name[32];
1069 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; 2189 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1070 hda_nid_t nid, nid_vol = 0; 2190 hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b};
1071 int i, err; 2191 int i, err;
1072 2192
1073 for (i = 0; i <= AUTO_SEQ_SIDE; i++) { 2193 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
@@ -1075,9 +2195,8 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
1075 2195
1076 if (!nid) 2196 if (!nid)
1077 continue; 2197 continue;
1078 2198
1079 if (i != AUTO_SEQ_FRONT) 2199 nid_vol = nid_vols[i];
1080 nid_vol = 0x18 + i;
1081 2200
1082 if (i == AUTO_SEQ_CENLFE) { 2201 if (i == AUTO_SEQ_CENLFE) {
1083 /* Center/LFE */ 2202 /* Center/LFE */
@@ -1105,21 +2224,21 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
1105 HDA_OUTPUT)); 2224 HDA_OUTPUT));
1106 if (err < 0) 2225 if (err < 0)
1107 return err; 2226 return err;
1108 } else if (i == AUTO_SEQ_FRONT){ 2227 } else if (i == AUTO_SEQ_FRONT) {
1109 /* add control to mixer index 0 */ 2228 /* add control to mixer index 0 */
1110 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2229 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1111 "Master Front Playback Volume", 2230 "Master Front Playback Volume",
1112 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, 2231 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1113 HDA_INPUT)); 2232 HDA_INPUT));
1114 if (err < 0) 2233 if (err < 0)
1115 return err; 2234 return err;
1116 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, 2235 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1117 "Master Front Playback Switch", 2236 "Master Front Playback Switch",
1118 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, 2237 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1119 HDA_INPUT)); 2238 HDA_INPUT));
1120 if (err < 0) 2239 if (err < 0)
1121 return err; 2240 return err;
1122 2241
1123 /* add control to PW3 */ 2242 /* add control to PW3 */
1124 sprintf(name, "%s Playback Volume", chname[i]); 2243 sprintf(name, "%s Playback Volume", chname[i]);
1125 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, 2244 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
@@ -1178,6 +2297,7 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1178 return 0; 2297 return 0;
1179 2298
1180 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */ 2299 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
2300 spec->hp_independent_mode_index = 1;
1181 2301
1182 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2302 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1183 "Headphone Playback Volume", 2303 "Headphone Playback Volume",
@@ -1218,7 +2338,7 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
1218 case 0x1d: /* Mic */ 2338 case 0x1d: /* Mic */
1219 idx = 2; 2339 idx = 2;
1220 break; 2340 break;
1221 2341
1222 case 0x1e: /* Line In */ 2342 case 0x1e: /* Line In */
1223 idx = 3; 2343 idx = 3;
1224 break; 2344 break;
@@ -1231,8 +2351,7 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
1231 idx = 1; 2351 idx = 1;
1232 break; 2352 break;
1233 } 2353 }
1234 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i], 2354 err = via_new_analog_input(spec, labels[i], idx, 0x17);
1235 idx, 0x17);
1236 if (err < 0) 2355 if (err < 0)
1237 return err; 2356 return err;
1238 imux->items[imux->num_items].label = labels[i]; 2357 imux->items[imux->num_items].label = labels[i];
@@ -1260,16 +2379,60 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
1260 def_conf = snd_hda_codec_get_pincfg(codec, nid); 2379 def_conf = snd_hda_codec_get_pincfg(codec, nid);
1261 seqassoc = (unsigned char) get_defcfg_association(def_conf); 2380 seqassoc = (unsigned char) get_defcfg_association(def_conf);
1262 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); 2381 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
1263 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { 2382 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
1264 if (seqassoc == 0xff) { 2383 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
1265 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); 2384 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
1266 snd_hda_codec_set_pincfg(codec, nid, def_conf); 2385 snd_hda_codec_set_pincfg(codec, nid, def_conf);
1267 }
1268 } 2386 }
1269 2387
1270 return; 2388 return;
1271} 2389}
1272 2390
2391static int vt1708_jack_detectect_get(struct snd_kcontrol *kcontrol,
2392 struct snd_ctl_elem_value *ucontrol)
2393{
2394 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2395 struct via_spec *spec = codec->spec;
2396
2397 if (spec->codec_type != VT1708)
2398 return 0;
2399 spec->vt1708_jack_detectect =
2400 !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
2401 ucontrol->value.integer.value[0] = spec->vt1708_jack_detectect;
2402 return 0;
2403}
2404
2405static int vt1708_jack_detectect_put(struct snd_kcontrol *kcontrol,
2406 struct snd_ctl_elem_value *ucontrol)
2407{
2408 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2409 struct via_spec *spec = codec->spec;
2410 int change;
2411
2412 if (spec->codec_type != VT1708)
2413 return 0;
2414 spec->vt1708_jack_detectect = ucontrol->value.integer.value[0];
2415 change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
2416 == !spec->vt1708_jack_detectect;
2417 if (spec->vt1708_jack_detectect) {
2418 mute_aa_path(codec, 1);
2419 notify_aa_path_ctls(codec);
2420 }
2421 return change;
2422}
2423
2424static struct snd_kcontrol_new vt1708_jack_detectect[] = {
2425 {
2426 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2427 .name = "Jack Detect",
2428 .count = 1,
2429 .info = snd_ctl_boolean_mono_info,
2430 .get = vt1708_jack_detectect_get,
2431 .put = vt1708_jack_detectect_put,
2432 },
2433 {} /* end */
2434};
2435
1273static int vt1708_parse_auto_config(struct hda_codec *codec) 2436static int vt1708_parse_auto_config(struct hda_codec *codec)
1274{ 2437{
1275 struct via_spec *spec = codec->spec; 2438 struct via_spec *spec = codec->spec;
@@ -1297,6 +2460,10 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
1297 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg); 2460 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
1298 if (err < 0) 2461 if (err < 0)
1299 return err; 2462 return err;
2463 /* add jack detect on/off control */
2464 err = snd_hda_add_new_ctls(codec, vt1708_jack_detectect);
2465 if (err < 0)
2466 return err;
1300 2467
1301 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 2468 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1302 2469
@@ -1316,19 +2483,44 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
1316 if (spec->hp_mux) 2483 if (spec->hp_mux)
1317 spec->mixers[spec->num_mixers++] = via_hp_mixer; 2484 spec->mixers[spec->num_mixers++] = via_hp_mixer;
1318 2485
2486 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
1319 return 1; 2487 return 1;
1320} 2488}
1321 2489
1322/* init callback for auto-configuration model -- overriding the default init */ 2490/* init callback for auto-configuration model -- overriding the default init */
1323static int via_auto_init(struct hda_codec *codec) 2491static int via_auto_init(struct hda_codec *codec)
1324{ 2492{
2493 struct via_spec *spec = codec->spec;
2494
1325 via_init(codec); 2495 via_init(codec);
1326 via_auto_init_multi_out(codec); 2496 via_auto_init_multi_out(codec);
1327 via_auto_init_hp_out(codec); 2497 via_auto_init_hp_out(codec);
1328 via_auto_init_analog_input(codec); 2498 via_auto_init_analog_input(codec);
2499 if (spec->codec_type == VT2002P || spec->codec_type == VT1812) {
2500 via_hp_bind_automute(codec);
2501 } else {
2502 via_hp_automute(codec);
2503 via_speaker_automute(codec);
2504 }
2505
1329 return 0; 2506 return 0;
1330} 2507}
1331 2508
2509static void vt1708_update_hp_jack_state(struct work_struct *work)
2510{
2511 struct via_spec *spec = container_of(work, struct via_spec,
2512 vt1708_hp_work.work);
2513 if (spec->codec_type != VT1708)
2514 return;
2515 /* if jack state toggled */
2516 if (spec->vt1708_hp_present
2517 != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) {
2518 spec->vt1708_hp_present ^= 1;
2519 via_hp_automute(spec->codec);
2520 }
2521 vt1708_start_hp_work(spec);
2522}
2523
1332static int get_mux_nids(struct hda_codec *codec) 2524static int get_mux_nids(struct hda_codec *codec)
1333{ 2525{
1334 struct via_spec *spec = codec->spec; 2526 struct via_spec *spec = codec->spec;
@@ -1378,7 +2570,7 @@ static int patch_vt1708(struct hda_codec *codec)
1378 "from BIOS. Using genenic mode...\n"); 2570 "from BIOS. Using genenic mode...\n");
1379 } 2571 }
1380 2572
1381 2573
1382 spec->stream_name_analog = "VT1708 Analog"; 2574 spec->stream_name_analog = "VT1708 Analog";
1383 spec->stream_analog_playback = &vt1708_pcm_analog_playback; 2575 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
1384 /* disable 32bit format on VT1708 */ 2576 /* disable 32bit format on VT1708 */
@@ -1390,7 +2582,7 @@ static int patch_vt1708(struct hda_codec *codec)
1390 spec->stream_digital_playback = &vt1708_pcm_digital_playback; 2582 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
1391 spec->stream_digital_capture = &vt1708_pcm_digital_capture; 2583 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
1392 2584
1393 2585
1394 if (!spec->adc_nids && spec->input_mux) { 2586 if (!spec->adc_nids && spec->input_mux) {
1395 spec->adc_nids = vt1708_adc_nids; 2587 spec->adc_nids = vt1708_adc_nids;
1396 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids); 2588 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
@@ -1405,7 +2597,8 @@ static int patch_vt1708(struct hda_codec *codec)
1405#ifdef CONFIG_SND_HDA_POWER_SAVE 2597#ifdef CONFIG_SND_HDA_POWER_SAVE
1406 spec->loopback.amplist = vt1708_loopbacks; 2598 spec->loopback.amplist = vt1708_loopbacks;
1407#endif 2599#endif
1408 2600 spec->codec = codec;
2601 INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state);
1409 return 0; 2602 return 0;
1410} 2603}
1411 2604
@@ -1433,7 +2626,8 @@ static struct snd_kcontrol_new vt1709_capture_mixer[] = {
1433}; 2626};
1434 2627
1435static struct hda_verb vt1709_uniwill_init_verbs[] = { 2628static struct hda_verb vt1709_uniwill_init_verbs[] = {
1436 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT}, 2629 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE,
2630 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
1437 { } 2631 { }
1438}; 2632};
1439 2633
@@ -1473,8 +2667,8 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
1473 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2667 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1474 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2668 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1475 2669
1476 /* Set input of PW4 as AOW4 */ 2670 /* Set input of PW4 as MW0 */
1477 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, 2671 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1478 /* PW9 Output enable */ 2672 /* PW9 Output enable */
1479 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 2673 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1480 { } 2674 { }
@@ -1487,8 +2681,8 @@ static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
1487 .nid = 0x10, /* NID to query formats and rates */ 2681 .nid = 0x10, /* NID to query formats and rates */
1488 .ops = { 2682 .ops = {
1489 .open = via_playback_pcm_open, 2683 .open = via_playback_pcm_open,
1490 .prepare = via_playback_pcm_prepare, 2684 .prepare = via_playback_multi_pcm_prepare,
1491 .cleanup = via_playback_pcm_cleanup 2685 .cleanup = via_playback_multi_pcm_cleanup,
1492 }, 2686 },
1493}; 2687};
1494 2688
@@ -1499,8 +2693,8 @@ static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1499 .nid = 0x10, /* NID to query formats and rates */ 2693 .nid = 0x10, /* NID to query formats and rates */
1500 .ops = { 2694 .ops = {
1501 .open = via_playback_pcm_open, 2695 .open = via_playback_pcm_open,
1502 .prepare = via_playback_pcm_prepare, 2696 .prepare = via_playback_multi_pcm_prepare,
1503 .cleanup = via_playback_pcm_cleanup 2697 .cleanup = via_playback_multi_pcm_cleanup,
1504 }, 2698 },
1505}; 2699};
1506 2700
@@ -1575,11 +2769,11 @@ static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1575 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */ 2769 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1576 2770
1577 } else if (cfg->line_outs == 3) { /* 6 channels */ 2771 } else if (cfg->line_outs == 3) { /* 6 channels */
1578 for(i = 0; i < cfg->line_outs; i++) { 2772 for (i = 0; i < cfg->line_outs; i++) {
1579 nid = cfg->line_out_pins[i]; 2773 nid = cfg->line_out_pins[i];
1580 if (nid) { 2774 if (nid) {
1581 /* config dac list */ 2775 /* config dac list */
1582 switch(i) { 2776 switch (i) {
1583 case AUTO_SEQ_FRONT: 2777 case AUTO_SEQ_FRONT:
1584 /* AOW0 */ 2778 /* AOW0 */
1585 spec->multiout.dac_nids[i] = 0x10; 2779 spec->multiout.dac_nids[i] = 0x10;
@@ -1608,56 +2802,58 @@ static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1608{ 2802{
1609 char name[32]; 2803 char name[32];
1610 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; 2804 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1611 hda_nid_t nid = 0; 2805 hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29};
1612 int i, err; 2806 int i, err;
1613 2807
1614 for (i = 0; i <= AUTO_SEQ_SIDE; i++) { 2808 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1615 nid = cfg->line_out_pins[i]; 2809 nid = cfg->line_out_pins[i];
1616 2810
1617 if (!nid) 2811 if (!nid)
1618 continue; 2812 continue;
1619 2813
2814 nid_vol = nid_vols[i];
2815
1620 if (i == AUTO_SEQ_CENLFE) { 2816 if (i == AUTO_SEQ_CENLFE) {
1621 /* Center/LFE */ 2817 /* Center/LFE */
1622 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2818 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1623 "Center Playback Volume", 2819 "Center Playback Volume",
1624 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, 2820 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1625 HDA_OUTPUT)); 2821 HDA_OUTPUT));
1626 if (err < 0) 2822 if (err < 0)
1627 return err; 2823 return err;
1628 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2824 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1629 "LFE Playback Volume", 2825 "LFE Playback Volume",
1630 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, 2826 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1631 HDA_OUTPUT)); 2827 HDA_OUTPUT));
1632 if (err < 0) 2828 if (err < 0)
1633 return err; 2829 return err;
1634 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, 2830 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1635 "Center Playback Switch", 2831 "Center Playback Switch",
1636 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, 2832 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1637 HDA_OUTPUT)); 2833 HDA_OUTPUT));
1638 if (err < 0) 2834 if (err < 0)
1639 return err; 2835 return err;
1640 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, 2836 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1641 "LFE Playback Switch", 2837 "LFE Playback Switch",
1642 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, 2838 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1643 HDA_OUTPUT)); 2839 HDA_OUTPUT));
1644 if (err < 0) 2840 if (err < 0)
1645 return err; 2841 return err;
1646 } else if (i == AUTO_SEQ_FRONT){ 2842 } else if (i == AUTO_SEQ_FRONT) {
1647 /* add control to mixer index 0 */ 2843 /* ADD control to mixer index 0 */
1648 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2844 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1649 "Master Front Playback Volume", 2845 "Master Front Playback Volume",
1650 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, 2846 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1651 HDA_INPUT)); 2847 HDA_INPUT));
1652 if (err < 0) 2848 if (err < 0)
1653 return err; 2849 return err;
1654 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, 2850 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1655 "Master Front Playback Switch", 2851 "Master Front Playback Switch",
1656 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, 2852 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1657 HDA_INPUT)); 2853 HDA_INPUT));
1658 if (err < 0) 2854 if (err < 0)
1659 return err; 2855 return err;
1660 2856
1661 /* add control to PW3 */ 2857 /* add control to PW3 */
1662 sprintf(name, "%s Playback Volume", chname[i]); 2858 sprintf(name, "%s Playback Volume", chname[i]);
1663 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, 2859 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
@@ -1674,26 +2870,26 @@ static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1674 } else if (i == AUTO_SEQ_SURROUND) { 2870 } else if (i == AUTO_SEQ_SURROUND) {
1675 sprintf(name, "%s Playback Volume", chname[i]); 2871 sprintf(name, "%s Playback Volume", chname[i]);
1676 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, 2872 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1677 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, 2873 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1678 HDA_OUTPUT)); 2874 HDA_OUTPUT));
1679 if (err < 0) 2875 if (err < 0)
1680 return err; 2876 return err;
1681 sprintf(name, "%s Playback Switch", chname[i]); 2877 sprintf(name, "%s Playback Switch", chname[i]);
1682 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, 2878 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1683 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, 2879 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1684 HDA_OUTPUT)); 2880 HDA_OUTPUT));
1685 if (err < 0) 2881 if (err < 0)
1686 return err; 2882 return err;
1687 } else if (i == AUTO_SEQ_SIDE) { 2883 } else if (i == AUTO_SEQ_SIDE) {
1688 sprintf(name, "%s Playback Volume", chname[i]); 2884 sprintf(name, "%s Playback Volume", chname[i]);
1689 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, 2885 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1690 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, 2886 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1691 HDA_OUTPUT)); 2887 HDA_OUTPUT));
1692 if (err < 0) 2888 if (err < 0)
1693 return err; 2889 return err;
1694 sprintf(name, "%s Playback Switch", chname[i]); 2890 sprintf(name, "%s Playback Switch", chname[i]);
1695 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, 2891 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1696 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, 2892 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1697 HDA_OUTPUT)); 2893 HDA_OUTPUT));
1698 if (err < 0) 2894 if (err < 0)
1699 return err; 2895 return err;
@@ -1714,6 +2910,7 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1714 spec->multiout.hp_nid = VT1709_HP_DAC_NID; 2910 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1715 else if (spec->multiout.num_dacs == 3) /* 6 channels */ 2911 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1716 spec->multiout.hp_nid = 0; 2912 spec->multiout.hp_nid = 0;
2913 spec->hp_independent_mode_index = 1;
1717 2914
1718 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 2915 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1719 "Headphone Playback Volume", 2916 "Headphone Playback Volume",
@@ -1752,7 +2949,7 @@ static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1752 case 0x1d: /* Mic */ 2949 case 0x1d: /* Mic */
1753 idx = 2; 2950 idx = 2;
1754 break; 2951 break;
1755 2952
1756 case 0x1e: /* Line In */ 2953 case 0x1e: /* Line In */
1757 idx = 3; 2954 idx = 3;
1758 break; 2955 break;
@@ -1765,8 +2962,7 @@ static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1765 idx = 1; 2962 idx = 1;
1766 break; 2963 break;
1767 } 2964 }
1768 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i], 2965 err = via_new_analog_input(spec, labels[i], idx, 0x18);
1769 idx, 0x18);
1770 if (err < 0) 2966 if (err < 0)
1771 return err; 2967 return err;
1772 imux->items[imux->num_items].label = labels[i]; 2968 imux->items[imux->num_items].label = labels[i];
@@ -1816,6 +3012,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
1816 if (spec->hp_mux) 3012 if (spec->hp_mux)
1817 spec->mixers[spec->num_mixers++] = via_hp_mixer; 3013 spec->mixers[spec->num_mixers++] = via_hp_mixer;
1818 3014
3015 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
1819 return 1; 3016 return 1;
1820} 3017}
1821 3018
@@ -1861,7 +3058,7 @@ static int patch_vt1709_10ch(struct hda_codec *codec)
1861 spec->stream_digital_playback = &vt1709_pcm_digital_playback; 3058 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1862 spec->stream_digital_capture = &vt1709_pcm_digital_capture; 3059 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1863 3060
1864 3061
1865 if (!spec->adc_nids && spec->input_mux) { 3062 if (!spec->adc_nids && spec->input_mux) {
1866 spec->adc_nids = vt1709_adc_nids; 3063 spec->adc_nids = vt1709_adc_nids;
1867 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids); 3064 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
@@ -1955,7 +3152,7 @@ static int patch_vt1709_6ch(struct hda_codec *codec)
1955 spec->stream_digital_playback = &vt1709_pcm_digital_playback; 3152 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1956 spec->stream_digital_capture = &vt1709_pcm_digital_capture; 3153 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1957 3154
1958 3155
1959 if (!spec->adc_nids && spec->input_mux) { 3156 if (!spec->adc_nids && spec->input_mux) {
1960 spec->adc_nids = vt1709_adc_nids; 3157 spec->adc_nids = vt1709_adc_nids;
1961 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids); 3158 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
@@ -2024,7 +3221,7 @@ static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
2024 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3221 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2025 3222
2026 /* Setup default input to PW4 */ 3223 /* Setup default input to PW4 */
2027 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, 3224 {0x1d, AC_VERB_SET_CONNECT_SEL, 0},
2028 /* PW9 Output enable */ 3225 /* PW9 Output enable */
2029 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3226 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2030 /* PW10 Input enable */ 3227 /* PW10 Input enable */
@@ -2068,10 +3265,29 @@ static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
2068}; 3265};
2069 3266
2070static struct hda_verb vt1708B_uniwill_init_verbs[] = { 3267static struct hda_verb vt1708B_uniwill_init_verbs[] = {
2071 {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT}, 3268 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
3269 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
3270 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3271 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3272 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3273 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3274 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3275 {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3276 {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
2072 { } 3277 { }
2073}; 3278};
2074 3279
3280static int via_pcm_open_close(struct hda_pcm_stream *hinfo,
3281 struct hda_codec *codec,
3282 struct snd_pcm_substream *substream)
3283{
3284 int idle = substream->pstr->substream_opened == 1
3285 && substream->ref_count == 0;
3286
3287 analog_low_current_mode(codec, idle);
3288 return 0;
3289}
3290
2075static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = { 3291static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
2076 .substreams = 2, 3292 .substreams = 2,
2077 .channels_min = 2, 3293 .channels_min = 2,
@@ -2080,7 +3296,8 @@ static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
2080 .ops = { 3296 .ops = {
2081 .open = via_playback_pcm_open, 3297 .open = via_playback_pcm_open,
2082 .prepare = via_playback_multi_pcm_prepare, 3298 .prepare = via_playback_multi_pcm_prepare,
2083 .cleanup = via_playback_multi_pcm_cleanup 3299 .cleanup = via_playback_multi_pcm_cleanup,
3300 .close = via_pcm_open_close
2084 }, 3301 },
2085}; 3302};
2086 3303
@@ -2102,8 +3319,10 @@ static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
2102 .channels_max = 2, 3319 .channels_max = 2,
2103 .nid = 0x13, /* NID to query formats and rates */ 3320 .nid = 0x13, /* NID to query formats and rates */
2104 .ops = { 3321 .ops = {
3322 .open = via_pcm_open_close,
2105 .prepare = via_capture_pcm_prepare, 3323 .prepare = via_capture_pcm_prepare,
2106 .cleanup = via_capture_pcm_cleanup 3324 .cleanup = via_capture_pcm_cleanup,
3325 .close = via_pcm_open_close
2107 }, 3326 },
2108}; 3327};
2109 3328
@@ -2260,6 +3479,7 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2260 return 0; 3479 return 0;
2261 3480
2262 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */ 3481 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
3482 spec->hp_independent_mode_index = 1;
2263 3483
2264 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 3484 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2265 "Headphone Playback Volume", 3485 "Headphone Playback Volume",
@@ -2313,8 +3533,7 @@ static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
2313 idx = 1; 3533 idx = 1;
2314 break; 3534 break;
2315 } 3535 }
2316 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i], 3536 err = via_new_analog_input(spec, labels[i], idx, 0x16);
2317 idx, 0x16);
2318 if (err < 0) 3537 if (err < 0)
2319 return err; 3538 return err;
2320 imux->items[imux->num_items].label = labels[i]; 3539 imux->items[imux->num_items].label = labels[i];
@@ -2364,6 +3583,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
2364 if (spec->hp_mux) 3583 if (spec->hp_mux)
2365 spec->mixers[spec->num_mixers++] = via_hp_mixer; 3584 spec->mixers[spec->num_mixers++] = via_hp_mixer;
2366 3585
3586 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
2367 return 1; 3587 return 1;
2368} 3588}
2369 3589
@@ -2376,12 +3596,14 @@ static struct hda_amp_list vt1708B_loopbacks[] = {
2376 { } /* end */ 3596 { } /* end */
2377}; 3597};
2378#endif 3598#endif
2379 3599static int patch_vt1708S(struct hda_codec *codec);
2380static int patch_vt1708B_8ch(struct hda_codec *codec) 3600static int patch_vt1708B_8ch(struct hda_codec *codec)
2381{ 3601{
2382 struct via_spec *spec; 3602 struct via_spec *spec;
2383 int err; 3603 int err;
2384 3604
3605 if (get_codec_type(codec) == VT1708BCE)
3606 return patch_vt1708S(codec);
2385 /* create a codec specific record */ 3607 /* create a codec specific record */
2386 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3608 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2387 if (spec == NULL) 3609 if (spec == NULL)
@@ -2483,29 +3705,15 @@ static int patch_vt1708B_4ch(struct hda_codec *codec)
2483 3705
2484/* Patch for VT1708S */ 3706/* Patch for VT1708S */
2485 3707
2486/* VT1708S software backdoor based override for buggy hardware micboost
2487 * setting */
2488#define MIC_BOOST_VOLUME(xname, nid) { \
2489 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2490 .name = xname, \
2491 .index = 0, \
2492 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2493 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2494 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
2495 .info = mic_boost_volume_info, \
2496 .get = snd_hda_mixer_amp_volume_get, \
2497 .put = snd_hda_mixer_amp_volume_put, \
2498 .tlv = { .c = mic_boost_tlv }, \
2499 .private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT) }
2500
2501/* capture mixer elements */ 3708/* capture mixer elements */
2502static struct snd_kcontrol_new vt1708S_capture_mixer[] = { 3709static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
2503 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), 3710 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
2504 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), 3711 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
2505 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), 3712 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
2506 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT), 3713 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
2507 MIC_BOOST_VOLUME("Mic Boost Capture Volume", 0x1A), 3714 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x1A, 0x0, HDA_INPUT),
2508 MIC_BOOST_VOLUME("Front Mic Boost Capture Volume", 0x1E), 3715 HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x1E, 0x0,
3716 HDA_INPUT),
2509 { 3717 {
2510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2511 /* The multiple "Capture Source" controls confuse alsamixer 3719 /* The multiple "Capture Source" controls confuse alsamixer
@@ -2542,11 +3750,21 @@ static struct hda_verb vt1708S_volume_init_verbs[] = {
2542 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 3750 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2543 /* Enable Mic Boost Volume backdoor */ 3751 /* Enable Mic Boost Volume backdoor */
2544 {0x1, 0xf98, 0x1}, 3752 {0x1, 0xf98, 0x1},
3753 /* don't bybass mixer */
3754 {0x1, 0xf88, 0xc0},
2545 { } 3755 { }
2546}; 3756};
2547 3757
2548static struct hda_verb vt1708S_uniwill_init_verbs[] = { 3758static struct hda_verb vt1708S_uniwill_init_verbs[] = {
2549 {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT}, 3759 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
3760 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
3761 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3762 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3763 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3764 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3765 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3766 {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
3767 {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
2550 { } 3768 { }
2551}; 3769};
2552 3770
@@ -2557,8 +3775,9 @@ static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
2557 .nid = 0x10, /* NID to query formats and rates */ 3775 .nid = 0x10, /* NID to query formats and rates */
2558 .ops = { 3776 .ops = {
2559 .open = via_playback_pcm_open, 3777 .open = via_playback_pcm_open,
2560 .prepare = via_playback_pcm_prepare, 3778 .prepare = via_playback_multi_pcm_prepare,
2561 .cleanup = via_playback_pcm_cleanup 3779 .cleanup = via_playback_multi_pcm_cleanup,
3780 .close = via_pcm_open_close
2562 }, 3781 },
2563}; 3782};
2564 3783
@@ -2568,8 +3787,10 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
2568 .channels_max = 2, 3787 .channels_max = 2,
2569 .nid = 0x13, /* NID to query formats and rates */ 3788 .nid = 0x13, /* NID to query formats and rates */
2570 .ops = { 3789 .ops = {
3790 .open = via_pcm_open_close,
2571 .prepare = via_capture_pcm_prepare, 3791 .prepare = via_capture_pcm_prepare,
2572 .cleanup = via_capture_pcm_cleanup 3792 .cleanup = via_capture_pcm_cleanup,
3793 .close = via_pcm_open_close
2573 }, 3794 },
2574}; 3795};
2575 3796
@@ -2726,6 +3947,7 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2726 return 0; 3947 return 0;
2727 3948
2728 spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */ 3949 spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */
3950 spec->hp_independent_mode_index = 1;
2729 3951
2730 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 3952 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2731 "Headphone Playback Volume", 3953 "Headphone Playback Volume",
@@ -2780,8 +4002,7 @@ static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
2780 idx = 1; 4002 idx = 1;
2781 break; 4003 break;
2782 } 4004 }
2783 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i], 4005 err = via_new_analog_input(spec, labels[i], idx, 0x16);
2784 idx, 0x16);
2785 if (err < 0) 4006 if (err < 0)
2786 return err; 4007 return err;
2787 imux->items[imux->num_items].label = labels[i]; 4008 imux->items[imux->num_items].label = labels[i];
@@ -2852,6 +4073,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
2852 if (spec->hp_mux) 4073 if (spec->hp_mux)
2853 spec->mixers[spec->num_mixers++] = via_hp_mixer; 4074 spec->mixers[spec->num_mixers++] = via_hp_mixer;
2854 4075
4076 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
2855 return 1; 4077 return 1;
2856} 4078}
2857 4079
@@ -2865,6 +4087,16 @@ static struct hda_amp_list vt1708S_loopbacks[] = {
2865}; 4087};
2866#endif 4088#endif
2867 4089
4090static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
4091 int offset, int num_steps, int step_size)
4092{
4093 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
4094 (offset << AC_AMPCAP_OFFSET_SHIFT) |
4095 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
4096 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
4097 (0 << AC_AMPCAP_MUTE_SHIFT));
4098}
4099
2868static int patch_vt1708S(struct hda_codec *codec) 4100static int patch_vt1708S(struct hda_codec *codec)
2869{ 4101{
2870 struct via_spec *spec; 4102 struct via_spec *spec;
@@ -2890,17 +4122,25 @@ static int patch_vt1708S(struct hda_codec *codec)
2890 spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs; 4122 spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
2891 spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs; 4123 spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
2892 4124
2893 spec->stream_name_analog = "VT1708S Analog"; 4125 if (codec->vendor_id == 0x11060440)
4126 spec->stream_name_analog = "VT1818S Analog";
4127 else
4128 spec->stream_name_analog = "VT1708S Analog";
2894 spec->stream_analog_playback = &vt1708S_pcm_analog_playback; 4129 spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
2895 spec->stream_analog_capture = &vt1708S_pcm_analog_capture; 4130 spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
2896 4131
2897 spec->stream_name_digital = "VT1708S Digital"; 4132 if (codec->vendor_id == 0x11060440)
4133 spec->stream_name_digital = "VT1818S Digital";
4134 else
4135 spec->stream_name_digital = "VT1708S Digital";
2898 spec->stream_digital_playback = &vt1708S_pcm_digital_playback; 4136 spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
2899 4137
2900 if (!spec->adc_nids && spec->input_mux) { 4138 if (!spec->adc_nids && spec->input_mux) {
2901 spec->adc_nids = vt1708S_adc_nids; 4139 spec->adc_nids = vt1708S_adc_nids;
2902 spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids); 4140 spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
2903 get_mux_nids(codec); 4141 get_mux_nids(codec);
4142 override_mic_boost(codec, 0x1a, 0, 3, 40);
4143 override_mic_boost(codec, 0x1e, 0, 3, 40);
2904 spec->mixers[spec->num_mixers] = vt1708S_capture_mixer; 4144 spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
2905 spec->num_mixers++; 4145 spec->num_mixers++;
2906 } 4146 }
@@ -2913,6 +4153,16 @@ static int patch_vt1708S(struct hda_codec *codec)
2913 spec->loopback.amplist = vt1708S_loopbacks; 4153 spec->loopback.amplist = vt1708S_loopbacks;
2914#endif 4154#endif
2915 4155
4156 /* correct names for VT1708BCE */
4157 if (get_codec_type(codec) == VT1708BCE) {
4158 kfree(codec->chip_name);
4159 codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
4160 snprintf(codec->bus->card->mixername,
4161 sizeof(codec->bus->card->mixername),
4162 "%s %s", codec->vendor_name, codec->chip_name);
4163 spec->stream_name_analog = "VT1708BCE Analog";
4164 spec->stream_name_digital = "VT1708BCE Digital";
4165 }
2916 return 0; 4166 return 0;
2917} 4167}
2918 4168
@@ -2967,12 +4217,20 @@ static struct hda_verb vt1702_volume_init_verbs[] = {
2967 /* PW6 PW7 Output enable */ 4217 /* PW6 PW7 Output enable */
2968 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 4218 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2969 {0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, 4219 {0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4220 /* mixer enable */
4221 {0x1, 0xF88, 0x3},
4222 /* GPIO 0~2 */
4223 {0x1, 0xF82, 0x3F},
2970 { } 4224 { }
2971}; 4225};
2972 4226
2973static struct hda_verb vt1702_uniwill_init_verbs[] = { 4227static struct hda_verb vt1702_uniwill_init_verbs[] = {
2974 {0x01, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_GPIO_EVENT}, 4228 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE,
2975 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT}, 4229 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
4230 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4231 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4232 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4233 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
2976 { } 4234 { }
2977}; 4235};
2978 4236
@@ -2984,7 +4242,8 @@ static struct hda_pcm_stream vt1702_pcm_analog_playback = {
2984 .ops = { 4242 .ops = {
2985 .open = via_playback_pcm_open, 4243 .open = via_playback_pcm_open,
2986 .prepare = via_playback_multi_pcm_prepare, 4244 .prepare = via_playback_multi_pcm_prepare,
2987 .cleanup = via_playback_multi_pcm_cleanup 4245 .cleanup = via_playback_multi_pcm_cleanup,
4246 .close = via_pcm_open_close
2988 }, 4247 },
2989}; 4248};
2990 4249
@@ -2994,8 +4253,10 @@ static struct hda_pcm_stream vt1702_pcm_analog_capture = {
2994 .channels_max = 2, 4253 .channels_max = 2,
2995 .nid = 0x12, /* NID to query formats and rates */ 4254 .nid = 0x12, /* NID to query formats and rates */
2996 .ops = { 4255 .ops = {
4256 .open = via_pcm_open_close,
2997 .prepare = via_capture_pcm_prepare, 4257 .prepare = via_capture_pcm_prepare,
2998 .cleanup = via_capture_pcm_cleanup 4258 .cleanup = via_capture_pcm_cleanup,
4259 .close = via_pcm_open_close
2999 }, 4260 },
3000}; 4261};
3001 4262
@@ -3065,12 +4326,13 @@ static int vt1702_auto_create_line_out_ctls(struct via_spec *spec,
3065 4326
3066static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) 4327static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
3067{ 4328{
3068 int err; 4329 int err, i;
3069 4330 struct hda_input_mux *imux;
4331 static const char *texts[] = { "ON", "OFF", NULL};
3070 if (!pin) 4332 if (!pin)
3071 return 0; 4333 return 0;
3072
3073 spec->multiout.hp_nid = 0x1D; 4334 spec->multiout.hp_nid = 0x1D;
4335 spec->hp_independent_mode_index = 0;
3074 4336
3075 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 4337 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
3076 "Headphone Playback Volume", 4338 "Headphone Playback Volume",
@@ -3084,8 +4346,18 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
3084 if (err < 0) 4346 if (err < 0)
3085 return err; 4347 return err;
3086 4348
3087 create_hp_imux(spec); 4349 imux = &spec->private_imux[1];
3088 4350
4351 /* for hp mode select */
4352 i = 0;
4353 while (texts[i] != NULL) {
4354 imux->items[imux->num_items].label = texts[i];
4355 imux->items[imux->num_items].index = i;
4356 imux->num_items++;
4357 i++;
4358 }
4359
4360 spec->hp_mux = &spec->private_imux[1];
3089 return 0; 4361 return 0;
3090} 4362}
3091 4363
@@ -3121,8 +4393,7 @@ static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
3121 idx = 3; 4393 idx = 3;
3122 break; 4394 break;
3123 } 4395 }
3124 err = via_new_analog_input(spec, cfg->input_pins[i], 4396 err = via_new_analog_input(spec, labels[i], idx, 0x1A);
3125 labels[i], idx, 0x1A);
3126 if (err < 0) 4397 if (err < 0)
3127 return err; 4398 return err;
3128 imux->items[imux->num_items].label = labels[i]; 4399 imux->items[imux->num_items].label = labels[i];
@@ -3152,6 +4423,12 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
3152 err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 4423 err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
3153 if (err < 0) 4424 if (err < 0)
3154 return err; 4425 return err;
4426 /* limit AA path volume to 0 dB */
4427 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
4428 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4429 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4430 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4431 (1 << AC_AMPCAP_MUTE_SHIFT));
3155 err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg); 4432 err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
3156 if (err < 0) 4433 if (err < 0)
3157 return err; 4434 return err;
@@ -3185,8 +4462,6 @@ static int patch_vt1702(struct hda_codec *codec)
3185{ 4462{
3186 struct via_spec *spec; 4463 struct via_spec *spec;
3187 int err; 4464 int err;
3188 unsigned int response;
3189 unsigned char control;
3190 4465
3191 /* create a codec specific record */ 4466 /* create a codec specific record */
3192 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 4467 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -3231,17 +4506,1638 @@ static int patch_vt1702(struct hda_codec *codec)
3231 spec->loopback.amplist = vt1702_loopbacks; 4506 spec->loopback.amplist = vt1702_loopbacks;
3232#endif 4507#endif
3233 4508
3234 /* Open backdoor */ 4509 return 0;
3235 response = snd_hda_codec_read(codec, codec->afg, 0, 0xF8C, 0); 4510}
3236 control = (unsigned char)(response & 0xff); 4511
3237 control |= 0x3; 4512/* Patch for VT1718S */
3238 snd_hda_codec_write(codec, codec->afg, 0, 0xF88, control); 4513
4514/* capture mixer elements */
4515static struct snd_kcontrol_new vt1718S_capture_mixer[] = {
4516 HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
4517 HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
4518 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
4519 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
4520 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
4521 HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x29, 0x0,
4522 HDA_INPUT),
4523 {
4524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4525 /* The multiple "Capture Source" controls confuse alsamixer
4526 * So call somewhat different..
4527 */
4528 .name = "Input Source",
4529 .count = 2,
4530 .info = via_mux_enum_info,
4531 .get = via_mux_enum_get,
4532 .put = via_mux_enum_put,
4533 },
4534 { } /* end */
4535};
4536
4537static struct hda_verb vt1718S_volume_init_verbs[] = {
4538 /*
4539 * Unmute ADC0-1 and set the default input to mic-in
4540 */
4541 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4542 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4543
4544
4545 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4546 * mixer widget
4547 */
4548 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
4549 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4550 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4551 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4552 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4553 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4554
4555 /* Setup default input of Front HP to MW9 */
4556 {0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
4557 /* PW9 PW10 Output enable */
4558 {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
4559 {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
4560 /* PW11 Input enable */
4561 {0x2f, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_IN_EN},
4562 /* Enable Boost Volume backdoor */
4563 {0x1, 0xf88, 0x8},
4564 /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */
4565 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4566 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4567 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4568 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4569 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4570 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4571 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4572 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4573 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4574 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4575 /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */
4576 {0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
4577 {0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
4578 /* Unmute MW4's index 0 */
4579 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4580 { }
4581};
4582
4583
4584static struct hda_verb vt1718S_uniwill_init_verbs[] = {
4585 {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
4586 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
4587 {0x24, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4588 {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4589 {0x26, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4590 {0x27, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4591 {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4592 {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4593 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4594 { }
4595};
4596
4597static struct hda_pcm_stream vt1718S_pcm_analog_playback = {
4598 .substreams = 2,
4599 .channels_min = 2,
4600 .channels_max = 10,
4601 .nid = 0x8, /* NID to query formats and rates */
4602 .ops = {
4603 .open = via_playback_pcm_open,
4604 .prepare = via_playback_multi_pcm_prepare,
4605 .cleanup = via_playback_multi_pcm_cleanup,
4606 .close = via_pcm_open_close,
4607 },
4608};
4609
4610static struct hda_pcm_stream vt1718S_pcm_analog_capture = {
4611 .substreams = 2,
4612 .channels_min = 2,
4613 .channels_max = 2,
4614 .nid = 0x10, /* NID to query formats and rates */
4615 .ops = {
4616 .open = via_pcm_open_close,
4617 .prepare = via_capture_pcm_prepare,
4618 .cleanup = via_capture_pcm_cleanup,
4619 .close = via_pcm_open_close,
4620 },
4621};
4622
4623static struct hda_pcm_stream vt1718S_pcm_digital_playback = {
4624 .substreams = 2,
4625 .channels_min = 2,
4626 .channels_max = 2,
4627 /* NID is set in via_build_pcms */
4628 .ops = {
4629 .open = via_dig_playback_pcm_open,
4630 .close = via_dig_playback_pcm_close,
4631 .prepare = via_dig_playback_pcm_prepare,
4632 .cleanup = via_dig_playback_pcm_cleanup
4633 },
4634};
4635
4636static struct hda_pcm_stream vt1718S_pcm_digital_capture = {
4637 .substreams = 1,
4638 .channels_min = 2,
4639 .channels_max = 2,
4640};
4641
4642/* fill in the dac_nids table from the parsed pin configuration */
4643static int vt1718S_auto_fill_dac_nids(struct via_spec *spec,
4644 const struct auto_pin_cfg *cfg)
4645{
4646 int i;
4647 hda_nid_t nid;
4648
4649 spec->multiout.num_dacs = cfg->line_outs;
4650
4651 spec->multiout.dac_nids = spec->private_dac_nids;
4652
4653 for (i = 0; i < 4; i++) {
4654 nid = cfg->line_out_pins[i];
4655 if (nid) {
4656 /* config dac list */
4657 switch (i) {
4658 case AUTO_SEQ_FRONT:
4659 spec->multiout.dac_nids[i] = 0x8;
4660 break;
4661 case AUTO_SEQ_CENLFE:
4662 spec->multiout.dac_nids[i] = 0xa;
4663 break;
4664 case AUTO_SEQ_SURROUND:
4665 spec->multiout.dac_nids[i] = 0x9;
4666 break;
4667 case AUTO_SEQ_SIDE:
4668 spec->multiout.dac_nids[i] = 0xb;
4669 break;
4670 }
4671 }
4672 }
4673
4674 return 0;
4675}
4676
4677/* add playback controls from the parsed DAC table */
4678static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec,
4679 const struct auto_pin_cfg *cfg)
4680{
4681 char name[32];
4682 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
4683 hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb};
4684 hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27};
4685 hda_nid_t nid, nid_vol, nid_mute = 0;
4686 int i, err;
4687
4688 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
4689 nid = cfg->line_out_pins[i];
4690
4691 if (!nid)
4692 continue;
4693 nid_vol = nid_vols[i];
4694 nid_mute = nid_mutes[i];
4695
4696 if (i == AUTO_SEQ_CENLFE) {
4697 /* Center/LFE */
4698 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
4699 "Center Playback Volume",
4700 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
4701 HDA_OUTPUT));
4702 if (err < 0)
4703 return err;
4704 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
4705 "LFE Playback Volume",
4706 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
4707 HDA_OUTPUT));
4708 if (err < 0)
4709 return err;
4710 err = via_add_control(
4711 spec, VIA_CTL_WIDGET_MUTE,
4712 "Center Playback Switch",
4713 HDA_COMPOSE_AMP_VAL(nid_mute, 1, 0,
4714 HDA_OUTPUT));
4715 if (err < 0)
4716 return err;
4717 err = via_add_control(
4718 spec, VIA_CTL_WIDGET_MUTE,
4719 "LFE Playback Switch",
4720 HDA_COMPOSE_AMP_VAL(nid_mute, 2, 0,
4721 HDA_OUTPUT));
4722 if (err < 0)
4723 return err;
4724 } else if (i == AUTO_SEQ_FRONT) {
4725 /* Front */
4726 sprintf(name, "%s Playback Volume", chname[i]);
4727 err = via_add_control(
4728 spec, VIA_CTL_WIDGET_VOL, name,
4729 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
4730 if (err < 0)
4731 return err;
4732 sprintf(name, "%s Playback Switch", chname[i]);
4733 err = via_add_control(
4734 spec, VIA_CTL_WIDGET_MUTE, name,
4735 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
4736 HDA_OUTPUT));
4737 if (err < 0)
4738 return err;
4739 } else {
4740 sprintf(name, "%s Playback Volume", chname[i]);
4741 err = via_add_control(
4742 spec, VIA_CTL_WIDGET_VOL, name,
4743 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
4744 if (err < 0)
4745 return err;
4746 sprintf(name, "%s Playback Switch", chname[i]);
4747 err = via_add_control(
4748 spec, VIA_CTL_WIDGET_MUTE, name,
4749 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
4750 HDA_OUTPUT));
4751 if (err < 0)
4752 return err;
4753 }
4754 }
4755 return 0;
4756}
4757
4758static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
4759{
4760 int err;
4761
4762 if (!pin)
4763 return 0;
4764
4765 spec->multiout.hp_nid = 0xc; /* AOW4 */
4766 spec->hp_independent_mode_index = 1;
4767
4768 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
4769 "Headphone Playback Volume",
4770 HDA_COMPOSE_AMP_VAL(0xc, 3, 0, HDA_OUTPUT));
4771 if (err < 0)
4772 return err;
4773
4774 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
4775 "Headphone Playback Switch",
4776 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4777 if (err < 0)
4778 return err;
4779
4780 create_hp_imux(spec);
4781 return 0;
4782}
4783
4784/* create playback/capture controls for input pins */
4785static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec,
4786 const struct auto_pin_cfg *cfg)
4787{
4788 static char *labels[] = {
4789 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
4790 };
4791 struct hda_input_mux *imux = &spec->private_imux[0];
4792 int i, err, idx = 0;
4793
4794 /* for internal loopback recording select */
4795 imux->items[imux->num_items].label = "Stereo Mixer";
4796 imux->items[imux->num_items].index = 5;
4797 imux->num_items++;
4798
4799 for (i = 0; i < AUTO_PIN_LAST; i++) {
4800 if (!cfg->input_pins[i])
4801 continue;
4802
4803 switch (cfg->input_pins[i]) {
4804 case 0x2b: /* Mic */
4805 idx = 1;
4806 break;
4807
4808 case 0x2a: /* Line In */
4809 idx = 2;
4810 break;
4811
4812 case 0x29: /* Front Mic */
4813 idx = 3;
4814 break;
4815
4816 case 0x2c: /* CD */
4817 idx = 0;
4818 break;
4819 }
4820 err = via_new_analog_input(spec, labels[i], idx, 0x21);
4821 if (err < 0)
4822 return err;
4823 imux->items[imux->num_items].label = labels[i];
4824 imux->items[imux->num_items].index = idx;
4825 imux->num_items++;
4826 }
4827 return 0;
4828}
4829
4830static int vt1718S_parse_auto_config(struct hda_codec *codec)
4831{
4832 struct via_spec *spec = codec->spec;
4833 int err;
4834
4835 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
4836
4837 if (err < 0)
4838 return err;
4839 err = vt1718S_auto_fill_dac_nids(spec, &spec->autocfg);
4840 if (err < 0)
4841 return err;
4842 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
4843 return 0; /* can't find valid BIOS pin config */
4844
4845 err = vt1718S_auto_create_multi_out_ctls(spec, &spec->autocfg);
4846 if (err < 0)
4847 return err;
4848 err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
4849 if (err < 0)
4850 return err;
4851 err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg);
4852 if (err < 0)
4853 return err;
4854
4855 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4856
4857 fill_dig_outs(codec);
4858
4859 if (spec->autocfg.dig_in_pin && codec->vendor_id == 0x11060428)
4860 spec->dig_in_nid = 0x13;
4861
4862 if (spec->kctls.list)
4863 spec->mixers[spec->num_mixers++] = spec->kctls.list;
4864
4865 spec->input_mux = &spec->private_imux[0];
4866
4867 if (spec->hp_mux)
4868 spec->mixers[spec->num_mixers++] = via_hp_mixer;
4869
4870 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
4871
4872 return 1;
4873}
4874
4875#ifdef CONFIG_SND_HDA_POWER_SAVE
4876static struct hda_amp_list vt1718S_loopbacks[] = {
4877 { 0x21, HDA_INPUT, 1 },
4878 { 0x21, HDA_INPUT, 2 },
4879 { 0x21, HDA_INPUT, 3 },
4880 { 0x21, HDA_INPUT, 4 },
4881 { } /* end */
4882};
4883#endif
4884
4885static int patch_vt1718S(struct hda_codec *codec)
4886{
4887 struct via_spec *spec;
4888 int err;
3239 4889
3240 /* Enable GPIO 0&1 for volume&mute control */ 4890 /* create a codec specific record */
3241 /* Enable GPIO 2 for DMIC-DATA */ 4891 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3242 response = snd_hda_codec_read(codec, codec->afg, 0, 0xF84, 0); 4892 if (spec == NULL)
3243 control = (unsigned char)((response >> 16) & 0x3f); 4893 return -ENOMEM;
3244 snd_hda_codec_write(codec, codec->afg, 0, 0xF82, control); 4894
4895 codec->spec = spec;
4896
4897 /* automatic parse from the BIOS config */
4898 err = vt1718S_parse_auto_config(codec);
4899 if (err < 0) {
4900 via_free(codec);
4901 return err;
4902 } else if (!err) {
4903 printk(KERN_INFO "hda_codec: Cannot set up configuration "
4904 "from BIOS. Using genenic mode...\n");
4905 }
4906
4907 spec->init_verbs[spec->num_iverbs++] = vt1718S_volume_init_verbs;
4908 spec->init_verbs[spec->num_iverbs++] = vt1718S_uniwill_init_verbs;
4909
4910 if (codec->vendor_id == 0x11060441)
4911 spec->stream_name_analog = "VT2020 Analog";
4912 else if (codec->vendor_id == 0x11064441)
4913 spec->stream_name_analog = "VT1828S Analog";
4914 else
4915 spec->stream_name_analog = "VT1718S Analog";
4916 spec->stream_analog_playback = &vt1718S_pcm_analog_playback;
4917 spec->stream_analog_capture = &vt1718S_pcm_analog_capture;
4918
4919 if (codec->vendor_id == 0x11060441)
4920 spec->stream_name_digital = "VT2020 Digital";
4921 else if (codec->vendor_id == 0x11064441)
4922 spec->stream_name_digital = "VT1828S Digital";
4923 else
4924 spec->stream_name_digital = "VT1718S Digital";
4925 spec->stream_digital_playback = &vt1718S_pcm_digital_playback;
4926 if (codec->vendor_id == 0x11060428 || codec->vendor_id == 0x11060441)
4927 spec->stream_digital_capture = &vt1718S_pcm_digital_capture;
4928
4929 if (!spec->adc_nids && spec->input_mux) {
4930 spec->adc_nids = vt1718S_adc_nids;
4931 spec->num_adc_nids = ARRAY_SIZE(vt1718S_adc_nids);
4932 get_mux_nids(codec);
4933 override_mic_boost(codec, 0x2b, 0, 3, 40);
4934 override_mic_boost(codec, 0x29, 0, 3, 40);
4935 spec->mixers[spec->num_mixers] = vt1718S_capture_mixer;
4936 spec->num_mixers++;
4937 }
4938
4939 codec->patch_ops = via_patch_ops;
4940
4941 codec->patch_ops.init = via_auto_init;
4942 codec->patch_ops.unsol_event = via_unsol_event;
4943
4944#ifdef CONFIG_SND_HDA_POWER_SAVE
4945 spec->loopback.amplist = vt1718S_loopbacks;
4946#endif
4947
4948 return 0;
4949}
4950
4951/* Patch for VT1716S */
4952
4953static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
4954 struct snd_ctl_elem_info *uinfo)
4955{
4956 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4957 uinfo->count = 1;
4958 uinfo->value.integer.min = 0;
4959 uinfo->value.integer.max = 1;
4960 return 0;
4961}
4962
4963static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
4964 struct snd_ctl_elem_value *ucontrol)
4965{
4966 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4967 int index = 0;
4968
4969 index = snd_hda_codec_read(codec, 0x26, 0,
4970 AC_VERB_GET_CONNECT_SEL, 0);
4971 if (index != -1)
4972 *ucontrol->value.integer.value = index;
4973
4974 return 0;
4975}
4976
4977static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
4978 struct snd_ctl_elem_value *ucontrol)
4979{
4980 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4981 struct via_spec *spec = codec->spec;
4982 int index = *ucontrol->value.integer.value;
4983
4984 snd_hda_codec_write(codec, 0x26, 0,
4985 AC_VERB_SET_CONNECT_SEL, index);
4986 spec->dmic_enabled = index;
4987 set_jack_power_state(codec);
4988
4989 return 1;
4990}
4991
4992/* capture mixer elements */
4993static struct snd_kcontrol_new vt1716S_capture_mixer[] = {
4994 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
4995 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
4996 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
4997 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
4998 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x1A, 0x0, HDA_INPUT),
4999 HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x1E, 0x0,
5000 HDA_INPUT),
5001 {
5002 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5003 .name = "Input Source",
5004 .count = 1,
5005 .info = via_mux_enum_info,
5006 .get = via_mux_enum_get,
5007 .put = via_mux_enum_put,
5008 },
5009 { } /* end */
5010};
5011
5012static struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
5013 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
5014 {
5015 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5016 .name = "Digital Mic Capture Switch",
5017 .count = 1,
5018 .info = vt1716s_dmic_info,
5019 .get = vt1716s_dmic_get,
5020 .put = vt1716s_dmic_put,
5021 },
5022 {} /* end */
5023};
5024
5025
5026/* mono-out mixer elements */
5027static struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
5028 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
5029 { } /* end */
5030};
5031
5032static struct hda_verb vt1716S_volume_init_verbs[] = {
5033 /*
5034 * Unmute ADC0-1 and set the default input to mic-in
5035 */
5036 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5037 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5038
5039
5040 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5041 * mixer widget
5042 */
5043 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
5044 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5045 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5046 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5047 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5048 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5049
5050 /* MUX Indices: Stereo Mixer = 5 */
5051 {0x17, AC_VERB_SET_CONNECT_SEL, 0x5},
5052
5053 /* Setup default input of PW4 to MW0 */
5054 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
5055
5056 /* Setup default input of SW1 as MW0 */
5057 {0x18, AC_VERB_SET_CONNECT_SEL, 0x1},
5058
5059 /* Setup default input of SW4 as AOW0 */
5060 {0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
5061
5062 /* PW9 PW10 Output enable */
5063 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5064 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5065
5066 /* Unmute SW1, PW12 */
5067 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5068 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5069 /* PW12 Output enable */
5070 {0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5071 /* Enable Boost Volume backdoor */
5072 {0x1, 0xf8a, 0x80},
5073 /* don't bybass mixer */
5074 {0x1, 0xf88, 0xc0},
5075 /* Enable mono output */
5076 {0x1, 0xf90, 0x08},
5077 { }
5078};
5079
5080
5081static struct hda_verb vt1716S_uniwill_init_verbs[] = {
5082 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
5083 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
5084 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5085 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5086 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5087 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE,
5088 AC_USRSP_EN | VIA_MONO_EVENT | VIA_JACK_EVENT},
5089 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5090 {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5091 { }
5092};
5093
5094static struct hda_pcm_stream vt1716S_pcm_analog_playback = {
5095 .substreams = 2,
5096 .channels_min = 2,
5097 .channels_max = 6,
5098 .nid = 0x10, /* NID to query formats and rates */
5099 .ops = {
5100 .open = via_playback_pcm_open,
5101 .prepare = via_playback_multi_pcm_prepare,
5102 .cleanup = via_playback_multi_pcm_cleanup,
5103 .close = via_pcm_open_close,
5104 },
5105};
5106
5107static struct hda_pcm_stream vt1716S_pcm_analog_capture = {
5108 .substreams = 2,
5109 .channels_min = 2,
5110 .channels_max = 2,
5111 .nid = 0x13, /* NID to query formats and rates */
5112 .ops = {
5113 .open = via_pcm_open_close,
5114 .prepare = via_capture_pcm_prepare,
5115 .cleanup = via_capture_pcm_cleanup,
5116 .close = via_pcm_open_close,
5117 },
5118};
5119
5120static struct hda_pcm_stream vt1716S_pcm_digital_playback = {
5121 .substreams = 2,
5122 .channels_min = 2,
5123 .channels_max = 2,
5124 /* NID is set in via_build_pcms */
5125 .ops = {
5126 .open = via_dig_playback_pcm_open,
5127 .close = via_dig_playback_pcm_close,
5128 .prepare = via_dig_playback_pcm_prepare,
5129 .cleanup = via_dig_playback_pcm_cleanup
5130 },
5131};
5132
5133/* fill in the dac_nids table from the parsed pin configuration */
5134static int vt1716S_auto_fill_dac_nids(struct via_spec *spec,
5135 const struct auto_pin_cfg *cfg)
5136{ int i;
5137 hda_nid_t nid;
5138
5139 spec->multiout.num_dacs = cfg->line_outs;
5140
5141 spec->multiout.dac_nids = spec->private_dac_nids;
5142
5143 for (i = 0; i < 3; i++) {
5144 nid = cfg->line_out_pins[i];
5145 if (nid) {
5146 /* config dac list */
5147 switch (i) {
5148 case AUTO_SEQ_FRONT:
5149 spec->multiout.dac_nids[i] = 0x10;
5150 break;
5151 case AUTO_SEQ_CENLFE:
5152 spec->multiout.dac_nids[i] = 0x25;
5153 break;
5154 case AUTO_SEQ_SURROUND:
5155 spec->multiout.dac_nids[i] = 0x11;
5156 break;
5157 }
5158 }
5159 }
5160
5161 return 0;
5162}
5163
5164/* add playback controls from the parsed DAC table */
5165static int vt1716S_auto_create_multi_out_ctls(struct via_spec *spec,
5166 const struct auto_pin_cfg *cfg)
5167{
5168 char name[32];
5169 static const char *chname[3] = { "Front", "Surround", "C/LFE" };
5170 hda_nid_t nid_vols[] = {0x10, 0x11, 0x25};
5171 hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27};
5172 hda_nid_t nid, nid_vol, nid_mute;
5173 int i, err;
5174
5175 for (i = 0; i <= AUTO_SEQ_CENLFE; i++) {
5176 nid = cfg->line_out_pins[i];
5177
5178 if (!nid)
5179 continue;
5180
5181 nid_vol = nid_vols[i];
5182 nid_mute = nid_mutes[i];
5183
5184 if (i == AUTO_SEQ_CENLFE) {
5185 err = via_add_control(
5186 spec, VIA_CTL_WIDGET_VOL,
5187 "Center Playback Volume",
5188 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
5189 if (err < 0)
5190 return err;
5191 err = via_add_control(
5192 spec, VIA_CTL_WIDGET_VOL,
5193 "LFE Playback Volume",
5194 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
5195 if (err < 0)
5196 return err;
5197 err = via_add_control(
5198 spec, VIA_CTL_WIDGET_MUTE,
5199 "Center Playback Switch",
5200 HDA_COMPOSE_AMP_VAL(nid_mute, 1, 0,
5201 HDA_OUTPUT));
5202 if (err < 0)
5203 return err;
5204 err = via_add_control(
5205 spec, VIA_CTL_WIDGET_MUTE,
5206 "LFE Playback Switch",
5207 HDA_COMPOSE_AMP_VAL(nid_mute, 2, 0,
5208 HDA_OUTPUT));
5209 if (err < 0)
5210 return err;
5211 } else if (i == AUTO_SEQ_FRONT) {
5212
5213 err = via_add_control(
5214 spec, VIA_CTL_WIDGET_VOL,
5215 "Master Front Playback Volume",
5216 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
5217 if (err < 0)
5218 return err;
5219 err = via_add_control(
5220 spec, VIA_CTL_WIDGET_MUTE,
5221 "Master Front Playback Switch",
5222 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
5223 if (err < 0)
5224 return err;
5225
5226 sprintf(name, "%s Playback Volume", chname[i]);
5227 err = via_add_control(
5228 spec, VIA_CTL_WIDGET_VOL, name,
5229 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
5230 if (err < 0)
5231 return err;
5232 sprintf(name, "%s Playback Switch", chname[i]);
5233 err = via_add_control(
5234 spec, VIA_CTL_WIDGET_MUTE, name,
5235 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
5236 HDA_OUTPUT));
5237 if (err < 0)
5238 return err;
5239 } else {
5240 sprintf(name, "%s Playback Volume", chname[i]);
5241 err = via_add_control(
5242 spec, VIA_CTL_WIDGET_VOL, name,
5243 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
5244 if (err < 0)
5245 return err;
5246 sprintf(name, "%s Playback Switch", chname[i]);
5247 err = via_add_control(
5248 spec, VIA_CTL_WIDGET_MUTE, name,
5249 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
5250 HDA_OUTPUT));
5251 if (err < 0)
5252 return err;
5253 }
5254 }
5255 return 0;
5256}
5257
5258static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5259{
5260 int err;
5261
5262 if (!pin)
5263 return 0;
5264
5265 spec->multiout.hp_nid = 0x25; /* AOW3 */
5266 spec->hp_independent_mode_index = 1;
5267
5268 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5269 "Headphone Playback Volume",
5270 HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
5271 if (err < 0)
5272 return err;
5273
5274 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
5275 "Headphone Playback Switch",
5276 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5277 if (err < 0)
5278 return err;
5279
5280 create_hp_imux(spec);
5281 return 0;
5282}
5283
5284/* create playback/capture controls for input pins */
5285static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec,
5286 const struct auto_pin_cfg *cfg)
5287{
5288 static char *labels[] = {
5289 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
5290 };
5291 struct hda_input_mux *imux = &spec->private_imux[0];
5292 int i, err, idx = 0;
5293
5294 /* for internal loopback recording select */
5295 imux->items[imux->num_items].label = "Stereo Mixer";
5296 imux->items[imux->num_items].index = 5;
5297 imux->num_items++;
5298
5299 for (i = 0; i < AUTO_PIN_LAST; i++) {
5300 if (!cfg->input_pins[i])
5301 continue;
5302
5303 switch (cfg->input_pins[i]) {
5304 case 0x1a: /* Mic */
5305 idx = 2;
5306 break;
5307
5308 case 0x1b: /* Line In */
5309 idx = 3;
5310 break;
5311
5312 case 0x1e: /* Front Mic */
5313 idx = 4;
5314 break;
5315
5316 case 0x1f: /* CD */
5317 idx = 1;
5318 break;
5319 }
5320 err = via_new_analog_input(spec, labels[i], idx, 0x16);
5321 if (err < 0)
5322 return err;
5323 imux->items[imux->num_items].label = labels[i];
5324 imux->items[imux->num_items].index = idx-1;
5325 imux->num_items++;
5326 }
5327 return 0;
5328}
5329
5330static int vt1716S_parse_auto_config(struct hda_codec *codec)
5331{
5332 struct via_spec *spec = codec->spec;
5333 int err;
5334
5335 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
5336 if (err < 0)
5337 return err;
5338 err = vt1716S_auto_fill_dac_nids(spec, &spec->autocfg);
5339 if (err < 0)
5340 return err;
5341 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
5342 return 0; /* can't find valid BIOS pin config */
5343
5344 err = vt1716S_auto_create_multi_out_ctls(spec, &spec->autocfg);
5345 if (err < 0)
5346 return err;
5347 err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
5348 if (err < 0)
5349 return err;
5350 err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg);
5351 if (err < 0)
5352 return err;
5353
5354 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5355
5356 fill_dig_outs(codec);
5357
5358 if (spec->kctls.list)
5359 spec->mixers[spec->num_mixers++] = spec->kctls.list;
5360
5361 spec->input_mux = &spec->private_imux[0];
5362
5363 if (spec->hp_mux)
5364 spec->mixers[spec->num_mixers++] = via_hp_mixer;
5365
5366 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
5367
5368 return 1;
5369}
5370
5371#ifdef CONFIG_SND_HDA_POWER_SAVE
5372static struct hda_amp_list vt1716S_loopbacks[] = {
5373 { 0x16, HDA_INPUT, 1 },
5374 { 0x16, HDA_INPUT, 2 },
5375 { 0x16, HDA_INPUT, 3 },
5376 { 0x16, HDA_INPUT, 4 },
5377 { } /* end */
5378};
5379#endif
5380
5381static int patch_vt1716S(struct hda_codec *codec)
5382{
5383 struct via_spec *spec;
5384 int err;
5385
5386 /* create a codec specific record */
5387 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5388 if (spec == NULL)
5389 return -ENOMEM;
5390
5391 codec->spec = spec;
5392
5393 /* automatic parse from the BIOS config */
5394 err = vt1716S_parse_auto_config(codec);
5395 if (err < 0) {
5396 via_free(codec);
5397 return err;
5398 } else if (!err) {
5399 printk(KERN_INFO "hda_codec: Cannot set up configuration "
5400 "from BIOS. Using genenic mode...\n");
5401 }
5402
5403 spec->init_verbs[spec->num_iverbs++] = vt1716S_volume_init_verbs;
5404 spec->init_verbs[spec->num_iverbs++] = vt1716S_uniwill_init_verbs;
5405
5406 spec->stream_name_analog = "VT1716S Analog";
5407 spec->stream_analog_playback = &vt1716S_pcm_analog_playback;
5408 spec->stream_analog_capture = &vt1716S_pcm_analog_capture;
5409
5410 spec->stream_name_digital = "VT1716S Digital";
5411 spec->stream_digital_playback = &vt1716S_pcm_digital_playback;
5412
5413 if (!spec->adc_nids && spec->input_mux) {
5414 spec->adc_nids = vt1716S_adc_nids;
5415 spec->num_adc_nids = ARRAY_SIZE(vt1716S_adc_nids);
5416 get_mux_nids(codec);
5417 override_mic_boost(codec, 0x1a, 0, 3, 40);
5418 override_mic_boost(codec, 0x1e, 0, 3, 40);
5419 spec->mixers[spec->num_mixers] = vt1716S_capture_mixer;
5420 spec->num_mixers++;
5421 }
5422
5423 spec->mixers[spec->num_mixers] = vt1716s_dmic_mixer;
5424 spec->num_mixers++;
5425
5426 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
5427
5428 codec->patch_ops = via_patch_ops;
5429
5430 codec->patch_ops.init = via_auto_init;
5431 codec->patch_ops.unsol_event = via_unsol_event;
5432
5433#ifdef CONFIG_SND_HDA_POWER_SAVE
5434 spec->loopback.amplist = vt1716S_loopbacks;
5435#endif
5436
5437 return 0;
5438}
5439
5440/* for vt2002P */
5441
5442/* capture mixer elements */
5443static struct snd_kcontrol_new vt2002P_capture_mixer[] = {
5444 HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
5445 HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
5446 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
5447 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
5448 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
5449 HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x29, 0x0,
5450 HDA_INPUT),
5451 {
5452 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5453 /* The multiple "Capture Source" controls confuse alsamixer
5454 * So call somewhat different..
5455 */
5456 /* .name = "Capture Source", */
5457 .name = "Input Source",
5458 .count = 2,
5459 .info = via_mux_enum_info,
5460 .get = via_mux_enum_get,
5461 .put = via_mux_enum_put,
5462 },
5463 { } /* end */
5464};
5465
5466static struct hda_verb vt2002P_volume_init_verbs[] = {
5467 /*
5468 * Unmute ADC0-1 and set the default input to mic-in
5469 */
5470 {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5471 {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5472
5473
5474 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5475 * mixer widget
5476 */
5477 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
5478 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5479 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5480 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5481 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5482 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5483
5484 /* MUX Indices: Mic = 0 */
5485 {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
5486 {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
5487
5488 /* PW9 Output enable */
5489 {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
5490
5491 /* Enable Boost Volume backdoor */
5492 {0x1, 0xfb9, 0x24},
5493
5494 /* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
5495 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5496 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5497 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5498 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5499 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5500 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5501 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5502 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5503
5504 /* set MUX0/1/4/8 = 0 (AOW0) */
5505 {0x34, AC_VERB_SET_CONNECT_SEL, 0},
5506 {0x35, AC_VERB_SET_CONNECT_SEL, 0},
5507 {0x37, AC_VERB_SET_CONNECT_SEL, 0},
5508 {0x3b, AC_VERB_SET_CONNECT_SEL, 0},
5509
5510 /* set PW0 index=0 (MW0) */
5511 {0x24, AC_VERB_SET_CONNECT_SEL, 0},
5512
5513 /* Enable AOW0 to MW9 */
5514 {0x1, 0xfb8, 0x88},
5515 { }
5516};
5517
5518
5519static struct hda_verb vt2002P_uniwill_init_verbs[] = {
5520 {0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
5521 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5522 {0x26, AC_VERB_SET_UNSOLICITED_ENABLE,
5523 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5524 {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5525 {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5526 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5527 { }
5528};
5529
5530static struct hda_pcm_stream vt2002P_pcm_analog_playback = {
5531 .substreams = 2,
5532 .channels_min = 2,
5533 .channels_max = 2,
5534 .nid = 0x8, /* NID to query formats and rates */
5535 .ops = {
5536 .open = via_playback_pcm_open,
5537 .prepare = via_playback_multi_pcm_prepare,
5538 .cleanup = via_playback_multi_pcm_cleanup,
5539 .close = via_pcm_open_close,
5540 },
5541};
5542
5543static struct hda_pcm_stream vt2002P_pcm_analog_capture = {
5544 .substreams = 2,
5545 .channels_min = 2,
5546 .channels_max = 2,
5547 .nid = 0x10, /* NID to query formats and rates */
5548 .ops = {
5549 .open = via_pcm_open_close,
5550 .prepare = via_capture_pcm_prepare,
5551 .cleanup = via_capture_pcm_cleanup,
5552 .close = via_pcm_open_close,
5553 },
5554};
5555
5556static struct hda_pcm_stream vt2002P_pcm_digital_playback = {
5557 .substreams = 1,
5558 .channels_min = 2,
5559 .channels_max = 2,
5560 /* NID is set in via_build_pcms */
5561 .ops = {
5562 .open = via_dig_playback_pcm_open,
5563 .close = via_dig_playback_pcm_close,
5564 .prepare = via_dig_playback_pcm_prepare,
5565 .cleanup = via_dig_playback_pcm_cleanup
5566 },
5567};
5568
5569/* fill in the dac_nids table from the parsed pin configuration */
5570static int vt2002P_auto_fill_dac_nids(struct via_spec *spec,
5571 const struct auto_pin_cfg *cfg)
5572{
5573 spec->multiout.num_dacs = 1;
5574 spec->multiout.dac_nids = spec->private_dac_nids;
5575 if (cfg->line_out_pins[0])
5576 spec->multiout.dac_nids[0] = 0x8;
5577 return 0;
5578}
5579
5580/* add playback controls from the parsed DAC table */
5581static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
5582 const struct auto_pin_cfg *cfg)
5583{
5584 int err;
5585
5586 if (!cfg->line_out_pins[0])
5587 return -1;
5588
5589
5590 /* Line-Out: PortE */
5591 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5592 "Master Front Playback Volume",
5593 HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT));
5594 if (err < 0)
5595 return err;
5596 err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
5597 "Master Front Playback Switch",
5598 HDA_COMPOSE_AMP_VAL(0x26, 3, 0, HDA_OUTPUT));
5599 if (err < 0)
5600 return err;
5601
5602 return 0;
5603}
5604
5605static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5606{
5607 int err;
5608
5609 if (!pin)
5610 return 0;
5611
5612 spec->multiout.hp_nid = 0x9;
5613 spec->hp_independent_mode_index = 1;
5614
5615 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5616 "Headphone Playback Volume",
5617 HDA_COMPOSE_AMP_VAL(
5618 spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
5619 if (err < 0)
5620 return err;
5621
5622 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
5623 "Headphone Playback Switch",
5624 HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
5625 if (err < 0)
5626 return err;
5627
5628 create_hp_imux(spec);
5629 return 0;
5630}
5631
5632/* create playback/capture controls for input pins */
5633static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec,
5634 const struct auto_pin_cfg *cfg)
5635{
5636 static char *labels[] = {
5637 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
5638 };
5639 struct hda_input_mux *imux = &spec->private_imux[0];
5640 int i, err, idx = 0;
5641
5642 for (i = 0; i < AUTO_PIN_LAST; i++) {
5643 if (!cfg->input_pins[i])
5644 continue;
5645
5646 switch (cfg->input_pins[i]) {
5647 case 0x2b: /* Mic */
5648 idx = 0;
5649 break;
5650
5651 case 0x2a: /* Line In */
5652 idx = 1;
5653 break;
5654
5655 case 0x29: /* Front Mic */
5656 idx = 2;
5657 break;
5658 }
5659 err = via_new_analog_input(spec, labels[i], idx, 0x21);
5660 if (err < 0)
5661 return err;
5662 imux->items[imux->num_items].label = labels[i];
5663 imux->items[imux->num_items].index = idx;
5664 imux->num_items++;
5665 }
5666
5667 /* build volume/mute control of loopback */
5668 err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21);
5669 if (err < 0)
5670 return err;
5671
5672 /* for internal loopback recording select */
5673 imux->items[imux->num_items].label = "Stereo Mixer";
5674 imux->items[imux->num_items].index = 3;
5675 imux->num_items++;
5676
5677 /* for digital mic select */
5678 imux->items[imux->num_items].label = "Digital Mic";
5679 imux->items[imux->num_items].index = 4;
5680 imux->num_items++;
5681
5682 return 0;
5683}
5684
5685static int vt2002P_parse_auto_config(struct hda_codec *codec)
5686{
5687 struct via_spec *spec = codec->spec;
5688 int err;
5689
5690
5691 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
5692 if (err < 0)
5693 return err;
5694
5695 err = vt2002P_auto_fill_dac_nids(spec, &spec->autocfg);
5696 if (err < 0)
5697 return err;
5698
5699 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
5700 return 0; /* can't find valid BIOS pin config */
5701
5702 err = vt2002P_auto_create_multi_out_ctls(spec, &spec->autocfg);
5703 if (err < 0)
5704 return err;
5705 err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
5706 if (err < 0)
5707 return err;
5708 err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg);
5709 if (err < 0)
5710 return err;
5711
5712 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5713
5714 fill_dig_outs(codec);
5715
5716 if (spec->kctls.list)
5717 spec->mixers[spec->num_mixers++] = spec->kctls.list;
5718
5719 spec->input_mux = &spec->private_imux[0];
5720
5721 if (spec->hp_mux)
5722 spec->mixers[spec->num_mixers++] = via_hp_mixer;
5723
5724 return 1;
5725}
5726
5727#ifdef CONFIG_SND_HDA_POWER_SAVE
5728static struct hda_amp_list vt2002P_loopbacks[] = {
5729 { 0x21, HDA_INPUT, 0 },
5730 { 0x21, HDA_INPUT, 1 },
5731 { 0x21, HDA_INPUT, 2 },
5732 { } /* end */
5733};
5734#endif
5735
5736
5737/* patch for vt2002P */
5738static int patch_vt2002P(struct hda_codec *codec)
5739{
5740 struct via_spec *spec;
5741 int err;
5742
5743 /* create a codec specific record */
5744 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5745 if (spec == NULL)
5746 return -ENOMEM;
5747
5748 codec->spec = spec;
5749
5750 /* automatic parse from the BIOS config */
5751 err = vt2002P_parse_auto_config(codec);
5752 if (err < 0) {
5753 via_free(codec);
5754 return err;
5755 } else if (!err) {
5756 printk(KERN_INFO "hda_codec: Cannot set up configuration "
5757 "from BIOS. Using genenic mode...\n");
5758 }
5759
5760 spec->init_verbs[spec->num_iverbs++] = vt2002P_volume_init_verbs;
5761 spec->init_verbs[spec->num_iverbs++] = vt2002P_uniwill_init_verbs;
5762
5763 spec->stream_name_analog = "VT2002P Analog";
5764 spec->stream_analog_playback = &vt2002P_pcm_analog_playback;
5765 spec->stream_analog_capture = &vt2002P_pcm_analog_capture;
5766
5767 spec->stream_name_digital = "VT2002P Digital";
5768 spec->stream_digital_playback = &vt2002P_pcm_digital_playback;
5769
5770 if (!spec->adc_nids && spec->input_mux) {
5771 spec->adc_nids = vt2002P_adc_nids;
5772 spec->num_adc_nids = ARRAY_SIZE(vt2002P_adc_nids);
5773 get_mux_nids(codec);
5774 override_mic_boost(codec, 0x2b, 0, 3, 40);
5775 override_mic_boost(codec, 0x29, 0, 3, 40);
5776 spec->mixers[spec->num_mixers] = vt2002P_capture_mixer;
5777 spec->num_mixers++;
5778 }
5779
5780 codec->patch_ops = via_patch_ops;
5781
5782 codec->patch_ops.init = via_auto_init;
5783 codec->patch_ops.unsol_event = via_unsol_event;
5784
5785#ifdef CONFIG_SND_HDA_POWER_SAVE
5786 spec->loopback.amplist = vt2002P_loopbacks;
5787#endif
5788
5789 return 0;
5790}
5791
5792/* for vt1812 */
5793
5794/* capture mixer elements */
5795static struct snd_kcontrol_new vt1812_capture_mixer[] = {
5796 HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
5797 HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
5798 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
5799 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
5800 HDA_CODEC_MUTE("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
5801 HDA_CODEC_MUTE("Front Mic Boost Capture Volume", 0x29, 0x0,
5802 HDA_INPUT),
5803 {
5804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5805 /* The multiple "Capture Source" controls confuse alsamixer
5806 * So call somewhat different..
5807 */
5808 .name = "Input Source",
5809 .count = 2,
5810 .info = via_mux_enum_info,
5811 .get = via_mux_enum_get,
5812 .put = via_mux_enum_put,
5813 },
5814 { } /* end */
5815};
5816
5817static struct hda_verb vt1812_volume_init_verbs[] = {
5818 /*
5819 * Unmute ADC0-1 and set the default input to mic-in
5820 */
5821 {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5822 {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5823
5824
5825 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5826 * mixer widget
5827 */
5828 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
5829 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5830 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5831 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5832 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5833 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5834
5835 /* MUX Indices: Mic = 0 */
5836 {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
5837 {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
5838
5839 /* PW9 Output enable */
5840 {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
5841
5842 /* Enable Boost Volume backdoor */
5843 {0x1, 0xfb9, 0x24},
5844
5845 /* MW0/1/4/13/15: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
5846 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5847 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5848 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5849 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5850 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5851 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5852 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5853 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5854 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5855 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5856
5857 /* set MUX0/1/4/13/15 = 0 (AOW0) */
5858 {0x34, AC_VERB_SET_CONNECT_SEL, 0},
5859 {0x35, AC_VERB_SET_CONNECT_SEL, 0},
5860 {0x38, AC_VERB_SET_CONNECT_SEL, 0},
5861 {0x3c, AC_VERB_SET_CONNECT_SEL, 0},
5862 {0x3d, AC_VERB_SET_CONNECT_SEL, 0},
5863
5864 /* Enable AOW0 to MW9 */
5865 {0x1, 0xfb8, 0xa8},
5866 { }
5867};
5868
5869
5870static struct hda_verb vt1812_uniwill_init_verbs[] = {
5871 {0x33, AC_VERB_SET_UNSOLICITED_ENABLE,
5872 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5873 {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT },
5874 {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
5875 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5876 {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5877 {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5878 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5879 { }
5880};
5881
5882static struct hda_pcm_stream vt1812_pcm_analog_playback = {
5883 .substreams = 2,
5884 .channels_min = 2,
5885 .channels_max = 2,
5886 .nid = 0x8, /* NID to query formats and rates */
5887 .ops = {
5888 .open = via_playback_pcm_open,
5889 .prepare = via_playback_multi_pcm_prepare,
5890 .cleanup = via_playback_multi_pcm_cleanup,
5891 .close = via_pcm_open_close,
5892 },
5893};
5894
5895static struct hda_pcm_stream vt1812_pcm_analog_capture = {
5896 .substreams = 2,
5897 .channels_min = 2,
5898 .channels_max = 2,
5899 .nid = 0x10, /* NID to query formats and rates */
5900 .ops = {
5901 .open = via_pcm_open_close,
5902 .prepare = via_capture_pcm_prepare,
5903 .cleanup = via_capture_pcm_cleanup,
5904 .close = via_pcm_open_close,
5905 },
5906};
5907
5908static struct hda_pcm_stream vt1812_pcm_digital_playback = {
5909 .substreams = 1,
5910 .channels_min = 2,
5911 .channels_max = 2,
5912 /* NID is set in via_build_pcms */
5913 .ops = {
5914 .open = via_dig_playback_pcm_open,
5915 .close = via_dig_playback_pcm_close,
5916 .prepare = via_dig_playback_pcm_prepare,
5917 .cleanup = via_dig_playback_pcm_cleanup
5918 },
5919};
5920/* fill in the dac_nids table from the parsed pin configuration */
5921static int vt1812_auto_fill_dac_nids(struct via_spec *spec,
5922 const struct auto_pin_cfg *cfg)
5923{
5924 spec->multiout.num_dacs = 1;
5925 spec->multiout.dac_nids = spec->private_dac_nids;
5926 if (cfg->line_out_pins[0])
5927 spec->multiout.dac_nids[0] = 0x8;
5928 return 0;
5929}
5930
5931
5932/* add playback controls from the parsed DAC table */
5933static int vt1812_auto_create_multi_out_ctls(struct via_spec *spec,
5934 const struct auto_pin_cfg *cfg)
5935{
5936 int err;
5937
5938 if (!cfg->line_out_pins[0])
5939 return -1;
5940
5941 /* Line-Out: PortE */
5942 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5943 "Master Front Playback Volume",
5944 HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT));
5945 if (err < 0)
5946 return err;
5947 err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
5948 "Master Front Playback Switch",
5949 HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT));
5950 if (err < 0)
5951 return err;
5952
5953 return 0;
5954}
5955
5956static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5957{
5958 int err;
5959
5960 if (!pin)
5961 return 0;
5962
5963 spec->multiout.hp_nid = 0x9;
5964 spec->hp_independent_mode_index = 1;
5965
5966
5967 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5968 "Headphone Playback Volume",
5969 HDA_COMPOSE_AMP_VAL(
5970 spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
5971 if (err < 0)
5972 return err;
5973
5974 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
5975 "Headphone Playback Switch",
5976 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5977 if (err < 0)
5978 return err;
5979
5980 create_hp_imux(spec);
5981 return 0;
5982}
5983
5984/* create playback/capture controls for input pins */
5985static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec,
5986 const struct auto_pin_cfg *cfg)
5987{
5988 static char *labels[] = {
5989 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
5990 };
5991 struct hda_input_mux *imux = &spec->private_imux[0];
5992 int i, err, idx = 0;
5993
5994 for (i = 0; i < AUTO_PIN_LAST; i++) {
5995 if (!cfg->input_pins[i])
5996 continue;
5997
5998 switch (cfg->input_pins[i]) {
5999 case 0x2b: /* Mic */
6000 idx = 0;
6001 break;
6002
6003 case 0x2a: /* Line In */
6004 idx = 1;
6005 break;
6006
6007 case 0x29: /* Front Mic */
6008 idx = 2;
6009 break;
6010 }
6011 err = via_new_analog_input(spec, labels[i], idx, 0x21);
6012 if (err < 0)
6013 return err;
6014 imux->items[imux->num_items].label = labels[i];
6015 imux->items[imux->num_items].index = idx;
6016 imux->num_items++;
6017 }
6018 /* build volume/mute control of loopback */
6019 err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21);
6020 if (err < 0)
6021 return err;
6022
6023 /* for internal loopback recording select */
6024 imux->items[imux->num_items].label = "Stereo Mixer";
6025 imux->items[imux->num_items].index = 5;
6026 imux->num_items++;
6027
6028 /* for digital mic select */
6029 imux->items[imux->num_items].label = "Digital Mic";
6030 imux->items[imux->num_items].index = 6;
6031 imux->num_items++;
6032
6033 return 0;
6034}
6035
6036static int vt1812_parse_auto_config(struct hda_codec *codec)
6037{
6038 struct via_spec *spec = codec->spec;
6039 int err;
6040
6041
6042 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
6043 if (err < 0)
6044 return err;
6045 fill_dig_outs(codec);
6046 err = vt1812_auto_fill_dac_nids(spec, &spec->autocfg);
6047 if (err < 0)
6048 return err;
6049
6050 if (!spec->autocfg.line_outs && !spec->autocfg.hp_outs)
6051 return 0; /* can't find valid BIOS pin config */
6052
6053 err = vt1812_auto_create_multi_out_ctls(spec, &spec->autocfg);
6054 if (err < 0)
6055 return err;
6056 err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
6057 if (err < 0)
6058 return err;
6059 err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg);
6060 if (err < 0)
6061 return err;
6062
6063 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
6064
6065 fill_dig_outs(codec);
6066
6067 if (spec->kctls.list)
6068 spec->mixers[spec->num_mixers++] = spec->kctls.list;
6069
6070 spec->input_mux = &spec->private_imux[0];
6071
6072 if (spec->hp_mux)
6073 spec->mixers[spec->num_mixers++] = via_hp_mixer;
6074
6075 return 1;
6076}
6077
6078#ifdef CONFIG_SND_HDA_POWER_SAVE
6079static struct hda_amp_list vt1812_loopbacks[] = {
6080 { 0x21, HDA_INPUT, 0 },
6081 { 0x21, HDA_INPUT, 1 },
6082 { 0x21, HDA_INPUT, 2 },
6083 { } /* end */
6084};
6085#endif
6086
6087
6088/* patch for vt1812 */
6089static int patch_vt1812(struct hda_codec *codec)
6090{
6091 struct via_spec *spec;
6092 int err;
6093
6094 /* create a codec specific record */
6095 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6096 if (spec == NULL)
6097 return -ENOMEM;
6098
6099 codec->spec = spec;
6100
6101 /* automatic parse from the BIOS config */
6102 err = vt1812_parse_auto_config(codec);
6103 if (err < 0) {
6104 via_free(codec);
6105 return err;
6106 } else if (!err) {
6107 printk(KERN_INFO "hda_codec: Cannot set up configuration "
6108 "from BIOS. Using genenic mode...\n");
6109 }
6110
6111
6112 spec->init_verbs[spec->num_iverbs++] = vt1812_volume_init_verbs;
6113 spec->init_verbs[spec->num_iverbs++] = vt1812_uniwill_init_verbs;
6114
6115 spec->stream_name_analog = "VT1812 Analog";
6116 spec->stream_analog_playback = &vt1812_pcm_analog_playback;
6117 spec->stream_analog_capture = &vt1812_pcm_analog_capture;
6118
6119 spec->stream_name_digital = "VT1812 Digital";
6120 spec->stream_digital_playback = &vt1812_pcm_digital_playback;
6121
6122
6123 if (!spec->adc_nids && spec->input_mux) {
6124 spec->adc_nids = vt1812_adc_nids;
6125 spec->num_adc_nids = ARRAY_SIZE(vt1812_adc_nids);
6126 get_mux_nids(codec);
6127 override_mic_boost(codec, 0x2b, 0, 3, 40);
6128 override_mic_boost(codec, 0x29, 0, 3, 40);
6129 spec->mixers[spec->num_mixers] = vt1812_capture_mixer;
6130 spec->num_mixers++;
6131 }
6132
6133 codec->patch_ops = via_patch_ops;
6134
6135 codec->patch_ops.init = via_auto_init;
6136 codec->patch_ops.unsol_event = via_unsol_event;
6137
6138#ifdef CONFIG_SND_HDA_POWER_SAVE
6139 spec->loopback.amplist = vt1812_loopbacks;
6140#endif
3245 6141
3246 return 0; 6142 return 0;
3247} 6143}
@@ -3318,6 +6214,23 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
3318 .patch = patch_vt1702}, 6214 .patch = patch_vt1702},
3319 { .id = 0x11067398, .name = "VT1702", 6215 { .id = 0x11067398, .name = "VT1702",
3320 .patch = patch_vt1702}, 6216 .patch = patch_vt1702},
6217 { .id = 0x11060428, .name = "VT1718S",
6218 .patch = patch_vt1718S},
6219 { .id = 0x11064428, .name = "VT1718S",
6220 .patch = patch_vt1718S},
6221 { .id = 0x11060441, .name = "VT2020",
6222 .patch = patch_vt1718S},
6223 { .id = 0x11064441, .name = "VT1828S",
6224 .patch = patch_vt1718S},
6225 { .id = 0x11060433, .name = "VT1716S",
6226 .patch = patch_vt1716S},
6227 { .id = 0x1106a721, .name = "VT1716S",
6228 .patch = patch_vt1716S},
6229 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
6230 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
6231 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
6232 { .id = 0x11060440, .name = "VT1818S",
6233 .patch = patch_vt1708S},
3321 {} /* terminator */ 6234 {} /* terminator */
3322}; 6235};
3323 6236
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 536eae2ccf94..f7ce33f00ea5 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
5 5
6snd-ice17xx-ak4xxx-objs := ak4xxx.o 6snd-ice17xx-ak4xxx-objs := ak4xxx.o
7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o 7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o 8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o
9 9
10# Toplevel Module Dependency 10# Toplevel Module Dependency
11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o 11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index d74033a2cfbe..c7cff6f8168a 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)
298 inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ 298 inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
299} 299}
300 300
301static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice)
302{
303 return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION);
304}
305
306static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice)
307{
308 return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK);
309}
310
301static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) 311static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
302{ 312{
303 snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); 313 snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data);
@@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
2557 mutex_init(&ice->i2c_mutex); 2567 mutex_init(&ice->i2c_mutex);
2558 mutex_init(&ice->open_mutex); 2568 mutex_init(&ice->open_mutex);
2559 ice->gpio.set_mask = snd_ice1712_set_gpio_mask; 2569 ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
2570 ice->gpio.get_mask = snd_ice1712_get_gpio_mask;
2560 ice->gpio.set_dir = snd_ice1712_set_gpio_dir; 2571 ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
2572 ice->gpio.get_dir = snd_ice1712_get_gpio_dir;
2561 ice->gpio.set_data = snd_ice1712_set_gpio_data; 2573 ice->gpio.set_data = snd_ice1712_set_gpio_data;
2562 ice->gpio.get_data = snd_ice1712_get_gpio_data; 2574 ice->gpio.get_data = snd_ice1712_get_gpio_data;
2563 2575
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index d063149e7047..0da778a69ef8 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -359,7 +359,9 @@ struct snd_ice1712 {
359 unsigned int saved[2]; /* for ewx_i2c */ 359 unsigned int saved[2]; /* for ewx_i2c */
360 /* operators */ 360 /* operators */
361 void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); 361 void (*set_mask)(struct snd_ice1712 *ice, unsigned int data);
362 unsigned int (*get_mask)(struct snd_ice1712 *ice);
362 void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); 363 void (*set_dir)(struct snd_ice1712 *ice, unsigned int data);
364 unsigned int (*get_dir)(struct snd_ice1712 *ice);
363 void (*set_data)(struct snd_ice1712 *ice, unsigned int data); 365 void (*set_data)(struct snd_ice1712 *ice, unsigned int data);
364 unsigned int (*get_data)(struct snd_ice1712 *ice); 366 unsigned int (*get_data)(struct snd_ice1712 *ice);
365 /* misc operators - move to another place? */ 367 /* misc operators - move to another place? */
@@ -377,8 +379,11 @@ struct snd_ice1712 {
377 unsigned int (*get_rate)(struct snd_ice1712 *ice); 379 unsigned int (*get_rate)(struct snd_ice1712 *ice);
378 void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); 380 void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
379 unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); 381 unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
380 void (*set_spdif_clock)(struct snd_ice1712 *ice); 382 int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
381 383 int (*get_spdif_master_type)(struct snd_ice1712 *ice);
384 char **ext_clock_names;
385 int ext_clock_count;
386 void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
382#ifdef CONFIG_PM 387#ifdef CONFIG_PM
383 int (*pm_suspend)(struct snd_ice1712 *); 388 int (*pm_suspend)(struct snd_ice1712 *);
384 int (*pm_resume)(struct snd_ice1712 *); 389 int (*pm_resume)(struct snd_ice1712 *);
@@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in
399 ice->gpio.set_dir(ice, bits); 404 ice->gpio.set_dir(ice, bits);
400} 405}
401 406
407static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice)
408{
409 return ice->gpio.get_dir(ice);
410}
411
402static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) 412static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits)
403{ 413{
404 ice->gpio.set_mask(ice, bits); 414 ice->gpio.set_mask(ice, bits);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 10fc92c05574..ae29073eea93 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -53,6 +53,7 @@
53#include "phase.h" 53#include "phase.h"
54#include "wtm.h" 54#include "wtm.h"
55#include "se.h" 55#include "se.h"
56#include "quartet.h"
56 57
57MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 58MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
58MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); 59MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -70,6 +71,7 @@ MODULE_SUPPORTED_DEVICE("{"
70 PHASE_DEVICE_DESC 71 PHASE_DEVICE_DESC
71 WTM_DEVICE_DESC 72 WTM_DEVICE_DESC
72 SE_DEVICE_DESC 73 SE_DEVICE_DESC
74 QTET_DEVICE_DESC
73 "{VIA,VT1720}," 75 "{VIA,VT1720},"
74 "{VIA,VT1724}," 76 "{VIA,VT1724},"
75 "{ICEnsemble,Generic ICE1724}," 77 "{ICEnsemble,Generic ICE1724},"
@@ -104,6 +106,8 @@ static int PRO_RATE_LOCKED;
104static int PRO_RATE_RESET = 1; 106static int PRO_RATE_RESET = 1;
105static unsigned int PRO_RATE_DEFAULT = 44100; 107static unsigned int PRO_RATE_DEFAULT = 44100;
106 108
109static char *ext_clock_names[1] = { "IEC958 In" };
110
107/* 111/*
108 * Basic I/O 112 * Basic I/O
109 */ 113 */
@@ -118,9 +122,12 @@ static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
118 return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; 122 return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
119} 123}
120 124
125/*
126 * locking rate makes sense only for internal clock mode
127 */
121static inline int is_pro_rate_locked(struct snd_ice1712 *ice) 128static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
122{ 129{
123 return ice->is_spdif_master(ice) || PRO_RATE_LOCKED; 130 return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED;
124} 131}
125 132
126/* 133/*
@@ -196,6 +203,12 @@ static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)
196 inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ 203 inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */
197} 204}
198 205
206/* get gpio direction 0 = read, 1 = write */
207static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice)
208{
209 return inl(ICEREG1724(ice, GPIO_DIRECTION));
210}
211
199/* set the gpio mask (0 = writable) */ 212/* set the gpio mask (0 = writable) */
200static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) 213static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
201{ 214{
@@ -205,6 +218,17 @@ static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
205 inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ 218 inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */
206} 219}
207 220
221static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice)
222{
223 unsigned int mask;
224 if (!ice->vt1720)
225 mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22));
226 else
227 mask = 0;
228 mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK));
229 return mask;
230}
231
208static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) 232static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data)
209{ 233{
210 outw(data, ICEREG1724(ice, GPIO_DATA)); 234 outw(data, ICEREG1724(ice, GPIO_DATA));
@@ -651,16 +675,22 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
651 return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; 675 return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY;
652 } 676 }
653 if (!force && is_pro_rate_locked(ice)) { 677 if (!force && is_pro_rate_locked(ice)) {
678 /* comparing required and current rate - makes sense for
679 * internal clock only */
654 spin_unlock_irqrestore(&ice->reg_lock, flags); 680 spin_unlock_irqrestore(&ice->reg_lock, flags);
655 return (rate == ice->cur_rate) ? 0 : -EBUSY; 681 return (rate == ice->cur_rate) ? 0 : -EBUSY;
656 } 682 }
657 683
658 old_rate = ice->get_rate(ice); 684 if (force || !ice->is_spdif_master(ice)) {
659 if (force || (old_rate != rate)) 685 /* force means the rate was switched by ucontrol, otherwise
660 ice->set_rate(ice, rate); 686 * setting clock rate for internal clock mode */
661 else if (rate == ice->cur_rate) { 687 old_rate = ice->get_rate(ice);
662 spin_unlock_irqrestore(&ice->reg_lock, flags); 688 if (force || (old_rate != rate))
663 return 0; 689 ice->set_rate(ice, rate);
690 else if (rate == ice->cur_rate) {
691 spin_unlock_irqrestore(&ice->reg_lock, flags);
692 return 0;
693 }
664 } 694 }
665 695
666 ice->cur_rate = rate; 696 ice->cur_rate = rate;
@@ -1016,6 +1046,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
1016 VT1724_BUFFER_ALIGN); 1046 VT1724_BUFFER_ALIGN);
1017 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1047 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
1018 VT1724_BUFFER_ALIGN); 1048 VT1724_BUFFER_ALIGN);
1049 if (ice->pro_open)
1050 ice->pro_open(ice, substream);
1019 return 0; 1051 return 0;
1020} 1052}
1021 1053
@@ -1034,6 +1066,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
1034 VT1724_BUFFER_ALIGN); 1066 VT1724_BUFFER_ALIGN);
1035 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1067 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
1036 VT1724_BUFFER_ALIGN); 1068 VT1724_BUFFER_ALIGN);
1069 if (ice->pro_open)
1070 ice->pro_open(ice, substream);
1037 return 0; 1071 return 0;
1038} 1072}
1039 1073
@@ -1787,15 +1821,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
1787 struct snd_ctl_elem_info *uinfo) 1821 struct snd_ctl_elem_info *uinfo)
1788{ 1822{
1789 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1823 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1790 1824 int hw_rates_count = ice->hw_rates->count;
1791 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1825 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1792 uinfo->count = 1; 1826 uinfo->count = 1;
1793 uinfo->value.enumerated.items = ice->hw_rates->count + 1; 1827
1828 uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count;
1829 /* upper limit - keep at top */
1794 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1830 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1795 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 1831 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1796 if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) 1832 if (uinfo->value.enumerated.item >= hw_rates_count)
1797 strcpy(uinfo->value.enumerated.name, "IEC958 Input"); 1833 /* ext_clock items */
1834 strcpy(uinfo->value.enumerated.name,
1835 ice->ext_clock_names[
1836 uinfo->value.enumerated.item - hw_rates_count]);
1798 else 1837 else
1838 /* int clock items */
1799 sprintf(uinfo->value.enumerated.name, "%d", 1839 sprintf(uinfo->value.enumerated.name, "%d",
1800 ice->hw_rates->list[uinfo->value.enumerated.item]); 1840 ice->hw_rates->list[uinfo->value.enumerated.item]);
1801 return 0; 1841 return 0;
@@ -1809,7 +1849,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
1809 1849
1810 spin_lock_irq(&ice->reg_lock); 1850 spin_lock_irq(&ice->reg_lock);
1811 if (ice->is_spdif_master(ice)) { 1851 if (ice->is_spdif_master(ice)) {
1812 ucontrol->value.enumerated.item[0] = ice->hw_rates->count; 1852 ucontrol->value.enumerated.item[0] = ice->hw_rates->count +
1853 ice->get_spdif_master_type(ice);
1813 } else { 1854 } else {
1814 rate = ice->get_rate(ice); 1855 rate = ice->get_rate(ice);
1815 ucontrol->value.enumerated.item[0] = 0; 1856 ucontrol->value.enumerated.item[0] = 0;
@@ -1824,8 +1865,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
1824 return 0; 1865 return 0;
1825} 1866}
1826 1867
1868static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice)
1869{
1870 /* standard external clock - only single type - SPDIF IN */
1871 return 0;
1872}
1873
1827/* setting clock to external - SPDIF */ 1874/* setting clock to external - SPDIF */
1828static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) 1875static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type)
1829{ 1876{
1830 unsigned char oval; 1877 unsigned char oval;
1831 unsigned char i2s_oval; 1878 unsigned char i2s_oval;
@@ -1834,27 +1881,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
1834 /* setting 256fs */ 1881 /* setting 256fs */
1835 i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); 1882 i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
1836 outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); 1883 outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
1884 return 0;
1837} 1885}
1838 1886
1887
1839static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, 1888static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
1840 struct snd_ctl_elem_value *ucontrol) 1889 struct snd_ctl_elem_value *ucontrol)
1841{ 1890{
1842 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1891 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1843 unsigned int old_rate, new_rate; 1892 unsigned int old_rate, new_rate;
1844 unsigned int item = ucontrol->value.enumerated.item[0]; 1893 unsigned int item = ucontrol->value.enumerated.item[0];
1845 unsigned int spdif = ice->hw_rates->count; 1894 unsigned int first_ext_clock = ice->hw_rates->count;
1846 1895
1847 if (item > spdif) 1896 if (item > first_ext_clock + ice->ext_clock_count - 1)
1848 return -EINVAL; 1897 return -EINVAL;
1849 1898
1899 /* if rate = 0 => external clock */
1850 spin_lock_irq(&ice->reg_lock); 1900 spin_lock_irq(&ice->reg_lock);
1851 if (ice->is_spdif_master(ice)) 1901 if (ice->is_spdif_master(ice))
1852 old_rate = 0; 1902 old_rate = 0;
1853 else 1903 else
1854 old_rate = ice->get_rate(ice); 1904 old_rate = ice->get_rate(ice);
1855 if (item == spdif) { 1905 if (item >= first_ext_clock) {
1856 /* switching to external clock via SPDIF */ 1906 /* switching to external clock */
1857 ice->set_spdif_clock(ice); 1907 ice->set_spdif_clock(ice, item - first_ext_clock);
1858 new_rate = 0; 1908 new_rate = 0;
1859 } else { 1909 } else {
1860 /* internal on-card clock */ 1910 /* internal on-card clock */
@@ -1866,7 +1916,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
1866 } 1916 }
1867 spin_unlock_irq(&ice->reg_lock); 1917 spin_unlock_irq(&ice->reg_lock);
1868 1918
1869 /* the first reset to the SPDIF master mode? */ 1919 /* the first switch to the ext. clock mode? */
1870 if (old_rate != new_rate && !new_rate) { 1920 if (old_rate != new_rate && !new_rate) {
1871 /* notify akm chips as well */ 1921 /* notify akm chips as well */
1872 unsigned int i; 1922 unsigned int i;
@@ -2136,6 +2186,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
2136 snd_vt1724_phase_cards, 2186 snd_vt1724_phase_cards,
2137 snd_vt1724_wtm_cards, 2187 snd_vt1724_wtm_cards,
2138 snd_vt1724_se_cards, 2188 snd_vt1724_se_cards,
2189 snd_vt1724_qtet_cards,
2139 NULL, 2190 NULL,
2140}; 2191};
2141 2192
@@ -2434,7 +2485,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
2434 mutex_init(&ice->open_mutex); 2485 mutex_init(&ice->open_mutex);
2435 mutex_init(&ice->i2c_mutex); 2486 mutex_init(&ice->i2c_mutex);
2436 ice->gpio.set_mask = snd_vt1724_set_gpio_mask; 2487 ice->gpio.set_mask = snd_vt1724_set_gpio_mask;
2488 ice->gpio.get_mask = snd_vt1724_get_gpio_mask;
2437 ice->gpio.set_dir = snd_vt1724_set_gpio_dir; 2489 ice->gpio.set_dir = snd_vt1724_set_gpio_dir;
2490 ice->gpio.get_dir = snd_vt1724_get_gpio_dir;
2438 ice->gpio.set_data = snd_vt1724_set_gpio_data; 2491 ice->gpio.set_data = snd_vt1724_set_gpio_data;
2439 ice->gpio.get_data = snd_vt1724_get_gpio_data; 2492 ice->gpio.get_data = snd_vt1724_get_gpio_data;
2440 ice->card = card; 2493 ice->card = card;
@@ -2522,6 +2575,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
2522 return err; 2575 return err;
2523 } 2576 }
2524 2577
2578 /* field init before calling chip_init */
2579 ice->ext_clock_count = 0;
2580
2525 for (tbl = card_tables; *tbl; tbl++) { 2581 for (tbl = card_tables; *tbl; tbl++) {
2526 for (c = *tbl; c->subvendor; c++) { 2582 for (c = *tbl; c->subvendor; c++) {
2527 if (c->subvendor == ice->eeprom.subvendor) { 2583 if (c->subvendor == ice->eeprom.subvendor) {
@@ -2560,6 +2616,13 @@ __found:
2560 ice->set_mclk = stdclock_set_mclk; 2616 ice->set_mclk = stdclock_set_mclk;
2561 if (!ice->set_spdif_clock) 2617 if (!ice->set_spdif_clock)
2562 ice->set_spdif_clock = stdclock_set_spdif_clock; 2618 ice->set_spdif_clock = stdclock_set_spdif_clock;
2619 if (!ice->get_spdif_master_type)
2620 ice->get_spdif_master_type = stdclock_get_spdif_master_type;
2621 if (!ice->ext_clock_names)
2622 ice->ext_clock_names = ext_clock_names;
2623 if (!ice->ext_clock_count)
2624 ice->ext_clock_count = ARRAY_SIZE(ext_clock_names);
2625
2563 if (!ice->hw_rates) 2626 if (!ice->hw_rates)
2564 set_std_hw_rates(ice); 2627 set_std_hw_rates(ice);
2565 2628
@@ -2719,7 +2782,7 @@ static int snd_vt1724_resume(struct pci_dev *pci)
2719 2782
2720 if (ice->pm_saved_is_spdif_master) { 2783 if (ice->pm_saved_is_spdif_master) {
2721 /* switching to external clock via SPDIF */ 2784 /* switching to external clock via SPDIF */
2722 ice->set_spdif_clock(ice); 2785 ice->set_spdif_clock(ice, 0);
2723 } else { 2786 } else {
2724 /* internal on-card clock */ 2787 /* internal on-card clock */
2725 snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); 2788 snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index fd948bfd9aef..0c9413d5341b 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
412 }, 412 },
413}; 413};
414 414
415
416static void ak4358_proc_regs_read(struct snd_info_entry *entry,
417 struct snd_info_buffer *buffer)
418{
419 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
420 int reg, val;
421 for (reg = 0; reg <= 0xf; reg++) {
422 val = snd_akm4xxx_get(ice->akm, 0, reg);
423 snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
424 }
425}
426
427static void ak4358_proc_init(struct snd_ice1712 *ice)
428{
429 struct snd_info_entry *entry;
430 if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
431 snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
432}
433
434static char *slave_vols[] __devinitdata = { 415static char *slave_vols[] __devinitdata = {
435 PCM_VOLUME, 416 PCM_VOLUME,
436 MONITOR_AN_IN_VOLUME, 417 MONITOR_AN_IN_VOLUME,
@@ -496,14 +477,37 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
496 /* only capture SPDIF over AK4114 */ 477 /* only capture SPDIF over AK4114 */
497 err = snd_ak4114_build(spec->ak4114, NULL, 478 err = snd_ak4114_build(spec->ak4114, NULL,
498 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 479 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
499
500 ak4358_proc_init(ice);
501 if (err < 0) 480 if (err < 0)
502 return err; 481 return err;
503 return 0; 482 return 0;
504} 483}
505 484
506/* 485/*
486 * suspend/resume
487 * */
488
489#ifdef CONFIG_PM
490static int juli_resume(struct snd_ice1712 *ice)
491{
492 struct snd_akm4xxx *ak = ice->akm;
493 struct juli_spec *spec = ice->spec;
494 /* akm4358 un-reset, un-mute */
495 snd_akm4xxx_reset(ak, 0);
496 /* reinit ak4114 */
497 snd_ak4114_reinit(spec->ak4114);
498 return 0;
499}
500
501static int juli_suspend(struct snd_ice1712 *ice)
502{
503 struct snd_akm4xxx *ak = ice->akm;
504 /* akm4358 reset and soft-mute */
505 snd_akm4xxx_reset(ak, 1);
506 return 0;
507}
508#endif
509
510/*
507 * initialize the chip 511 * initialize the chip
508 */ 512 */
509 513
@@ -550,13 +554,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
550} 554}
551 555
552/* setting clock to external - SPDIF */ 556/* setting clock to external - SPDIF */
553static void juli_set_spdif_clock(struct snd_ice1712 *ice) 557static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type)
554{ 558{
555 unsigned int old; 559 unsigned int old;
556 old = ice->gpio.get_data(ice); 560 old = ice->gpio.get_data(ice);
557 /* external clock (= 0), multiply 1x, 48kHz */ 561 /* external clock (= 0), multiply 1x, 48kHz */
558 ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | 562 ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
559 GPIO_FREQ_48KHZ); 563 GPIO_FREQ_48KHZ);
564 return 0;
560} 565}
561 566
562/* Called when ak4114 detects change in the input SPDIF stream */ 567/* Called when ak4114 detects change in the input SPDIF stream */
@@ -646,6 +651,13 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
646 ice->set_spdif_clock = juli_set_spdif_clock; 651 ice->set_spdif_clock = juli_set_spdif_clock;
647 652
648 ice->spdif.ops.open = juli_spdif_in_open; 653 ice->spdif.ops.open = juli_spdif_in_open;
654
655#ifdef CONFIG_PM
656 ice->pm_resume = juli_resume;
657 ice->pm_suspend = juli_suspend;
658 ice->pm_suspend_enabled = 1;
659#endif
660
649 return 0; 661 return 0;
650} 662}
651 663
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
new file mode 100644
index 000000000000..1948632787e6
--- /dev/null
+++ b/sound/pci/ice1712/quartet.c
@@ -0,0 +1,1130 @@
1/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for Infrasonic Quartet
5 *
6 * Copyright (c) 2009 Pavel Hofman <pavel.hofman@ivitera.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include <asm/io.h>
26#include <linux/delay.h>
27#include <linux/interrupt.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <sound/core.h>
31#include <sound/tlv.h>
32#include <sound/info.h>
33
34#include "ice1712.h"
35#include "envy24ht.h"
36#include <sound/ak4113.h>
37#include "quartet.h"
38
39struct qtet_spec {
40 struct ak4113 *ak4113;
41 unsigned int scr; /* system control register */
42 unsigned int mcr; /* monitoring control register */
43 unsigned int cpld; /* cpld register */
44};
45
46struct qtet_kcontrol_private {
47 unsigned int bit;
48 void (*set_register)(struct snd_ice1712 *ice, unsigned int val);
49 unsigned int (*get_register)(struct snd_ice1712 *ice);
50 unsigned char *texts[2];
51};
52
53enum {
54 IN12_SEL = 0,
55 IN34_SEL,
56 AIN34_SEL,
57 COAX_OUT,
58 IN12_MON12,
59 IN12_MON34,
60 IN34_MON12,
61 IN34_MON34,
62 OUT12_MON34,
63 OUT34_MON12,
64};
65
66static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
67 "Word Clock 256xFS"};
68
69/* chip address on I2C bus */
70#define AK4113_ADDR 0x26 /* S/PDIF receiver */
71
72/* chip address on SPI bus */
73#define AK4620_ADDR 0x02 /* ADC/DAC */
74
75
76/*
77 * GPIO pins
78 */
79
80/* GPIO0 - O - DATA0, def. 0 */
81#define GPIO_D0 (1<<0)
82/* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */
83#define GPIO_D1_JACKDTC0 (1<<1)
84/* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */
85#define GPIO_D2_JACKDTC1 (1<<2)
86/* GPIO3 - I/O - DATA3, def. 1 */
87#define GPIO_D3 (1<<3)
88/* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */
89#define GPIO_D4_SPI_CDTO (1<<4)
90/* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */
91#define GPIO_D5_SPI_CCLK (1<<5)
92/* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */
93#define GPIO_D6_CD (1<<6)
94/* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */
95#define GPIO_D7_DD (1<<7)
96/* GPIO8 - O - CPLD Chip Select, def. 1 */
97#define GPIO_CPLD_CSN (1<<8)
98/* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */
99#define GPIO_CPLD_RW (1<<9)
100/* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */
101#define GPIO_SPI_CSN0 (1<<10)
102/* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */
103#define GPIO_SPI_CSN1 (1<<11)
104/* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1,
105 * init 0 */
106#define GPIO_EX_GPIOE (1<<12)
107/* GPIO13 - O - Ex. Register0 Chip Select for System Control Register,
108 * def. 1 */
109#define GPIO_SCR (1<<13)
110/* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register,
111 * def. 1 */
112#define GPIO_MCR (1<<14)
113
114#define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\
115 GPIO_SPI_CSN0 | GPIO_SPI_CSN1)
116
117#define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \
118 GPIO_D2_JACKDTC1 | GPIO_D3 | \
119 GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \
120 GPIO_D6_CD | GPIO_D7_DD)
121
122/* System Control Register GPIO_SCR data bits */
123/* Mic/Line select relay (0:line, 1:mic) */
124#define SCR_RELAY GPIO_D0
125/* Phantom power drive control (0:5V, 1:48V) */
126#define SCR_PHP_V GPIO_D1_JACKDTC0
127/* H/W mute control (0:Normal, 1:Mute) */
128#define SCR_MUTE GPIO_D2_JACKDTC1
129/* Phantom power control (0:Phantom on, 1:off) */
130#define SCR_PHP GPIO_D3
131/* Analog input 1/2 Source Select */
132#define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO
133#define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK
134/* Analog input 3/4 Source Select (0:line, 1:hi-z) */
135#define SCR_AIN34_SEL GPIO_D6_CD
136/* Codec Power Down (0:power down, 1:normal) */
137#define SCR_CODEC_PDN GPIO_D7_DD
138
139#define SCR_AIN12_LINE (0)
140#define SCR_AIN12_MIC (SCR_AIN12_SEL0)
141#define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0)
142
143/* Monitor Control Register GPIO_MCR data bits */
144/* Input 1/2 to Monitor 1/2 (0:off, 1:on) */
145#define MCR_IN12_MON12 GPIO_D0
146/* Input 1/2 to Monitor 3/4 (0:off, 1:on) */
147#define MCR_IN12_MON34 GPIO_D1_JACKDTC0
148/* Input 3/4 to Monitor 1/2 (0:off, 1:on) */
149#define MCR_IN34_MON12 GPIO_D2_JACKDTC1
150/* Input 3/4 to Monitor 3/4 (0:off, 1:on) */
151#define MCR_IN34_MON34 GPIO_D3
152/* Output to Monitor 1/2 (0:off, 1:on) */
153#define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO
154/* Output to Monitor 3/4 (0:off, 1:on) */
155#define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK
156
157/* CPLD Register DATA bits */
158/* Clock Rate Select */
159#define CPLD_CKS0 GPIO_D0
160#define CPLD_CKS1 GPIO_D1_JACKDTC0
161#define CPLD_CKS2 GPIO_D2_JACKDTC1
162/* Sync Source Select (0:Internal, 1:External) */
163#define CPLD_SYNC_SEL GPIO_D3
164/* Word Clock FS Select (0:FS, 1:256FS) */
165#define CPLD_WORD_SEL GPIO_D4_SPI_CDTO
166/* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */
167#define CPLD_COAX_OUT GPIO_D5_SPI_CCLK
168/* Input 1/2 Source Select (0:Analog12, 1:An34) */
169#define CPLD_IN12_SEL GPIO_D6_CD
170/* Input 3/4 Source Select (0:Analog34, 1:Digital In) */
171#define CPLD_IN34_SEL GPIO_D7_DD
172
173/* internal clock (CPLD_SYNC_SEL = 0) options */
174#define CPLD_CKS_44100HZ (0)
175#define CPLD_CKS_48000HZ (CPLD_CKS0)
176#define CPLD_CKS_88200HZ (CPLD_CKS1)
177#define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0)
178#define CPLD_CKS_176400HZ (CPLD_CKS2)
179#define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0)
180
181#define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2)
182
183/* external clock (CPLD_SYNC_SEL = 1) options */
184/* external clock - SPDIF */
185#define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL)
186/* external clock - WordClock 1xfs */
187#define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL)
188/* external clock - WordClock 256xfs */
189#define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\
190 CPLD_SYNC_SEL)
191
192#define EXT_SPDIF_TYPE 0
193#define EXT_WORDCLOCK_1FS_TYPE 1
194#define EXT_WORDCLOCK_256FS_TYPE 2
195
196#define AK4620_DFS0 (1<<0)
197#define AK4620_DFS1 (1<<1)
198#define AK4620_CKS0 (1<<2)
199#define AK4620_CKS1 (1<<3)
200/* Clock and Format Control register */
201#define AK4620_DFS_REG 0x02
202
203/* Deem and Volume Control register */
204#define AK4620_DEEMVOL_REG 0x03
205#define AK4620_SMUTE (1<<7)
206
207/*
208 * Conversion from int value to its binary form. Used for debugging.
209 * The output buffer must be allocated prior to calling the function.
210 */
211static char *get_binary(char *buffer, int value)
212{
213 int i, j, pos;
214 pos = 0;
215 for (i = 0; i < 4; ++i) {
216 for (j = 0; j < 8; ++j) {
217 if (value & (1 << (31-(i*8 + j))))
218 buffer[pos] = '1';
219 else
220 buffer[pos] = '0';
221 pos++;
222 }
223 if (i < 3) {
224 buffer[pos] = ' ';
225 pos++;
226 }
227 }
228 buffer[pos] = '\0';
229 return buffer;
230}
231
232/*
233 * Initial setup of the conversion array GPIO <-> rate
234 */
235static unsigned int qtet_rates[] = {
236 44100, 48000, 88200,
237 96000, 176400, 192000,
238};
239
240static unsigned int cks_vals[] = {
241 CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ,
242 CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ,
243};
244
245static struct snd_pcm_hw_constraint_list qtet_rates_info = {
246 .count = ARRAY_SIZE(qtet_rates),
247 .list = qtet_rates,
248 .mask = 0,
249};
250
251static void qtet_ak4113_write(void *private_data, unsigned char reg,
252 unsigned char val)
253{
254 snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR,
255 reg, val);
256}
257
258static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg)
259{
260 return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data,
261 AK4113_ADDR, reg);
262}
263
264
265/*
266 * AK4620 section
267 */
268
269/*
270 * Write data to addr register of ak4620
271 */
272static void qtet_akm_write(struct snd_akm4xxx *ak, int chip,
273 unsigned char addr, unsigned char data)
274{
275 unsigned int tmp, orig_dir;
276 int idx;
277 unsigned int addrdata;
278 struct snd_ice1712 *ice = ak->private_data[0];
279
280 if (snd_BUG_ON(chip < 0 || chip >= 4))
281 return;
282 /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x,
283 data=0x%x\n", chip, addr, data);*/
284 orig_dir = ice->gpio.get_dir(ice);
285 ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL);
286 /* set mask - only SPI bits */
287 ice->gpio.set_mask(ice, ~GPIO_SPI_ALL);
288
289 tmp = ice->gpio.get_data(ice);
290 /* high all */
291 tmp |= GPIO_SPI_ALL;
292 ice->gpio.set_data(ice, tmp);
293 udelay(100);
294 /* drop chip select */
295 if (chip)
296 /* CODEC 1 */
297 tmp &= ~GPIO_SPI_CSN1;
298 else
299 tmp &= ~GPIO_SPI_CSN0;
300 ice->gpio.set_data(ice, tmp);
301 udelay(100);
302
303 /* build I2C address + data byte */
304 addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f);
305 addrdata = (addrdata << 8) | data;
306 for (idx = 15; idx >= 0; idx--) {
307 /* drop clock */
308 tmp &= ~GPIO_D5_SPI_CCLK;
309 ice->gpio.set_data(ice, tmp);
310 udelay(100);
311 /* set data */
312 if (addrdata & (1 << idx))
313 tmp |= GPIO_D4_SPI_CDTO;
314 else
315 tmp &= ~GPIO_D4_SPI_CDTO;
316 ice->gpio.set_data(ice, tmp);
317 udelay(100);
318 /* raise clock */
319 tmp |= GPIO_D5_SPI_CCLK;
320 ice->gpio.set_data(ice, tmp);
321 udelay(100);
322 }
323 /* all back to 1 */
324 tmp |= GPIO_SPI_ALL;
325 ice->gpio.set_data(ice, tmp);
326 udelay(100);
327
328 /* return all gpios to non-writable */
329 ice->gpio.set_mask(ice, 0xffffff);
330 /* restore GPIOs direction */
331 ice->gpio.set_dir(ice, orig_dir);
332}
333
334static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr,
335 unsigned char mask, unsigned char value)
336{
337 unsigned char tmp;
338 int chip;
339 for (chip = 0; chip < ak->num_chips; chip++) {
340 tmp = snd_akm4xxx_get(ak, chip, addr);
341 /* clear the bits */
342 tmp &= ~mask;
343 /* set the new bits */
344 tmp |= value;
345 snd_akm4xxx_write(ak, chip, addr, tmp);
346 }
347}
348
349/*
350 * change the rate of AK4620
351 */
352static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
353{
354 unsigned char ak4620_dfs;
355
356 if (rate == 0) /* no hint - S/PDIF input is master or the new spdif
357 input rate undetected, simply return */
358 return;
359
360 /* adjust DFS on codecs - see datasheet */
361 if (rate > 108000)
362 ak4620_dfs = AK4620_DFS1 | AK4620_CKS1;
363 else if (rate > 54000)
364 ak4620_dfs = AK4620_DFS0 | AK4620_CKS0;
365 else
366 ak4620_dfs = 0;
367
368 /* set new value */
369 qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 |
370 AK4620_CKS0 | AK4620_CKS1, ak4620_dfs);
371}
372
373#define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch }
374
375#define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume"
376#define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume"
377#define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume"
378#define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume"
379
380static const struct snd_akm4xxx_dac_channel qtet_dac[] = {
381 AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2),
382 AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2),
383};
384
385static const struct snd_akm4xxx_adc_channel qtet_adc[] = {
386 AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2),
387 AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2),
388};
389
390static struct snd_akm4xxx akm_qtet_dac __devinitdata = {
391 .type = SND_AK4620,
392 .num_dacs = 4, /* DAC1 - Output 12
393 */
394 .num_adcs = 4, /* ADC1 - Input 12
395 */
396 .ops = {
397 .write = qtet_akm_write,
398 .set_rate_val = qtet_akm_set_rate_val,
399 },
400 .dac_info = qtet_dac,
401 .adc_info = qtet_adc,
402};
403
404/* Communication routines with the CPLD */
405
406
407/* Writes data to external register reg, both reg and data are
408 * GPIO representations */
409static void reg_write(struct snd_ice1712 *ice, unsigned int reg,
410 unsigned int data)
411{
412 unsigned int tmp;
413
414 mutex_lock(&ice->gpio_mutex);
415 /* set direction of used GPIOs*/
416 /* all outputs */
417 tmp = 0x00ffff;
418 ice->gpio.set_dir(ice, tmp);
419 /* mask - writable bits */
420 ice->gpio.set_mask(ice, ~(tmp));
421 /* write the data */
422 tmp = ice->gpio.get_data(ice);
423 tmp &= ~GPIO_DATA_MASK;
424 tmp |= data;
425 ice->gpio.set_data(ice, tmp);
426 udelay(100);
427 /* drop output enable */
428 tmp &= ~GPIO_EX_GPIOE;
429 ice->gpio.set_data(ice, tmp);
430 udelay(100);
431 /* drop the register gpio */
432 tmp &= ~reg;
433 ice->gpio.set_data(ice, tmp);
434 udelay(100);
435 /* raise the register GPIO */
436 tmp |= reg;
437 ice->gpio.set_data(ice, tmp);
438 udelay(100);
439
440 /* raise all data gpios */
441 tmp |= GPIO_DATA_MASK;
442 ice->gpio.set_data(ice, tmp);
443 /* mask - immutable bits */
444 ice->gpio.set_mask(ice, 0xffffff);
445 /* outputs only 8-15 */
446 ice->gpio.set_dir(ice, 0x00ff00);
447 mutex_unlock(&ice->gpio_mutex);
448}
449
450static unsigned int get_scr(struct snd_ice1712 *ice)
451{
452 struct qtet_spec *spec = ice->spec;
453 return spec->scr;
454}
455
456static unsigned int get_mcr(struct snd_ice1712 *ice)
457{
458 struct qtet_spec *spec = ice->spec;
459 return spec->mcr;
460}
461
462static unsigned int get_cpld(struct snd_ice1712 *ice)
463{
464 struct qtet_spec *spec = ice->spec;
465 return spec->cpld;
466}
467
468static void set_scr(struct snd_ice1712 *ice, unsigned int val)
469{
470 struct qtet_spec *spec = ice->spec;
471 reg_write(ice, GPIO_SCR, val);
472 spec->scr = val;
473}
474
475static void set_mcr(struct snd_ice1712 *ice, unsigned int val)
476{
477 struct qtet_spec *spec = ice->spec;
478 reg_write(ice, GPIO_MCR, val);
479 spec->mcr = val;
480}
481
482static void set_cpld(struct snd_ice1712 *ice, unsigned int val)
483{
484 struct qtet_spec *spec = ice->spec;
485 reg_write(ice, GPIO_CPLD_CSN, val);
486 spec->cpld = val;
487}
488#ifdef CONFIG_PROC_FS
489static void proc_regs_read(struct snd_info_entry *entry,
490 struct snd_info_buffer *buffer)
491{
492 struct snd_ice1712 *ice = entry->private_data;
493 char bin_buffer[36];
494
495 snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer,
496 get_scr(ice)));
497 snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer,
498 get_mcr(ice)));
499 snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer,
500 get_cpld(ice)));
501}
502
503static void proc_init(struct snd_ice1712 *ice)
504{
505 struct snd_info_entry *entry;
506 if (!snd_card_proc_new(ice->card, "quartet", &entry))
507 snd_info_set_text_ops(entry, ice, proc_regs_read);
508}
509#else /* !CONFIG_PROC_FS */
510static void proc_init(struct snd_ice1712 *ice) {}
511#endif
512
513static int qtet_mute_get(struct snd_kcontrol *kcontrol,
514 struct snd_ctl_elem_value *ucontrol)
515{
516 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
517 unsigned int val;
518 val = get_scr(ice) & SCR_MUTE;
519 ucontrol->value.integer.value[0] = (val) ? 0 : 1;
520 return 0;
521}
522
523static int qtet_mute_put(struct snd_kcontrol *kcontrol,
524 struct snd_ctl_elem_value *ucontrol)
525{
526 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
527 unsigned int old, new, smute;
528 old = get_scr(ice) & SCR_MUTE;
529 if (ucontrol->value.integer.value[0]) {
530 /* unmute */
531 new = 0;
532 /* un-smuting DAC */
533 smute = 0;
534 } else {
535 /* mute */
536 new = SCR_MUTE;
537 /* smuting DAC */
538 smute = AK4620_SMUTE;
539 }
540 if (old != new) {
541 struct snd_akm4xxx *ak = ice->akm;
542 set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new);
543 /* set smute */
544 qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute);
545 return 1;
546 }
547 /* no change */
548 return 0;
549}
550
551static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_info *uinfo)
553{
554 static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"};
555 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
556 uinfo->count = 1;
557 uinfo->value.enumerated.items = ARRAY_SIZE(texts);
558
559 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
560 uinfo->value.enumerated.item =
561 uinfo->value.enumerated.items - 1;
562 strcpy(uinfo->value.enumerated.name,
563 texts[uinfo->value.enumerated.item]);
564
565 return 0;
566}
567
568static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_value *ucontrol)
570{
571 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
572 unsigned int val, result;
573 val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0);
574 switch (val) {
575 case SCR_AIN12_LINE:
576 result = 0;
577 break;
578 case SCR_AIN12_MIC:
579 result = 1;
580 break;
581 case SCR_AIN12_LOWCUT:
582 result = 2;
583 break;
584 default:
585 /* BUG - no other combinations allowed */
586 snd_BUG();
587 result = 0;
588 }
589 ucontrol->value.integer.value[0] = result;
590 return 0;
591}
592
593static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol,
594 struct snd_ctl_elem_value *ucontrol)
595{
596 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
597 unsigned int old, new, tmp, masked_old;
598 old = new = get_scr(ice);
599 masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0);
600 tmp = ucontrol->value.integer.value[0];
601 if (tmp == 2)
602 tmp = 3; /* binary 10 is not supported */
603 tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */
604 if (tmp != masked_old) {
605 /* change requested */
606 switch (tmp) {
607 case SCR_AIN12_LINE:
608 new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0);
609 set_scr(ice, new);
610 /* turn off relay */
611 new &= ~SCR_RELAY;
612 set_scr(ice, new);
613 break;
614 case SCR_AIN12_MIC:
615 /* turn on relay */
616 new = old | SCR_RELAY;
617 set_scr(ice, new);
618 new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0;
619 set_scr(ice, new);
620 break;
621 case SCR_AIN12_LOWCUT:
622 /* turn on relay */
623 new = old | SCR_RELAY;
624 set_scr(ice, new);
625 new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0;
626 set_scr(ice, new);
627 break;
628 default:
629 snd_BUG();
630 }
631 return 1;
632 }
633 /* no change */
634 return 0;
635}
636
637static int qtet_php_get(struct snd_kcontrol *kcontrol,
638 struct snd_ctl_elem_value *ucontrol)
639{
640 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
641 unsigned int val;
642 /* if phantom voltage =48V, phantom on */
643 val = get_scr(ice) & SCR_PHP_V;
644 ucontrol->value.integer.value[0] = val ? 1 : 0;
645 return 0;
646}
647
648static int qtet_php_put(struct snd_kcontrol *kcontrol,
649 struct snd_ctl_elem_value *ucontrol)
650{
651 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
652 unsigned int old, new;
653 old = new = get_scr(ice);
654 if (ucontrol->value.integer.value[0] /* phantom on requested */
655 && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ {
656 /* is off, turn on */
657 /* turn voltage on first, = 1 */
658 new = old | SCR_PHP_V;
659 set_scr(ice, new);
660 /* turn phantom on, = 0 */
661 new &= ~SCR_PHP;
662 set_scr(ice, new);
663 } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) {
664 /* phantom off requested and 1 = voltage 48V */
665 /* is on, turn off */
666 /* turn voltage off first, = 0 */
667 new = old & ~SCR_PHP_V;
668 set_scr(ice, new);
669 /* turn phantom off, = 1 */
670 new |= SCR_PHP;
671 set_scr(ice, new);
672 }
673 if (old != new)
674 return 1;
675 /* no change */
676 return 0;
677}
678
679#define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\
680 .set_register = set_##xreg,\
681 .get_register = get_##xreg, }
682
683
684#define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\
685 .set_register = set_##xreg,\
686 .get_register = get_##xreg,\
687 .texts = {xtext1, xtext2} }
688
689static struct qtet_kcontrol_private qtet_privates[] = {
690 PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"),
691 PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"),
692 PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"),
693 PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"),
694 PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr),
695 PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr),
696 PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr),
697 PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr),
698 PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr),
699 PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr),
700};
701
702static int qtet_enum_info(struct snd_kcontrol *kcontrol,
703 struct snd_ctl_elem_info *uinfo)
704{
705 struct qtet_kcontrol_private private =
706 qtet_privates[kcontrol->private_value];
707 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
708 uinfo->count = 1;
709 uinfo->value.enumerated.items = ARRAY_SIZE(private.texts);
710
711 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
712 uinfo->value.enumerated.item =
713 uinfo->value.enumerated.items - 1;
714 strcpy(uinfo->value.enumerated.name,
715 private.texts[uinfo->value.enumerated.item]);
716
717 return 0;
718}
719
720static int qtet_sw_get(struct snd_kcontrol *kcontrol,
721 struct snd_ctl_elem_value *ucontrol)
722{
723 struct qtet_kcontrol_private private =
724 qtet_privates[kcontrol->private_value];
725 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
726 ucontrol->value.integer.value[0] =
727 (private.get_register(ice) & private.bit) ? 1 : 0;
728 return 0;
729}
730
731static int qtet_sw_put(struct snd_kcontrol *kcontrol,
732 struct snd_ctl_elem_value *ucontrol)
733{
734 struct qtet_kcontrol_private private =
735 qtet_privates[kcontrol->private_value];
736 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
737 unsigned int old, new;
738 old = private.get_register(ice);
739 if (ucontrol->value.integer.value[0])
740 new = old | private.bit;
741 else
742 new = old & ~private.bit;
743 if (old != new) {
744 private.set_register(ice, new);
745 return 1;
746 }
747 /* no change */
748 return 0;
749}
750
751#define qtet_sw_info snd_ctl_boolean_mono_info
752
753#define QTET_CONTROL(xname, xtype, xpriv) \
754 {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
755 .name = xname,\
756 .info = qtet_##xtype##_info,\
757 .get = qtet_sw_get,\
758 .put = qtet_sw_put,\
759 .private_value = xpriv }
760
761static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
762 {
763 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
764 .name = "Master Playback Switch",
765 .info = qtet_sw_info,
766 .get = qtet_mute_get,
767 .put = qtet_mute_put,
768 .private_value = 0
769 },
770 {
771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
772 .name = "Phantom Power",
773 .info = qtet_sw_info,
774 .get = qtet_php_get,
775 .put = qtet_php_put,
776 .private_value = 0
777 },
778 {
779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
780 .name = "Analog In 1/2 Capture Switch",
781 .info = qtet_ain12_enum_info,
782 .get = qtet_ain12_sw_get,
783 .put = qtet_ain12_sw_put,
784 .private_value = 0
785 },
786 QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL),
787 QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL),
788 QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL),
789 QTET_CONTROL("Coax Output Source", enum, COAX_OUT),
790 QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12),
791 QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34),
792 QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12),
793 QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34),
794 QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34),
795 QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12),
796};
797
798static char *slave_vols[] __devinitdata = {
799 PCM_12_PLAYBACK_VOLUME,
800 PCM_34_PLAYBACK_VOLUME,
801 NULL
802};
803
804static __devinitdata
805DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1);
806
807static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
808 const char *name)
809{
810 struct snd_ctl_elem_id sid;
811 memset(&sid, 0, sizeof(sid));
812 /* FIXME: strcpy is bad. */
813 strcpy(sid.name, name);
814 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
815 return snd_ctl_find_id(card, &sid);
816}
817
818static void __devinit add_slaves(struct snd_card *card,
819 struct snd_kcontrol *master, char **list)
820{
821 for (; *list; list++) {
822 struct snd_kcontrol *slave = ctl_find(card, *list);
823 if (slave)
824 snd_ctl_add_slave(master, slave);
825 }
826}
827
828static int __devinit qtet_add_controls(struct snd_ice1712 *ice)
829{
830 struct qtet_spec *spec = ice->spec;
831 int err, i;
832 struct snd_kcontrol *vmaster;
833 err = snd_ice1712_akm4xxx_build_controls(ice);
834 if (err < 0)
835 return err;
836 for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) {
837 err = snd_ctl_add(ice->card,
838 snd_ctl_new1(&qtet_controls[i], ice));
839 if (err < 0)
840 return err;
841 }
842
843 /* Create virtual master control */
844 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
845 qtet_master_db_scale);
846 if (!vmaster)
847 return -ENOMEM;
848 add_slaves(ice->card, vmaster, slave_vols);
849 err = snd_ctl_add(ice->card, vmaster);
850 if (err < 0)
851 return err;
852 /* only capture SPDIF over AK4113 */
853 err = snd_ak4113_build(spec->ak4113,
854 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
855 if (err < 0)
856 return err;
857 return 0;
858}
859
860static inline int qtet_is_spdif_master(struct snd_ice1712 *ice)
861{
862 /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */
863 return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0;
864}
865
866static unsigned int qtet_get_rate(struct snd_ice1712 *ice)
867{
868 int i;
869 unsigned char result;
870
871 result = get_cpld(ice) & CPLD_CKS_MASK;
872 for (i = 0; i < ARRAY_SIZE(cks_vals); i++)
873 if (cks_vals[i] == result)
874 return qtet_rates[i];
875 return 0;
876}
877
878static int get_cks_val(int rate)
879{
880 int i;
881 for (i = 0; i < ARRAY_SIZE(qtet_rates); i++)
882 if (qtet_rates[i] == rate)
883 return cks_vals[i];
884 return 0;
885}
886
887/* setting new rate */
888static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate)
889{
890 unsigned int new;
891 unsigned char val;
892 /* switching ice1724 to external clock - supplied by ext. circuits */
893 val = inb(ICEMT1724(ice, RATE));
894 outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
895
896 new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate);
897 /* switch to internal clock, drop CPLD_SYNC_SEL */
898 new &= ~CPLD_SYNC_SEL;
899 /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n",
900 get_cpld(ice), new); */
901 set_cpld(ice, new);
902}
903
904static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice,
905 unsigned int rate)
906{
907 /* no change in master clock */
908 return 0;
909}
910
911/* setting clock to external - SPDIF */
912static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type)
913{
914 unsigned int old, new;
915
916 old = new = get_cpld(ice);
917 new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL);
918 switch (type) {
919 case EXT_SPDIF_TYPE:
920 new |= CPLD_EXT_SPDIF;
921 break;
922 case EXT_WORDCLOCK_1FS_TYPE:
923 new |= CPLD_EXT_WORDCLOCK_1FS;
924 break;
925 case EXT_WORDCLOCK_256FS_TYPE:
926 new |= CPLD_EXT_WORDCLOCK_256FS;
927 break;
928 default:
929 snd_BUG();
930 }
931 if (old != new) {
932 set_cpld(ice, new);
933 /* changed */
934 return 1;
935 }
936 return 0;
937}
938
939static int qtet_get_spdif_master_type(struct snd_ice1712 *ice)
940{
941 unsigned int val;
942 int result;
943 val = get_cpld(ice);
944 /* checking only rate/clock-related bits */
945 val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL);
946 if (!(val & CPLD_SYNC_SEL)) {
947 /* switched to internal clock, is not any external type */
948 result = -1;
949 } else {
950 switch (val) {
951 case (CPLD_EXT_SPDIF):
952 result = EXT_SPDIF_TYPE;
953 break;
954 case (CPLD_EXT_WORDCLOCK_1FS):
955 result = EXT_WORDCLOCK_1FS_TYPE;
956 break;
957 case (CPLD_EXT_WORDCLOCK_256FS):
958 result = EXT_WORDCLOCK_256FS_TYPE;
959 break;
960 default:
961 /* undefined combination of external clock setup */
962 snd_BUG();
963 result = 0;
964 }
965 }
966 return result;
967}
968
969/* Called when ak4113 detects change in the input SPDIF stream */
970static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0,
971 unsigned char c1)
972{
973 struct snd_ice1712 *ice = ak4113->change_callback_private;
974 int rate;
975 if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) &&
976 c1) {
977 /* only for SPDIF master mode, rate was changed */
978 rate = snd_ak4113_external_rate(ak4113);
979 /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n",
980 rate); */
981 qtet_akm_set_rate_val(ice->akm, rate);
982 }
983}
984
985/*
986 * If clock slaved to SPDIF-IN, setting runtime rate
987 * to the detected external rate
988 */
989static void qtet_spdif_in_open(struct snd_ice1712 *ice,
990 struct snd_pcm_substream *substream)
991{
992 struct qtet_spec *spec = ice->spec;
993 struct snd_pcm_runtime *runtime = substream->runtime;
994 int rate;
995
996 if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE)
997 /* not external SPDIF, no rate limitation */
998 return;
999 /* only external SPDIF can detect incoming sample rate */
1000 rate = snd_ak4113_external_rate(spec->ak4113);
1001 if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
1002 runtime->hw.rate_min = rate;
1003 runtime->hw.rate_max = rate;
1004 }
1005}
1006
1007/*
1008 * initialize the chip
1009 */
1010static int __devinit qtet_init(struct snd_ice1712 *ice)
1011{
1012 static const unsigned char ak4113_init_vals[] = {
1013 /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN |
1014 AK4113_OCKS0 | AK4113_OCKS1,
1015 /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX |
1016 AK4113_DEM_OFF | AK4113_DEAU,
1017 /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE |
1018 AK4113_XTL_24_576M,
1019 /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0),
1020 /* AK4113_REG_INT0_MASK */ 0,
1021 /* AK4113_REG_INT1_MASK */ 0,
1022 /* AK4113_REG_DATDTS */ 0,
1023 };
1024 int err;
1025 struct qtet_spec *spec;
1026 struct snd_akm4xxx *ak;
1027 unsigned char val;
1028
1029 /* switching ice1724 to external clock - supplied by ext. circuits */
1030 val = inb(ICEMT1724(ice, RATE));
1031 outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
1032
1033 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1034 if (!spec)
1035 return -ENOMEM;
1036 /* qtet is clocked by Xilinx array */
1037 ice->hw_rates = &qtet_rates_info;
1038 ice->is_spdif_master = qtet_is_spdif_master;
1039 ice->get_rate = qtet_get_rate;
1040 ice->set_rate = qtet_set_rate;
1041 ice->set_mclk = qtet_set_mclk;
1042 ice->set_spdif_clock = qtet_set_spdif_clock;
1043 ice->get_spdif_master_type = qtet_get_spdif_master_type;
1044 ice->ext_clock_names = ext_clock_names;
1045 ice->ext_clock_count = ARRAY_SIZE(ext_clock_names);
1046 /* since Qtet can detect correct SPDIF-in rate, all streams can be
1047 * limited to this specific rate */
1048 ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open;
1049 ice->spec = spec;
1050
1051 /* Mute Off */
1052 /* SCR Initialize*/
1053 /* keep codec power down first */
1054 set_scr(ice, SCR_PHP);
1055 udelay(1);
1056 /* codec power up */
1057 set_scr(ice, SCR_PHP | SCR_CODEC_PDN);
1058
1059 /* MCR Initialize */
1060 set_mcr(ice, 0);
1061
1062 /* CPLD Initialize */
1063 set_cpld(ice, 0);
1064
1065
1066 ice->num_total_dacs = 2;
1067 ice->num_total_adcs = 2;
1068
1069 ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL);
1070 ak = ice->akm;
1071 if (!ak)
1072 return -ENOMEM;
1073 /* only one codec with two chips */
1074 ice->akm_codecs = 1;
1075 err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice);
1076 if (err < 0)
1077 return err;
1078 err = snd_ak4113_create(ice->card,
1079 qtet_ak4113_read,
1080 qtet_ak4113_write,
1081 ak4113_init_vals,
1082 ice, &spec->ak4113);
1083 if (err < 0)
1084 return err;
1085 /* callback for codecs rate setting */
1086 spec->ak4113->change_callback = qtet_ak4113_change;
1087 spec->ak4113->change_callback_private = ice;
1088 /* AK41143 in Quartet can detect external rate correctly
1089 * (i.e. check_flags = 0) */
1090 spec->ak4113->check_flags = 0;
1091
1092 proc_init(ice);
1093
1094 qtet_set_rate(ice, 44100);
1095 return 0;
1096}
1097
1098static unsigned char qtet_eeprom[] __devinitdata = {
1099 [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC,
1100 1xDACs, SPDIF in */
1101 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
1102 [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */
1103 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */
1104 [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output
1105 only during output operations */
1106 [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */
1107 [ICE_EEP2_GPIO_DIR2] = 0x00,
1108 [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */
1109 [ICE_EEP2_GPIO_MASK1] = 0x00,
1110 [ICE_EEP2_GPIO_MASK2] = 0xff,
1111
1112 [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */
1113 [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW
1114 and GPIO15 always zero */
1115 [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */
1116};
1117
1118/* entry point */
1119struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = {
1120 {
1121 .subvendor = VT1724_SUBDEVICE_QTET,
1122 .name = "Infrasonic Quartet",
1123 .model = "quartet",
1124 .chip_init = qtet_init,
1125 .build_controls = qtet_add_controls,
1126 .eeprom_size = sizeof(qtet_eeprom),
1127 .eeprom_data = qtet_eeprom,
1128 },
1129 { } /* terminator */
1130};
diff --git a/sound/pci/ice1712/quartet.h b/sound/pci/ice1712/quartet.h
new file mode 100644
index 000000000000..80809b72439a
--- /dev/null
+++ b/sound/pci/ice1712/quartet.h
@@ -0,0 +1,10 @@
1#ifndef __SOUND_QTET_H
2#define __SOUND_QTET_H
3
4#define QTET_DEVICE_DESC "{Infrasonic,Quartet},"
5
6#define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */
7
8extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[];
9
10#endif /* __SOUND_QTET_H */
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index aac20fb4aad2..b990143636f1 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2063,6 +2063,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
2063 .type = AC97_TUNE_HP_ONLY 2063 .type = AC97_TUNE_HP_ONLY
2064 }, 2064 },
2065 { 2065 {
2066 .subvendor = 0x161f,
2067 .subdevice = 0x203a,
2068 .name = "Gateway 4525GZ", /* AD1981B */
2069 .type = AC97_TUNE_INV_EAPD
2070 },
2071 {
2066 .subvendor = 0x1734, 2072 .subvendor = 0x1734,
2067 .subdevice = 0x0088, 2073 .subdevice = 0x0088,
2068 .name = "Fujitsu-Siemens D1522", /* AD1981 */ 2074 .name = "Fujitsu-Siemens D1522", /* AD1981 */
diff --git a/sound/pci/oxygen/Makefile b/sound/pci/oxygen/Makefile
index 4ba07d42fd1d..389941cf6100 100644
--- a/sound/pci/oxygen/Makefile
+++ b/sound/pci/oxygen/Makefile
@@ -1,7 +1,8 @@
1snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o 1snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o
2snd-hifier-objs := hifier.o 2snd-hifier-objs := hifier.o
3snd-oxygen-objs := oxygen.o 3snd-oxygen-objs := oxygen.o
4snd-virtuoso-objs := virtuoso.o 4snd-virtuoso-objs := virtuoso.o xonar_lib.o \
5 xonar_pcm179x.o xonar_cs43xx.o xonar_hdmi.o
5 6
6obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o 7obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o
7obj-$(CONFIG_SND_HIFIER) += snd-hifier.o 8obj-$(CONFIG_SND_HIFIER) += snd-hifier.o
diff --git a/sound/pci/oxygen/cs2000.h b/sound/pci/oxygen/cs2000.h
new file mode 100644
index 000000000000..c3501bdb5edc
--- /dev/null
+++ b/sound/pci/oxygen/cs2000.h
@@ -0,0 +1,83 @@
1#ifndef CS2000_H_INCLUDED
2#define CS2000_H_INCLUDED
3
4#define CS2000_DEV_ID 0x01
5#define CS2000_DEV_CTRL 0x02
6#define CS2000_DEV_CFG_1 0x03
7#define CS2000_DEV_CFG_2 0x04
8#define CS2000_GLOBAL_CFG 0x05
9#define CS2000_RATIO_0 0x06 /* 32 bits, big endian */
10#define CS2000_RATIO_1 0x0a
11#define CS2000_RATIO_2 0x0e
12#define CS2000_RATIO_3 0x12
13#define CS2000_FUN_CFG_1 0x16
14#define CS2000_FUN_CFG_2 0x17
15#define CS2000_FUN_CFG_3 0x1e
16
17/* DEV_ID */
18#define CS2000_DEVICE_MASK 0xf8
19#define CS2000_REVISION_MASK 0x07
20
21/* DEV_CTRL */
22#define CS2000_UNLOCK 0x80
23#define CS2000_AUX_OUT_DIS 0x02
24#define CS2000_CLK_OUT_DIS 0x01
25
26/* DEV_CFG_1 */
27#define CS2000_R_MOD_SEL_MASK 0xe0
28#define CS2000_R_MOD_SEL_1 0x00
29#define CS2000_R_MOD_SEL_2 0x20
30#define CS2000_R_MOD_SEL_4 0x40
31#define CS2000_R_MOD_SEL_8 0x60
32#define CS2000_R_MOD_SEL_1_2 0x80
33#define CS2000_R_MOD_SEL_1_4 0xa0
34#define CS2000_R_MOD_SEL_1_8 0xc0
35#define CS2000_R_MOD_SEL_1_16 0xe0
36#define CS2000_R_SEL_MASK 0x18
37#define CS2000_R_SEL_SHIFT 3
38#define CS2000_AUX_OUT_SRC_MASK 0x06
39#define CS2000_AUX_OUT_SRC_REF_CLK 0x00
40#define CS2000_AUX_OUT_SRC_CLK_IN 0x02
41#define CS2000_AUX_OUT_SRC_CLK_OUT 0x04
42#define CS2000_AUX_OUT_SRC_PLL_LOCK 0x06
43#define CS2000_EN_DEV_CFG_1 0x01
44
45/* DEV_CFG_2 */
46#define CS2000_LOCK_CLK_MASK 0x06
47#define CS2000_LOCK_CLK_SHIFT 1
48#define CS2000_FRAC_N_SRC_MASK 0x01
49#define CS2000_FRAC_N_SRC_STATIC 0x00
50#define CS2000_FRAC_N_SRC_DYNAMIC 0x01
51
52/* GLOBAL_CFG */
53#define CS2000_FREEZE 0x08
54#define CS2000_EN_DEV_CFG_2 0x01
55
56/* FUN_CFG_1 */
57#define CS2000_CLK_SKIP_EN 0x80
58#define CS2000_AUX_LOCK_CFG_MASK 0x40
59#define CS2000_AUX_LOCK_CFG_PP_HIGH 0x00
60#define CS2000_AUX_LOCK_CFG_OD_LOW 0x40
61#define CS2000_REF_CLK_DIV_MASK 0x18
62#define CS2000_REF_CLK_DIV_4 0x00
63#define CS2000_REF_CLK_DIV_2 0x08
64#define CS2000_REF_CLK_DIV_1 0x10
65
66/* FUN_CFG_2 */
67#define CS2000_CLK_OUT_UNL 0x10
68#define CS2000_L_F_RATIO_CFG_MASK 0x08
69#define CS2000_L_F_RATIO_CFG_20_12 0x00
70#define CS2000_L_F_RATIO_CFG_12_20 0x08
71
72/* FUN_CFG_3 */
73#define CS2000_CLK_IN_BW_MASK 0x70
74#define CS2000_CLK_IN_BW_1 0x00
75#define CS2000_CLK_IN_BW_2 0x10
76#define CS2000_CLK_IN_BW_4 0x20
77#define CS2000_CLK_IN_BW_8 0x30
78#define CS2000_CLK_IN_BW_16 0x40
79#define CS2000_CLK_IN_BW_32 0x50
80#define CS2000_CLK_IN_BW_64 0x60
81#define CS2000_CLK_IN_BW_128 0x70
82
83#endif
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 84ef13183419..e3c229b63311 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -17,6 +17,12 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20/*
21 * CMI8788:
22 *
23 * SPI 0 -> AK4396
24 */
25
20#include <linux/delay.h> 26#include <linux/delay.h>
21#include <linux/pci.h> 27#include <linux/pci.h>
22#include <sound/control.h> 28#include <sound/control.h>
@@ -51,23 +57,28 @@ static struct pci_device_id hifier_ids[] __devinitdata = {
51MODULE_DEVICE_TABLE(pci, hifier_ids); 57MODULE_DEVICE_TABLE(pci, hifier_ids);
52 58
53struct hifier_data { 59struct hifier_data {
54 u8 ak4396_ctl2; 60 u8 ak4396_regs[5];
55}; 61};
56 62
57static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) 63static void ak4396_write(struct oxygen *chip, u8 reg, u8 value)
58{ 64{
65 struct hifier_data *data = chip->model_data;
66
59 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 67 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
60 OXYGEN_SPI_DATA_LENGTH_2 | 68 OXYGEN_SPI_DATA_LENGTH_2 |
61 OXYGEN_SPI_CLOCK_160 | 69 OXYGEN_SPI_CLOCK_160 |
62 (0 << OXYGEN_SPI_CODEC_SHIFT) | 70 (0 << OXYGEN_SPI_CODEC_SHIFT) |
63 OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 71 OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
64 AK4396_WRITE | (reg << 8) | value); 72 AK4396_WRITE | (reg << 8) | value);
73 data->ak4396_regs[reg] = value;
65} 74}
66 75
67static void update_ak4396_volume(struct oxygen *chip) 76static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value)
68{ 77{
69 ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); 78 struct hifier_data *data = chip->model_data;
70 ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); 79
80 if (value != data->ak4396_regs[reg])
81 ak4396_write(chip, reg, value);
71} 82}
72 83
73static void hifier_registers_init(struct oxygen *chip) 84static void hifier_registers_init(struct oxygen *chip)
@@ -75,16 +86,19 @@ static void hifier_registers_init(struct oxygen *chip)
75 struct hifier_data *data = chip->model_data; 86 struct hifier_data *data = chip->model_data;
76 87
77 ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); 88 ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
78 ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2); 89 ak4396_write(chip, AK4396_CONTROL_2,
90 data->ak4396_regs[AK4396_CONTROL_2]);
79 ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); 91 ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
80 update_ak4396_volume(chip); 92 ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
93 ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
81} 94}
82 95
83static void hifier_init(struct oxygen *chip) 96static void hifier_init(struct oxygen *chip)
84{ 97{
85 struct hifier_data *data = chip->model_data; 98 struct hifier_data *data = chip->model_data;
86 99
87 data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; 100 data->ak4396_regs[AK4396_CONTROL_2] =
101 AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
88 hifier_registers_init(chip); 102 hifier_registers_init(chip);
89 103
90 snd_component_add(chip->card, "AK4396"); 104 snd_component_add(chip->card, "AK4396");
@@ -106,20 +120,29 @@ static void set_ak4396_params(struct oxygen *chip,
106 struct hifier_data *data = chip->model_data; 120 struct hifier_data *data = chip->model_data;
107 u8 value; 121 u8 value;
108 122
109 value = data->ak4396_ctl2 & ~AK4396_DFS_MASK; 123 value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK;
110 if (params_rate(params) <= 54000) 124 if (params_rate(params) <= 54000)
111 value |= AK4396_DFS_NORMAL; 125 value |= AK4396_DFS_NORMAL;
112 else if (params_rate(params) <= 108000) 126 else if (params_rate(params) <= 108000)
113 value |= AK4396_DFS_DOUBLE; 127 value |= AK4396_DFS_DOUBLE;
114 else 128 else
115 value |= AK4396_DFS_QUAD; 129 value |= AK4396_DFS_QUAD;
116 data->ak4396_ctl2 = value;
117 130
118 msleep(1); /* wait for the new MCLK to become stable */ 131 msleep(1); /* wait for the new MCLK to become stable */
119 132
120 ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB); 133 if (value != data->ak4396_regs[AK4396_CONTROL_2]) {
121 ak4396_write(chip, AK4396_CONTROL_2, value); 134 ak4396_write(chip, AK4396_CONTROL_1,
122 ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); 135 AK4396_DIF_24_MSB);
136 ak4396_write(chip, AK4396_CONTROL_2, value);
137 ak4396_write(chip, AK4396_CONTROL_1,
138 AK4396_DIF_24_MSB | AK4396_RSTN);
139 }
140}
141
142static void update_ak4396_volume(struct oxygen *chip)
143{
144 ak4396_write_cached(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
145 ak4396_write_cached(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
123} 146}
124 147
125static void update_ak4396_mute(struct oxygen *chip) 148static void update_ak4396_mute(struct oxygen *chip)
@@ -127,11 +150,10 @@ static void update_ak4396_mute(struct oxygen *chip)
127 struct hifier_data *data = chip->model_data; 150 struct hifier_data *data = chip->model_data;
128 u8 value; 151 u8 value;
129 152
130 value = data->ak4396_ctl2 & ~AK4396_SMUTE; 153 value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE;
131 if (chip->dac_mute) 154 if (chip->dac_mute)
132 value |= AK4396_SMUTE; 155 value |= AK4396_SMUTE;
133 data->ak4396_ctl2 = value; 156 ak4396_write_cached(chip, AK4396_CONTROL_2, value);
134 ak4396_write(chip, AK4396_CONTROL_2, value);
135} 157}
136 158
137static void set_cs5340_params(struct oxygen *chip, 159static void set_cs5340_params(struct oxygen *chip,
@@ -141,21 +163,14 @@ static void set_cs5340_params(struct oxygen *chip,
141 163
142static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); 164static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
143 165
144static int hifier_control_filter(struct snd_kcontrol_new *template)
145{
146 if (!strcmp(template->name, "Stereo Upmixing"))
147 return 1; /* stereo only - we don't need upmixing */
148 return 0;
149}
150
151static const struct oxygen_model model_hifier = { 166static const struct oxygen_model model_hifier = {
152 .shortname = "C-Media CMI8787", 167 .shortname = "C-Media CMI8787",
153 .longname = "C-Media Oxygen HD Audio", 168 .longname = "C-Media Oxygen HD Audio",
154 .chip = "CMI8788", 169 .chip = "CMI8788",
155 .init = hifier_init, 170 .init = hifier_init,
156 .control_filter = hifier_control_filter,
157 .cleanup = hifier_cleanup, 171 .cleanup = hifier_cleanup,
158 .resume = hifier_resume, 172 .resume = hifier_resume,
173 .get_i2s_mclk = oxygen_default_i2s_mclk,
159 .set_dac_params = set_ak4396_params, 174 .set_dac_params = set_ak4396_params,
160 .set_adc_params = set_cs5340_params, 175 .set_adc_params = set_cs5340_params,
161 .update_dac_volume = update_ak4396_volume, 176 .update_dac_volume = update_ak4396_volume,
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 72db4c39007f..acbedebcffd9 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -18,6 +18,8 @@
18 */ 18 */
19 19
20/* 20/*
21 * CMI8788:
22 *
21 * SPI 0 -> 1st AK4396 (front) 23 * SPI 0 -> 1st AK4396 (front)
22 * SPI 1 -> 2nd AK4396 (surround) 24 * SPI 1 -> 2nd AK4396 (surround)
23 * SPI 2 -> 3rd AK4396 (center/LFE) 25 * SPI 2 -> 3rd AK4396 (center/LFE)
@@ -27,6 +29,10 @@
27 * GPIO 0 -> DFS0 of AK5385 29 * GPIO 0 -> DFS0 of AK5385
28 * GPIO 1 -> DFS1 of AK5385 30 * GPIO 1 -> DFS1 of AK5385
29 * GPIO 8 -> enable headphone amplifier on HT-Omega models 31 * GPIO 8 -> enable headphone amplifier on HT-Omega models
32 *
33 * CM9780:
34 *
35 * GPO 0 -> route line-in (0) or AC97 output (1) to ADC input
30 */ 36 */
31 37
32#include <linux/delay.h> 38#include <linux/delay.h>
@@ -91,8 +97,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
91#define GPIO_CLARO_HP 0x0100 97#define GPIO_CLARO_HP 0x0100
92 98
93struct generic_data { 99struct generic_data {
94 u8 ak4396_ctl2; 100 u8 ak4396_regs[4][5];
95 u16 saved_wm8785_registers[2]; 101 u16 wm8785_regs[3];
96}; 102};
97 103
98static void ak4396_write(struct oxygen *chip, unsigned int codec, 104static void ak4396_write(struct oxygen *chip, unsigned int codec,
@@ -102,12 +108,24 @@ static void ak4396_write(struct oxygen *chip, unsigned int codec,
102 static const u8 codec_spi_map[4] = { 108 static const u8 codec_spi_map[4] = {
103 0, 1, 2, 4 109 0, 1, 2, 4
104 }; 110 };
111 struct generic_data *data = chip->model_data;
112
105 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 113 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
106 OXYGEN_SPI_DATA_LENGTH_2 | 114 OXYGEN_SPI_DATA_LENGTH_2 |
107 OXYGEN_SPI_CLOCK_160 | 115 OXYGEN_SPI_CLOCK_160 |
108 (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | 116 (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
109 OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 117 OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
110 AK4396_WRITE | (reg << 8) | value); 118 AK4396_WRITE | (reg << 8) | value);
119 data->ak4396_regs[codec][reg] = value;
120}
121
122static void ak4396_write_cached(struct oxygen *chip, unsigned int codec,
123 u8 reg, u8 value)
124{
125 struct generic_data *data = chip->model_data;
126
127 if (value != data->ak4396_regs[codec][reg])
128 ak4396_write(chip, codec, reg, value);
111} 129}
112 130
113static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) 131static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value)
@@ -120,20 +138,8 @@ static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value)
120 (3 << OXYGEN_SPI_CODEC_SHIFT) | 138 (3 << OXYGEN_SPI_CODEC_SHIFT) |
121 OXYGEN_SPI_CEN_LATCH_CLOCK_LO, 139 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
122 (reg << 9) | value); 140 (reg << 9) | value);
123 if (reg < ARRAY_SIZE(data->saved_wm8785_registers)) 141 if (reg < ARRAY_SIZE(data->wm8785_regs))
124 data->saved_wm8785_registers[reg] = value; 142 data->wm8785_regs[reg] = value;
125}
126
127static void update_ak4396_volume(struct oxygen *chip)
128{
129 unsigned int i;
130
131 for (i = 0; i < 4; ++i) {
132 ak4396_write(chip, i,
133 AK4396_LCH_ATT, chip->dac_volume[i * 2]);
134 ak4396_write(chip, i,
135 AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]);
136 }
137} 143}
138 144
139static void ak4396_registers_init(struct oxygen *chip) 145static void ak4396_registers_init(struct oxygen *chip)
@@ -142,21 +148,25 @@ static void ak4396_registers_init(struct oxygen *chip)
142 unsigned int i; 148 unsigned int i;
143 149
144 for (i = 0; i < 4; ++i) { 150 for (i = 0; i < 4; ++i) {
145 ak4396_write(chip, i, 151 ak4396_write(chip, i, AK4396_CONTROL_1,
146 AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); 152 AK4396_DIF_24_MSB | AK4396_RSTN);
147 ak4396_write(chip, i, 153 ak4396_write(chip, i, AK4396_CONTROL_2,
148 AK4396_CONTROL_2, data->ak4396_ctl2); 154 data->ak4396_regs[0][AK4396_CONTROL_2]);
149 ak4396_write(chip, i, 155 ak4396_write(chip, i, AK4396_CONTROL_3,
150 AK4396_CONTROL_3, AK4396_PCM); 156 AK4396_PCM);
157 ak4396_write(chip, i, AK4396_LCH_ATT,
158 chip->dac_volume[i * 2]);
159 ak4396_write(chip, i, AK4396_RCH_ATT,
160 chip->dac_volume[i * 2 + 1]);
151 } 161 }
152 update_ak4396_volume(chip);
153} 162}
154 163
155static void ak4396_init(struct oxygen *chip) 164static void ak4396_init(struct oxygen *chip)
156{ 165{
157 struct generic_data *data = chip->model_data; 166 struct generic_data *data = chip->model_data;
158 167
159 data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; 168 data->ak4396_regs[0][AK4396_CONTROL_2] =
169 AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
160 ak4396_registers_init(chip); 170 ak4396_registers_init(chip);
161 snd_component_add(chip->card, "AK4396"); 171 snd_component_add(chip->card, "AK4396");
162} 172}
@@ -173,17 +183,17 @@ static void wm8785_registers_init(struct oxygen *chip)
173 struct generic_data *data = chip->model_data; 183 struct generic_data *data = chip->model_data;
174 184
175 wm8785_write(chip, WM8785_R7, 0); 185 wm8785_write(chip, WM8785_R7, 0);
176 wm8785_write(chip, WM8785_R0, data->saved_wm8785_registers[0]); 186 wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]);
177 wm8785_write(chip, WM8785_R1, data->saved_wm8785_registers[1]); 187 wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]);
178} 188}
179 189
180static void wm8785_init(struct oxygen *chip) 190static void wm8785_init(struct oxygen *chip)
181{ 191{
182 struct generic_data *data = chip->model_data; 192 struct generic_data *data = chip->model_data;
183 193
184 data->saved_wm8785_registers[0] = WM8785_MCR_SLAVE | 194 data->wm8785_regs[0] =
185 WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; 195 WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST;
186 data->saved_wm8785_registers[1] = WM8785_WL_24; 196 data->wm8785_regs[2] = WM8785_HPFR | WM8785_HPFL;
187 wm8785_registers_init(chip); 197 wm8785_registers_init(chip);
188 snd_component_add(chip->card, "WM8785"); 198 snd_component_add(chip->card, "WM8785");
189} 199}
@@ -264,24 +274,36 @@ static void set_ak4396_params(struct oxygen *chip,
264 unsigned int i; 274 unsigned int i;
265 u8 value; 275 u8 value;
266 276
267 value = data->ak4396_ctl2 & ~AK4396_DFS_MASK; 277 value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK;
268 if (params_rate(params) <= 54000) 278 if (params_rate(params) <= 54000)
269 value |= AK4396_DFS_NORMAL; 279 value |= AK4396_DFS_NORMAL;
270 else if (params_rate(params) <= 108000) 280 else if (params_rate(params) <= 108000)
271 value |= AK4396_DFS_DOUBLE; 281 value |= AK4396_DFS_DOUBLE;
272 else 282 else
273 value |= AK4396_DFS_QUAD; 283 value |= AK4396_DFS_QUAD;
274 data->ak4396_ctl2 = value;
275 284
276 msleep(1); /* wait for the new MCLK to become stable */ 285 msleep(1); /* wait for the new MCLK to become stable */
277 286
287 if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) {
288 for (i = 0; i < 4; ++i) {
289 ak4396_write(chip, i, AK4396_CONTROL_1,
290 AK4396_DIF_24_MSB);
291 ak4396_write(chip, i, AK4396_CONTROL_2, value);
292 ak4396_write(chip, i, AK4396_CONTROL_1,
293 AK4396_DIF_24_MSB | AK4396_RSTN);
294 }
295 }
296}
297
298static void update_ak4396_volume(struct oxygen *chip)
299{
300 unsigned int i;
301
278 for (i = 0; i < 4; ++i) { 302 for (i = 0; i < 4; ++i) {
279 ak4396_write(chip, i, 303 ak4396_write_cached(chip, i, AK4396_LCH_ATT,
280 AK4396_CONTROL_1, AK4396_DIF_24_MSB); 304 chip->dac_volume[i * 2]);
281 ak4396_write(chip, i, 305 ak4396_write_cached(chip, i, AK4396_RCH_ATT,
282 AK4396_CONTROL_2, value); 306 chip->dac_volume[i * 2 + 1]);
283 ak4396_write(chip, i,
284 AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
285 } 307 }
286} 308}
287 309
@@ -291,21 +313,19 @@ static void update_ak4396_mute(struct oxygen *chip)
291 unsigned int i; 313 unsigned int i;
292 u8 value; 314 u8 value;
293 315
294 value = data->ak4396_ctl2 & ~AK4396_SMUTE; 316 value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE;
295 if (chip->dac_mute) 317 if (chip->dac_mute)
296 value |= AK4396_SMUTE; 318 value |= AK4396_SMUTE;
297 data->ak4396_ctl2 = value;
298 for (i = 0; i < 4; ++i) 319 for (i = 0; i < 4; ++i)
299 ak4396_write(chip, i, AK4396_CONTROL_2, value); 320 ak4396_write_cached(chip, i, AK4396_CONTROL_2, value);
300} 321}
301 322
302static void set_wm8785_params(struct oxygen *chip, 323static void set_wm8785_params(struct oxygen *chip,
303 struct snd_pcm_hw_params *params) 324 struct snd_pcm_hw_params *params)
304{ 325{
326 struct generic_data *data = chip->model_data;
305 unsigned int value; 327 unsigned int value;
306 328
307 wm8785_write(chip, WM8785_R7, 0);
308
309 value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; 329 value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST;
310 if (params_rate(params) <= 48000) 330 if (params_rate(params) <= 48000)
311 value |= WM8785_OSR_SINGLE; 331 value |= WM8785_OSR_SINGLE;
@@ -313,13 +333,11 @@ static void set_wm8785_params(struct oxygen *chip,
313 value |= WM8785_OSR_DOUBLE; 333 value |= WM8785_OSR_DOUBLE;
314 else 334 else
315 value |= WM8785_OSR_QUAD; 335 value |= WM8785_OSR_QUAD;
316 wm8785_write(chip, WM8785_R0, value); 336 if (value != data->wm8785_regs[0]) {
317 337 wm8785_write(chip, WM8785_R7, 0);
318 if (snd_pcm_format_width(params_format(params)) <= 16) 338 wm8785_write(chip, WM8785_R0, value);
319 value = WM8785_WL_16; 339 wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]);
320 else 340 }
321 value = WM8785_WL_24;
322 wm8785_write(chip, WM8785_R1, value);
323} 341}
324 342
325static void set_ak5385_params(struct oxygen *chip, 343static void set_ak5385_params(struct oxygen *chip,
@@ -337,6 +355,134 @@ static void set_ak5385_params(struct oxygen *chip,
337 value, GPIO_AK5385_DFS_MASK); 355 value, GPIO_AK5385_DFS_MASK);
338} 356}
339 357
358static int rolloff_info(struct snd_kcontrol *ctl,
359 struct snd_ctl_elem_info *info)
360{
361 static const char *const names[2] = {
362 "Sharp Roll-off", "Slow Roll-off"
363 };
364
365 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
366 info->count = 1;
367 info->value.enumerated.items = 2;
368 if (info->value.enumerated.item >= 2)
369 info->value.enumerated.item = 1;
370 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
371 return 0;
372}
373
374static int rolloff_get(struct snd_kcontrol *ctl,
375 struct snd_ctl_elem_value *value)
376{
377 struct oxygen *chip = ctl->private_data;
378 struct generic_data *data = chip->model_data;
379
380 value->value.enumerated.item[0] =
381 (data->ak4396_regs[0][AK4396_CONTROL_2] & AK4396_SLOW) != 0;
382 return 0;
383}
384
385static int rolloff_put(struct snd_kcontrol *ctl,
386 struct snd_ctl_elem_value *value)
387{
388 struct oxygen *chip = ctl->private_data;
389 struct generic_data *data = chip->model_data;
390 unsigned int i;
391 int changed;
392 u8 reg;
393
394 mutex_lock(&chip->mutex);
395 reg = data->ak4396_regs[0][AK4396_CONTROL_2];
396 if (value->value.enumerated.item[0])
397 reg |= AK4396_SLOW;
398 else
399 reg &= ~AK4396_SLOW;
400 changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2];
401 if (changed) {
402 for (i = 0; i < 4; ++i)
403 ak4396_write(chip, i, AK4396_CONTROL_2, reg);
404 }
405 mutex_unlock(&chip->mutex);
406 return changed;
407}
408
409static const struct snd_kcontrol_new rolloff_control = {
410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
411 .name = "DAC Filter Playback Enum",
412 .info = rolloff_info,
413 .get = rolloff_get,
414 .put = rolloff_put,
415};
416
417static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
418{
419 static const char *const names[2] = {
420 "None", "High-pass Filter"
421 };
422
423 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
424 info->count = 1;
425 info->value.enumerated.items = 2;
426 if (info->value.enumerated.item >= 2)
427 info->value.enumerated.item = 1;
428 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
429 return 0;
430}
431
432static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
433{
434 struct oxygen *chip = ctl->private_data;
435 struct generic_data *data = chip->model_data;
436
437 value->value.enumerated.item[0] =
438 (data->wm8785_regs[WM8785_R2] & WM8785_HPFR) != 0;
439 return 0;
440}
441
442static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
443{
444 struct oxygen *chip = ctl->private_data;
445 struct generic_data *data = chip->model_data;
446 unsigned int reg;
447 int changed;
448
449 mutex_lock(&chip->mutex);
450 reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL);
451 if (value->value.enumerated.item[0])
452 reg |= WM8785_HPFR | WM8785_HPFL;
453 changed = reg != data->wm8785_regs[WM8785_R2];
454 if (changed)
455 wm8785_write(chip, WM8785_R2, reg);
456 mutex_unlock(&chip->mutex);
457 return changed;
458}
459
460static const struct snd_kcontrol_new hpf_control = {
461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
462 .name = "ADC Filter Capture Enum",
463 .info = hpf_info,
464 .get = hpf_get,
465 .put = hpf_put,
466};
467
468static int generic_mixer_init(struct oxygen *chip)
469{
470 return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip));
471}
472
473static int generic_wm8785_mixer_init(struct oxygen *chip)
474{
475 int err;
476
477 err = generic_mixer_init(chip);
478 if (err < 0)
479 return err;
480 err = snd_ctl_add(chip->card, snd_ctl_new1(&hpf_control, chip));
481 if (err < 0)
482 return err;
483 return 0;
484}
485
340static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); 486static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
341 487
342static const struct oxygen_model model_generic = { 488static const struct oxygen_model model_generic = {
@@ -344,8 +490,10 @@ static const struct oxygen_model model_generic = {
344 .longname = "C-Media Oxygen HD Audio", 490 .longname = "C-Media Oxygen HD Audio",
345 .chip = "CMI8788", 491 .chip = "CMI8788",
346 .init = generic_init, 492 .init = generic_init,
493 .mixer_init = generic_wm8785_mixer_init,
347 .cleanup = generic_cleanup, 494 .cleanup = generic_cleanup,
348 .resume = generic_resume, 495 .resume = generic_resume,
496 .get_i2s_mclk = oxygen_default_i2s_mclk,
349 .set_dac_params = set_ak4396_params, 497 .set_dac_params = set_ak4396_params,
350 .set_adc_params = set_wm8785_params, 498 .set_adc_params = set_wm8785_params,
351 .update_dac_volume = update_ak4396_volume, 499 .update_dac_volume = update_ak4396_volume,
@@ -374,6 +522,7 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
374 switch (id->driver_data) { 522 switch (id->driver_data) {
375 case MODEL_MERIDIAN: 523 case MODEL_MERIDIAN:
376 chip->model.init = meridian_init; 524 chip->model.init = meridian_init;
525 chip->model.mixer_init = generic_mixer_init;
377 chip->model.resume = meridian_resume; 526 chip->model.resume = meridian_resume;
378 chip->model.set_adc_params = set_ak5385_params; 527 chip->model.set_adc_params = set_ak5385_params;
379 chip->model.device_config = PLAYBACK_0_TO_I2S | 528 chip->model.device_config = PLAYBACK_0_TO_I2S |
@@ -389,6 +538,7 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
389 break; 538 break;
390 case MODEL_CLARO_HALO: 539 case MODEL_CLARO_HALO:
391 chip->model.init = claro_halo_init; 540 chip->model.init = claro_halo_init;
541 chip->model.mixer_init = generic_mixer_init;
392 chip->model.cleanup = claro_cleanup; 542 chip->model.cleanup = claro_cleanup;
393 chip->model.suspend = claro_suspend; 543 chip->model.suspend = claro_suspend;
394 chip->model.resume = claro_resume; 544 chip->model.resume = claro_resume;
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index bd615dbffadb..6147216af744 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -78,12 +78,15 @@ struct oxygen_model {
78 void (*resume)(struct oxygen *chip); 78 void (*resume)(struct oxygen *chip);
79 void (*pcm_hardware_filter)(unsigned int channel, 79 void (*pcm_hardware_filter)(unsigned int channel,
80 struct snd_pcm_hardware *hardware); 80 struct snd_pcm_hardware *hardware);
81 unsigned int (*get_i2s_mclk)(struct oxygen *chip, unsigned int channel,
82 struct snd_pcm_hw_params *hw_params);
81 void (*set_dac_params)(struct oxygen *chip, 83 void (*set_dac_params)(struct oxygen *chip,
82 struct snd_pcm_hw_params *params); 84 struct snd_pcm_hw_params *params);
83 void (*set_adc_params)(struct oxygen *chip, 85 void (*set_adc_params)(struct oxygen *chip,
84 struct snd_pcm_hw_params *params); 86 struct snd_pcm_hw_params *params);
85 void (*update_dac_volume)(struct oxygen *chip); 87 void (*update_dac_volume)(struct oxygen *chip);
86 void (*update_dac_mute)(struct oxygen *chip); 88 void (*update_dac_mute)(struct oxygen *chip);
89 void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed);
87 void (*gpio_changed)(struct oxygen *chip); 90 void (*gpio_changed)(struct oxygen *chip);
88 void (*uart_input)(struct oxygen *chip); 91 void (*uart_input)(struct oxygen *chip);
89 void (*ac97_switch)(struct oxygen *chip, 92 void (*ac97_switch)(struct oxygen *chip,
@@ -162,6 +165,8 @@ void oxygen_update_spdif_source(struct oxygen *chip);
162/* oxygen_pcm.c */ 165/* oxygen_pcm.c */
163 166
164int oxygen_pcm_init(struct oxygen *chip); 167int oxygen_pcm_init(struct oxygen *chip);
168unsigned int oxygen_default_i2s_mclk(struct oxygen *chip, unsigned int channel,
169 struct snd_pcm_hw_params *hw_params);
165 170
166/* oxygen_io.c */ 171/* oxygen_io.c */
167 172
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 9a8936e20744..9c5e6450eebb 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -278,7 +278,11 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
278static void oxygen_restore_eeprom(struct oxygen *chip, 278static void oxygen_restore_eeprom(struct oxygen *chip,
279 const struct pci_device_id *id) 279 const struct pci_device_id *id)
280{ 280{
281 if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) { 281 u16 eeprom_id;
282
283 eeprom_id = oxygen_read_eeprom(chip, 0);
284 if (eeprom_id != OXYGEN_EEPROM_ID &&
285 (eeprom_id != 0xffff || id->subdevice != 0x8788)) {
282 /* 286 /*
283 * This function gets called only when a known card model has 287 * This function gets called only when a known card model has
284 * been detected, i.e., we know there is a valid subsystem 288 * been detected, i.e., we know there is a valid subsystem
@@ -303,6 +307,28 @@ static void oxygen_restore_eeprom(struct oxygen *chip,
303 } 307 }
304} 308}
305 309
310static void pci_bridge_magic(void)
311{
312 struct pci_dev *pci = NULL;
313 u32 tmp;
314
315 for (;;) {
316 /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */
317 pci = pci_get_device(0x12d8, 0xe110, pci);
318 if (!pci)
319 break;
320 /*
321 * ... configure its secondary internal arbiter to park to
322 * the secondary port, instead of to the last master.
323 */
324 if (!pci_read_config_dword(pci, 0x40, &tmp)) {
325 tmp |= 1;
326 pci_write_config_dword(pci, 0x40, tmp);
327 }
328 /* Why? Try asking C-Media. */
329 }
330}
331
306static void oxygen_init(struct oxygen *chip) 332static void oxygen_init(struct oxygen *chip)
307{ 333{
308 unsigned int i; 334 unsigned int i;
@@ -581,6 +607,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
581 snd_card_set_dev(card, &pci->dev); 607 snd_card_set_dev(card, &pci->dev);
582 card->private_free = oxygen_card_free; 608 card->private_free = oxygen_card_free;
583 609
610 pci_bridge_magic();
584 oxygen_init(chip); 611 oxygen_init(chip);
585 chip->model.init(chip); 612 chip->model.init(chip);
586 613
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 5401c547c4e3..f375b8a27862 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -99,11 +99,15 @@ static int dac_mute_put(struct snd_kcontrol *ctl,
99 99
100static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) 100static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
101{ 101{
102 static const char *const names[3] = { 102 static const char *const names[5] = {
103 "Front", "Front+Surround", "Front+Surround+Back" 103 "Front",
104 "Front+Surround",
105 "Front+Surround+Back",
106 "Front+Surround+Center/LFE",
107 "Front+Surround+Center/LFE+Back",
104 }; 108 };
105 struct oxygen *chip = ctl->private_data; 109 struct oxygen *chip = ctl->private_data;
106 unsigned int count = 2 + (chip->model.dac_channels == 8); 110 unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3;
107 111
108 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 112 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
109 info->count = 1; 113 info->count = 1;
@@ -127,7 +131,7 @@ static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
127void oxygen_update_dac_routing(struct oxygen *chip) 131void oxygen_update_dac_routing(struct oxygen *chip)
128{ 132{
129 /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */ 133 /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */
130 static const unsigned int reg_values[3] = { 134 static const unsigned int reg_values[5] = {
131 /* stereo -> front */ 135 /* stereo -> front */
132 (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | 136 (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |
133 (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | 137 (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
@@ -143,6 +147,16 @@ void oxygen_update_dac_routing(struct oxygen *chip)
143 (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | 147 (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
144 (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | 148 (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
145 (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), 149 (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),
150 /* stereo -> front+surround+center/LFE */
151 (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |
152 (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
153 (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
154 (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),
155 /* stereo -> front+surround+center/LFE+back */
156 (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |
157 (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
158 (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
159 (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),
146 }; 160 };
147 u8 channels; 161 u8 channels;
148 unsigned int reg_value; 162 unsigned int reg_value;
@@ -167,22 +181,23 @@ void oxygen_update_dac_routing(struct oxygen *chip)
167 OXYGEN_PLAY_DAC1_SOURCE_MASK | 181 OXYGEN_PLAY_DAC1_SOURCE_MASK |
168 OXYGEN_PLAY_DAC2_SOURCE_MASK | 182 OXYGEN_PLAY_DAC2_SOURCE_MASK |
169 OXYGEN_PLAY_DAC3_SOURCE_MASK); 183 OXYGEN_PLAY_DAC3_SOURCE_MASK);
184 if (chip->model.update_center_lfe_mix)
185 chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2);
170} 186}
171 187
172static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) 188static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
173{ 189{
174 struct oxygen *chip = ctl->private_data; 190 struct oxygen *chip = ctl->private_data;
175 unsigned int count = 2 + (chip->model.dac_channels == 8); 191 unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3;
176 int changed; 192 int changed;
177 193
194 if (value->value.enumerated.item[0] >= count)
195 return -EINVAL;
178 mutex_lock(&chip->mutex); 196 mutex_lock(&chip->mutex);
179 changed = value->value.enumerated.item[0] != chip->dac_routing; 197 changed = value->value.enumerated.item[0] != chip->dac_routing;
180 if (changed) { 198 if (changed) {
181 chip->dac_routing = min(value->value.enumerated.item[0], 199 chip->dac_routing = value->value.enumerated.item[0];
182 count - 1);
183 spin_lock_irq(&chip->reg_lock);
184 oxygen_update_dac_routing(chip); 200 oxygen_update_dac_routing(chip);
185 spin_unlock_irq(&chip->reg_lock);
186 } 201 }
187 mutex_unlock(&chip->mutex); 202 mutex_unlock(&chip->mutex);
188 return changed; 203 return changed;
@@ -790,7 +805,7 @@ static const struct {
790 .controls = { 805 .controls = {
791 { 806 {
792 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
793 .name = "Analog Input Monitor Switch", 808 .name = "Analog Input Monitor Playback Switch",
794 .info = snd_ctl_boolean_mono_info, 809 .info = snd_ctl_boolean_mono_info,
795 .get = monitor_get, 810 .get = monitor_get,
796 .put = monitor_put, 811 .put = monitor_put,
@@ -798,7 +813,7 @@ static const struct {
798 }, 813 },
799 { 814 {
800 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 815 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
801 .name = "Analog Input Monitor Volume", 816 .name = "Analog Input Monitor Playback Volume",
802 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 817 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
803 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 818 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
804 .info = monitor_volume_info, 819 .info = monitor_volume_info,
@@ -815,7 +830,7 @@ static const struct {
815 .controls = { 830 .controls = {
816 { 831 {
817 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 832 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
818 .name = "Analog Input Monitor Switch", 833 .name = "Analog Input Monitor Playback Switch",
819 .info = snd_ctl_boolean_mono_info, 834 .info = snd_ctl_boolean_mono_info,
820 .get = monitor_get, 835 .get = monitor_get,
821 .put = monitor_put, 836 .put = monitor_put,
@@ -823,7 +838,7 @@ static const struct {
823 }, 838 },
824 { 839 {
825 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 840 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
826 .name = "Analog Input Monitor Volume", 841 .name = "Analog Input Monitor Playback Volume",
827 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 842 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
828 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 843 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
829 .info = monitor_volume_info, 844 .info = monitor_volume_info,
@@ -840,7 +855,7 @@ static const struct {
840 .controls = { 855 .controls = {
841 { 856 {
842 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 857 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
843 .name = "Analog Input Monitor Switch", 858 .name = "Analog Input Monitor Playback Switch",
844 .index = 1, 859 .index = 1,
845 .info = snd_ctl_boolean_mono_info, 860 .info = snd_ctl_boolean_mono_info,
846 .get = monitor_get, 861 .get = monitor_get,
@@ -849,7 +864,7 @@ static const struct {
849 }, 864 },
850 { 865 {
851 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 866 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
852 .name = "Analog Input Monitor Volume", 867 .name = "Analog Input Monitor Playback Volume",
853 .index = 1, 868 .index = 1,
854 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 869 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
855 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 870 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -867,7 +882,7 @@ static const struct {
867 .controls = { 882 .controls = {
868 { 883 {
869 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
870 .name = "Digital Input Monitor Switch", 885 .name = "Digital Input Monitor Playback Switch",
871 .info = snd_ctl_boolean_mono_info, 886 .info = snd_ctl_boolean_mono_info,
872 .get = monitor_get, 887 .get = monitor_get,
873 .put = monitor_put, 888 .put = monitor_put,
@@ -875,7 +890,7 @@ static const struct {
875 }, 890 },
876 { 891 {
877 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 892 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
878 .name = "Digital Input Monitor Volume", 893 .name = "Digital Input Monitor Playback Volume",
879 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 894 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
880 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 895 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
881 .info = monitor_volume_info, 896 .info = monitor_volume_info,
@@ -954,6 +969,9 @@ static int add_controls(struct oxygen *chip,
954 if (err == 1) 969 if (err == 1)
955 continue; 970 continue;
956 } 971 }
972 if (!strcmp(template.name, "Stereo Upmixing") &&
973 chip->model.dac_channels == 2)
974 continue;
957 if (!strcmp(template.name, "Master Playback Volume") && 975 if (!strcmp(template.name, "Master Playback Volume") &&
958 chip->model.dac_tlv) { 976 chip->model.dac_tlv) {
959 template.tlv.p = chip->model.dac_tlv; 977 template.tlv.p = chip->model.dac_tlv;
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index ef2345d82b86..9dff6954c397 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -271,13 +271,16 @@ static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params)
271 } 271 }
272} 272}
273 273
274static unsigned int oxygen_i2s_mclk(struct snd_pcm_hw_params *hw_params) 274unsigned int oxygen_default_i2s_mclk(struct oxygen *chip,
275 unsigned int channel,
276 struct snd_pcm_hw_params *hw_params)
275{ 277{
276 if (params_rate(hw_params) <= 96000) 278 if (params_rate(hw_params) <= 96000)
277 return OXYGEN_I2S_MCLK_256; 279 return OXYGEN_I2S_MCLK_256;
278 else 280 else
279 return OXYGEN_I2S_MCLK_128; 281 return OXYGEN_I2S_MCLK_128;
280} 282}
283EXPORT_SYMBOL(oxygen_default_i2s_mclk);
281 284
282static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) 285static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params)
283{ 286{
@@ -354,7 +357,7 @@ static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream,
354 OXYGEN_REC_FORMAT_A_MASK); 357 OXYGEN_REC_FORMAT_A_MASK);
355 oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, 358 oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT,
356 oxygen_rate(hw_params) | 359 oxygen_rate(hw_params) |
357 oxygen_i2s_mclk(hw_params) | 360 chip->model.get_i2s_mclk(chip, PCM_A, hw_params) |
358 chip->model.adc_i2s_format | 361 chip->model.adc_i2s_format |
359 oxygen_i2s_bits(hw_params), 362 oxygen_i2s_bits(hw_params),
360 OXYGEN_I2S_RATE_MASK | 363 OXYGEN_I2S_RATE_MASK |
@@ -390,7 +393,8 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
390 if (!is_ac97) 393 if (!is_ac97)
391 oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, 394 oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT,
392 oxygen_rate(hw_params) | 395 oxygen_rate(hw_params) |
393 oxygen_i2s_mclk(hw_params) | 396 chip->model.get_i2s_mclk(chip, PCM_B,
397 hw_params) |
394 chip->model.adc_i2s_format | 398 chip->model.adc_i2s_format |
395 oxygen_i2s_bits(hw_params), 399 oxygen_i2s_bits(hw_params),
396 OXYGEN_I2S_RATE_MASK | 400 OXYGEN_I2S_RATE_MASK |
@@ -435,6 +439,7 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream,
435 if (err < 0) 439 if (err < 0)
436 return err; 440 return err;
437 441
442 mutex_lock(&chip->mutex);
438 spin_lock_irq(&chip->reg_lock); 443 spin_lock_irq(&chip->reg_lock);
439 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, 444 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
440 OXYGEN_SPDIF_OUT_ENABLE); 445 OXYGEN_SPDIF_OUT_ENABLE);
@@ -446,6 +451,7 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream,
446 OXYGEN_SPDIF_OUT_RATE_MASK); 451 OXYGEN_SPDIF_OUT_RATE_MASK);
447 oxygen_update_spdif_source(chip); 452 oxygen_update_spdif_source(chip);
448 spin_unlock_irq(&chip->reg_lock); 453 spin_unlock_irq(&chip->reg_lock);
454 mutex_unlock(&chip->mutex);
449 return 0; 455 return 0;
450} 456}
451 457
@@ -459,6 +465,7 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream,
459 if (err < 0) 465 if (err < 0)
460 return err; 466 return err;
461 467
468 mutex_lock(&chip->mutex);
462 spin_lock_irq(&chip->reg_lock); 469 spin_lock_irq(&chip->reg_lock);
463 oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, 470 oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS,
464 oxygen_play_channels(hw_params), 471 oxygen_play_channels(hw_params),
@@ -469,18 +476,18 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream,
469 oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, 476 oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
470 oxygen_rate(hw_params) | 477 oxygen_rate(hw_params) |
471 chip->model.dac_i2s_format | 478 chip->model.dac_i2s_format |
472 oxygen_i2s_mclk(hw_params) | 479 chip->model.get_i2s_mclk(chip, PCM_MULTICH,
480 hw_params) |
473 oxygen_i2s_bits(hw_params), 481 oxygen_i2s_bits(hw_params),
474 OXYGEN_I2S_RATE_MASK | 482 OXYGEN_I2S_RATE_MASK |
475 OXYGEN_I2S_FORMAT_MASK | 483 OXYGEN_I2S_FORMAT_MASK |
476 OXYGEN_I2S_MCLK_MASK | 484 OXYGEN_I2S_MCLK_MASK |
477 OXYGEN_I2S_BITS_MASK); 485 OXYGEN_I2S_BITS_MASK);
478 oxygen_update_dac_routing(chip);
479 oxygen_update_spdif_source(chip); 486 oxygen_update_spdif_source(chip);
480 spin_unlock_irq(&chip->reg_lock); 487 spin_unlock_irq(&chip->reg_lock);
481 488
482 mutex_lock(&chip->mutex);
483 chip->model.set_dac_params(chip, hw_params); 489 chip->model.set_dac_params(chip, hw_params);
490 oxygen_update_dac_routing(chip);
484 mutex_unlock(&chip->mutex); 491 mutex_unlock(&chip->mutex);
485 return 0; 492 return 0;
486} 493}
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 6ebcb6bdd712..6accaf9580b2 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -17,145 +17,12 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20/*
21 * Xonar D2/D2X
22 * ------------
23 *
24 * CMI8788:
25 *
26 * SPI 0 -> 1st PCM1796 (front)
27 * SPI 1 -> 2nd PCM1796 (surround)
28 * SPI 2 -> 3rd PCM1796 (center/LFE)
29 * SPI 4 -> 4th PCM1796 (back)
30 *
31 * GPIO 2 -> M0 of CS5381
32 * GPIO 3 -> M1 of CS5381
33 * GPIO 5 <- external power present (D2X only)
34 * GPIO 7 -> ALT
35 * GPIO 8 -> enable output to speakers
36 */
37
38/*
39 * Xonar D1/DX
40 * -----------
41 *
42 * CMI8788:
43 *
44 * I²C <-> CS4398 (front)
45 * <-> CS4362A (surround, center/LFE, back)
46 *
47 * GPI 0 <- external power present (DX only)
48 *
49 * GPIO 0 -> enable output to speakers
50 * GPIO 1 -> enable front panel I/O
51 * GPIO 2 -> M0 of CS5361
52 * GPIO 3 -> M1 of CS5361
53 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
54 *
55 * CS4398:
56 *
57 * AD0 <- 1
58 * AD1 <- 1
59 *
60 * CS4362A:
61 *
62 * AD0 <- 0
63 */
64
65/*
66 * Xonar HDAV1.3 (Deluxe)
67 * ----------------------
68 *
69 * CMI8788:
70 *
71 * I²C <-> PCM1796 (front)
72 *
73 * GPI 0 <- external power present
74 *
75 * GPIO 0 -> enable output to speakers
76 * GPIO 2 -> M0 of CS5381
77 * GPIO 3 -> M1 of CS5381
78 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
79 *
80 * TXD -> HDMI controller
81 * RXD <- HDMI controller
82 *
83 * PCM1796 front: AD1,0 <- 0,0
84 *
85 * no daughterboard
86 * ----------------
87 *
88 * GPIO 4 <- 1
89 *
90 * H6 daughterboard
91 * ----------------
92 *
93 * GPIO 4 <- 0
94 * GPIO 5 <- 0
95 *
96 * I²C <-> PCM1796 (surround)
97 * <-> PCM1796 (center/LFE)
98 * <-> PCM1796 (back)
99 *
100 * PCM1796 surround: AD1,0 <- 0,1
101 * PCM1796 center/LFE: AD1,0 <- 1,0
102 * PCM1796 back: AD1,0 <- 1,1
103 *
104 * unknown daughterboard
105 * ---------------------
106 *
107 * GPIO 4 <- 0
108 * GPIO 5 <- 1
109 *
110 * I²C <-> CS4362A (surround, center/LFE, back)
111 *
112 * CS4362A: AD0 <- 0
113 */
114
115/*
116 * Xonar Essence ST (Deluxe)/STX
117 * -----------------------------
118 *
119 * CMI8788:
120 *
121 * I²C <-> PCM1792A
122 *
123 * GPI 0 <- external power present
124 *
125 * GPIO 0 -> enable output to speakers
126 * GPIO 1 -> route HP to front panel (0) or rear jack (1)
127 * GPIO 2 -> M0 of CS5381
128 * GPIO 3 -> M1 of CS5381
129 * GPIO 7 -> route output to speaker jacks (0) or HP (1)
130 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
131 *
132 * PCM1792A:
133 *
134 * AD0 <- 0
135 *
136 * H6 daughterboard
137 * ----------------
138 *
139 * GPIO 4 <- 0
140 * GPIO 5 <- 0
141 */
142
143#include <linux/pci.h> 20#include <linux/pci.h>
144#include <linux/delay.h> 21#include <linux/delay.h>
145#include <linux/mutex.h>
146#include <sound/ac97_codec.h>
147#include <sound/asoundef.h>
148#include <sound/control.h>
149#include <sound/core.h> 22#include <sound/core.h>
150#include <sound/initval.h> 23#include <sound/initval.h>
151#include <sound/pcm.h> 24#include <sound/pcm.h>
152#include <sound/pcm_params.h> 25#include "xonar.h"
153#include <sound/tlv.h>
154#include "oxygen.h"
155#include "cm9780.h"
156#include "pcm1796.h"
157#include "cs4398.h"
158#include "cs4362a.h"
159 26
160MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 27MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
161MODULE_DESCRIPTION("Asus AVx00 driver"); 28MODULE_DESCRIPTION("Asus AVx00 driver");
@@ -173,972 +40,28 @@ MODULE_PARM_DESC(id, "ID string");
173module_param_array(enable, bool, NULL, 0444); 40module_param_array(enable, bool, NULL, 0444);
174MODULE_PARM_DESC(enable, "enable card"); 41MODULE_PARM_DESC(enable, "enable card");
175 42
176enum {
177 MODEL_D2,
178 MODEL_D2X,
179 MODEL_D1,
180 MODEL_DX,
181 MODEL_HDAV, /* without daughterboard */
182 MODEL_HDAV_H6, /* with H6 daughterboard */
183 MODEL_ST,
184 MODEL_ST_H6,
185 MODEL_STX,
186};
187
188static struct pci_device_id xonar_ids[] __devinitdata = { 43static struct pci_device_id xonar_ids[] __devinitdata = {
189 { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 }, 44 { OXYGEN_PCI_SUBID(0x1043, 0x8269) },
190 { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX }, 45 { OXYGEN_PCI_SUBID(0x1043, 0x8275) },
191 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, 46 { OXYGEN_PCI_SUBID(0x1043, 0x82b7) },
192 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, 47 { OXYGEN_PCI_SUBID(0x1043, 0x8314) },
193 { OXYGEN_PCI_SUBID(0x1043, 0x8327), .driver_data = MODEL_DX }, 48 { OXYGEN_PCI_SUBID(0x1043, 0x8327) },
194 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, 49 { OXYGEN_PCI_SUBID(0x1043, 0x834f) },
195 { OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX }, 50 { OXYGEN_PCI_SUBID(0x1043, 0x835c) },
196 { OXYGEN_PCI_SUBID(0x1043, 0x835d), .driver_data = MODEL_ST }, 51 { OXYGEN_PCI_SUBID(0x1043, 0x835d) },
197 { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, 52 { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
198 { } 53 { }
199}; 54};
200MODULE_DEVICE_TABLE(pci, xonar_ids); 55MODULE_DEVICE_TABLE(pci, xonar_ids);
201 56
202
203#define GPIO_CS53x1_M_MASK 0x000c
204#define GPIO_CS53x1_M_SINGLE 0x0000
205#define GPIO_CS53x1_M_DOUBLE 0x0004
206#define GPIO_CS53x1_M_QUAD 0x0008
207
208#define GPIO_D2X_EXT_POWER 0x0020
209#define GPIO_D2_ALT 0x0080
210#define GPIO_D2_OUTPUT_ENABLE 0x0100
211
212#define GPI_DX_EXT_POWER 0x01
213#define GPIO_DX_OUTPUT_ENABLE 0x0001
214#define GPIO_DX_FRONT_PANEL 0x0002
215#define GPIO_DX_INPUT_ROUTE 0x0100
216
217#define GPIO_DB_MASK 0x0030
218#define GPIO_DB_H6 0x0000
219#define GPIO_DB_XX 0x0020
220
221#define GPIO_ST_HP_REAR 0x0002
222#define GPIO_ST_HP 0x0080
223
224#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */
225#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
226#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
227
228struct xonar_data {
229 unsigned int anti_pop_delay;
230 unsigned int dacs;
231 u16 output_enable_bit;
232 u8 ext_power_reg;
233 u8 ext_power_int_reg;
234 u8 ext_power_bit;
235 u8 has_power;
236 u8 pcm1796_oversampling;
237 u8 cs4398_fm;
238 u8 cs4362a_fm;
239 u8 hdmi_params[5];
240};
241
242static void xonar_gpio_changed(struct oxygen *chip);
243
244static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
245 u8 reg, u8 value)
246{
247 /* maps ALSA channel pair number to SPI output */
248 static const u8 codec_map[4] = {
249 0, 1, 2, 4
250 };
251 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
252 OXYGEN_SPI_DATA_LENGTH_2 |
253 OXYGEN_SPI_CLOCK_160 |
254 (codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
255 OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
256 (reg << 8) | value);
257}
258
259static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec,
260 u8 reg, u8 value)
261{
262 oxygen_write_i2c(chip, I2C_DEVICE_PCM1796(codec), reg, value);
263}
264
265static void pcm1796_write(struct oxygen *chip, unsigned int codec,
266 u8 reg, u8 value)
267{
268 if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) ==
269 OXYGEN_FUNCTION_SPI)
270 pcm1796_write_spi(chip, codec, reg, value);
271 else
272 pcm1796_write_i2c(chip, codec, reg, value);
273}
274
275static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
276{
277 oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
278}
279
280static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
281{
282 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
283}
284
285static void hdmi_write_command(struct oxygen *chip, u8 command,
286 unsigned int count, const u8 *params)
287{
288 unsigned int i;
289 u8 checksum;
290
291 oxygen_write_uart(chip, 0xfb);
292 oxygen_write_uart(chip, 0xef);
293 oxygen_write_uart(chip, command);
294 oxygen_write_uart(chip, count);
295 for (i = 0; i < count; ++i)
296 oxygen_write_uart(chip, params[i]);
297 checksum = 0xfb + 0xef + command + count;
298 for (i = 0; i < count; ++i)
299 checksum += params[i];
300 oxygen_write_uart(chip, checksum);
301}
302
303static void xonar_enable_output(struct oxygen *chip)
304{
305 struct xonar_data *data = chip->model_data;
306
307 msleep(data->anti_pop_delay);
308 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
309}
310
311static void xonar_common_init(struct oxygen *chip)
312{
313 struct xonar_data *data = chip->model_data;
314
315 if (data->ext_power_reg) {
316 oxygen_set_bits8(chip, data->ext_power_int_reg,
317 data->ext_power_bit);
318 chip->interrupt_mask |= OXYGEN_INT_GPIO;
319 chip->model.gpio_changed = xonar_gpio_changed;
320 data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
321 & data->ext_power_bit);
322 }
323 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
324 GPIO_CS53x1_M_MASK | data->output_enable_bit);
325 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
326 GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
327 oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
328 xonar_enable_output(chip);
329}
330
331static void update_pcm1796_volume(struct oxygen *chip)
332{
333 struct xonar_data *data = chip->model_data;
334 unsigned int i;
335
336 for (i = 0; i < data->dacs; ++i) {
337 pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]);
338 pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]);
339 }
340}
341
342static void update_pcm1796_mute(struct oxygen *chip)
343{
344 struct xonar_data *data = chip->model_data;
345 unsigned int i;
346 u8 value;
347
348 value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
349 if (chip->dac_mute)
350 value |= PCM1796_MUTE;
351 for (i = 0; i < data->dacs; ++i)
352 pcm1796_write(chip, i, 18, value);
353}
354
355static void pcm1796_init(struct oxygen *chip)
356{
357 struct xonar_data *data = chip->model_data;
358 unsigned int i;
359
360 for (i = 0; i < data->dacs; ++i) {
361 pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
362 pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
363 pcm1796_write(chip, i, 21, 0);
364 }
365 update_pcm1796_mute(chip); /* set ATLD before ATL/ATR */
366 update_pcm1796_volume(chip);
367}
368
369static void xonar_d2_init(struct oxygen *chip)
370{
371 struct xonar_data *data = chip->model_data;
372
373 data->anti_pop_delay = 300;
374 data->dacs = 4;
375 data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
376 data->pcm1796_oversampling = PCM1796_OS_64;
377
378 pcm1796_init(chip);
379
380 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
381 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
382
383 xonar_common_init(chip);
384
385 snd_component_add(chip->card, "PCM1796");
386 snd_component_add(chip->card, "CS5381");
387}
388
389static void xonar_d2x_init(struct oxygen *chip)
390{
391 struct xonar_data *data = chip->model_data;
392
393 data->ext_power_reg = OXYGEN_GPIO_DATA;
394 data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
395 data->ext_power_bit = GPIO_D2X_EXT_POWER;
396 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
397
398 xonar_d2_init(chip);
399}
400
401static void update_cs4362a_volumes(struct oxygen *chip)
402{
403 u8 mute;
404
405 mute = chip->dac_mute ? CS4362A_MUTE : 0;
406 cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
407 cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
408 cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
409 cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
410 cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
411 cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
412}
413
414static void update_cs43xx_volume(struct oxygen *chip)
415{
416 cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
417 cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
418 update_cs4362a_volumes(chip);
419}
420
421static void update_cs43xx_mute(struct oxygen *chip)
422{
423 u8 reg;
424
425 reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
426 if (chip->dac_mute)
427 reg |= CS4398_MUTE_B | CS4398_MUTE_A;
428 cs4398_write(chip, 4, reg);
429 update_cs4362a_volumes(chip);
430}
431
432static void cs43xx_init(struct oxygen *chip)
433{
434 struct xonar_data *data = chip->model_data;
435
436 /* set CPEN (control port mode) and power down */
437 cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
438 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
439 /* configure */
440 cs4398_write(chip, 2, data->cs4398_fm);
441 cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
442 cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
443 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
444 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
445 cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
446 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
447 cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
448 cs4362a_write(chip, 0x05, 0);
449 cs4362a_write(chip, 0x06, data->cs4362a_fm);
450 cs4362a_write(chip, 0x09, data->cs4362a_fm);
451 cs4362a_write(chip, 0x0c, data->cs4362a_fm);
452 update_cs43xx_volume(chip);
453 update_cs43xx_mute(chip);
454 /* clear power down */
455 cs4398_write(chip, 8, CS4398_CPEN);
456 cs4362a_write(chip, 0x01, CS4362A_CPEN);
457}
458
459static void xonar_d1_init(struct oxygen *chip)
460{
461 struct xonar_data *data = chip->model_data;
462
463 data->anti_pop_delay = 800;
464 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
465 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
466 data->cs4362a_fm = CS4362A_FM_SINGLE |
467 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
468
469 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
470 OXYGEN_2WIRE_LENGTH_8 |
471 OXYGEN_2WIRE_INTERRUPT_MASK |
472 OXYGEN_2WIRE_SPEED_FAST);
473
474 cs43xx_init(chip);
475
476 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
477 GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
478 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
479 GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
480
481 xonar_common_init(chip);
482
483 snd_component_add(chip->card, "CS4398");
484 snd_component_add(chip->card, "CS4362A");
485 snd_component_add(chip->card, "CS5361");
486}
487
488static void xonar_dx_init(struct oxygen *chip)
489{
490 struct xonar_data *data = chip->model_data;
491
492 data->ext_power_reg = OXYGEN_GPI_DATA;
493 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
494 data->ext_power_bit = GPI_DX_EXT_POWER;
495
496 xonar_d1_init(chip);
497}
498
499static void xonar_hdav_init(struct oxygen *chip)
500{
501 struct xonar_data *data = chip->model_data;
502 u8 param;
503
504 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
505 OXYGEN_2WIRE_LENGTH_8 |
506 OXYGEN_2WIRE_INTERRUPT_MASK |
507 OXYGEN_2WIRE_SPEED_FAST);
508
509 data->anti_pop_delay = 100;
510 data->dacs = chip->model.private_data == MODEL_HDAV_H6 ? 4 : 1;
511 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
512 data->ext_power_reg = OXYGEN_GPI_DATA;
513 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
514 data->ext_power_bit = GPI_DX_EXT_POWER;
515 data->pcm1796_oversampling = PCM1796_OS_64;
516
517 pcm1796_init(chip);
518
519 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DX_INPUT_ROUTE);
520 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DX_INPUT_ROUTE);
521
522 oxygen_reset_uart(chip);
523 param = 0;
524 hdmi_write_command(chip, 0x61, 1, &param);
525 param = 1;
526 hdmi_write_command(chip, 0x74, 1, &param);
527 data->hdmi_params[1] = IEC958_AES3_CON_FS_48000;
528 data->hdmi_params[4] = 1;
529 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
530
531 xonar_common_init(chip);
532
533 snd_component_add(chip->card, "PCM1796");
534 snd_component_add(chip->card, "CS5381");
535}
536
537static void xonar_st_init(struct oxygen *chip)
538{
539 struct xonar_data *data = chip->model_data;
540
541 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
542 OXYGEN_2WIRE_LENGTH_8 |
543 OXYGEN_2WIRE_INTERRUPT_MASK |
544 OXYGEN_2WIRE_SPEED_FAST);
545
546 if (chip->model.private_data == MODEL_ST_H6)
547 chip->model.dac_channels = 8;
548 data->anti_pop_delay = 100;
549 data->dacs = chip->model.private_data == MODEL_ST_H6 ? 4 : 1;
550 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
551 data->pcm1796_oversampling = PCM1796_OS_64;
552
553 pcm1796_init(chip);
554
555 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
556 GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
557 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
558 GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
559
560 xonar_common_init(chip);
561
562 snd_component_add(chip->card, "PCM1792A");
563 snd_component_add(chip->card, "CS5381");
564}
565
566static void xonar_stx_init(struct oxygen *chip)
567{
568 struct xonar_data *data = chip->model_data;
569
570 data->ext_power_reg = OXYGEN_GPI_DATA;
571 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
572 data->ext_power_bit = GPI_DX_EXT_POWER;
573
574 xonar_st_init(chip);
575}
576
577static void xonar_disable_output(struct oxygen *chip)
578{
579 struct xonar_data *data = chip->model_data;
580
581 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
582}
583
584static void xonar_d2_cleanup(struct oxygen *chip)
585{
586 xonar_disable_output(chip);
587}
588
589static void xonar_d1_cleanup(struct oxygen *chip)
590{
591 xonar_disable_output(chip);
592 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
593 oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
594}
595
596static void xonar_hdav_cleanup(struct oxygen *chip)
597{
598 u8 param = 0;
599
600 hdmi_write_command(chip, 0x74, 1, &param);
601 xonar_disable_output(chip);
602}
603
604static void xonar_st_cleanup(struct oxygen *chip)
605{
606 xonar_disable_output(chip);
607}
608
609static void xonar_d2_suspend(struct oxygen *chip)
610{
611 xonar_d2_cleanup(chip);
612}
613
614static void xonar_d1_suspend(struct oxygen *chip)
615{
616 xonar_d1_cleanup(chip);
617}
618
619static void xonar_hdav_suspend(struct oxygen *chip)
620{
621 xonar_hdav_cleanup(chip);
622 msleep(2);
623}
624
625static void xonar_st_suspend(struct oxygen *chip)
626{
627 xonar_st_cleanup(chip);
628}
629
630static void xonar_d2_resume(struct oxygen *chip)
631{
632 pcm1796_init(chip);
633 xonar_enable_output(chip);
634}
635
636static void xonar_d1_resume(struct oxygen *chip)
637{
638 oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
639 msleep(1);
640 cs43xx_init(chip);
641 xonar_enable_output(chip);
642}
643
644static void xonar_hdav_resume(struct oxygen *chip)
645{
646 struct xonar_data *data = chip->model_data;
647 u8 param;
648
649 oxygen_reset_uart(chip);
650 param = 0;
651 hdmi_write_command(chip, 0x61, 1, &param);
652 param = 1;
653 hdmi_write_command(chip, 0x74, 1, &param);
654 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
655 pcm1796_init(chip);
656 xonar_enable_output(chip);
657}
658
659static void xonar_st_resume(struct oxygen *chip)
660{
661 pcm1796_init(chip);
662 xonar_enable_output(chip);
663}
664
665static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
666 struct snd_pcm_hardware *hardware)
667{
668 if (channel == PCM_MULTICH) {
669 hardware->rates = SNDRV_PCM_RATE_44100 |
670 SNDRV_PCM_RATE_48000 |
671 SNDRV_PCM_RATE_96000 |
672 SNDRV_PCM_RATE_192000;
673 hardware->rate_min = 44100;
674 }
675}
676
677static void set_pcm1796_params(struct oxygen *chip,
678 struct snd_pcm_hw_params *params)
679{
680 struct xonar_data *data = chip->model_data;
681 unsigned int i;
682
683 data->pcm1796_oversampling =
684 params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
685 for (i = 0; i < data->dacs; ++i)
686 pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
687}
688
689static void set_cs53x1_params(struct oxygen *chip,
690 struct snd_pcm_hw_params *params)
691{
692 unsigned int value;
693
694 if (params_rate(params) <= 54000)
695 value = GPIO_CS53x1_M_SINGLE;
696 else if (params_rate(params) <= 108000)
697 value = GPIO_CS53x1_M_DOUBLE;
698 else
699 value = GPIO_CS53x1_M_QUAD;
700 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
701 value, GPIO_CS53x1_M_MASK);
702}
703
704static void set_cs43xx_params(struct oxygen *chip,
705 struct snd_pcm_hw_params *params)
706{
707 struct xonar_data *data = chip->model_data;
708
709 data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST;
710 data->cs4362a_fm = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
711 if (params_rate(params) <= 50000) {
712 data->cs4398_fm |= CS4398_FM_SINGLE;
713 data->cs4362a_fm |= CS4362A_FM_SINGLE;
714 } else if (params_rate(params) <= 100000) {
715 data->cs4398_fm |= CS4398_FM_DOUBLE;
716 data->cs4362a_fm |= CS4362A_FM_DOUBLE;
717 } else {
718 data->cs4398_fm |= CS4398_FM_QUAD;
719 data->cs4362a_fm |= CS4362A_FM_QUAD;
720 }
721 cs4398_write(chip, 2, data->cs4398_fm);
722 cs4362a_write(chip, 0x06, data->cs4362a_fm);
723 cs4362a_write(chip, 0x09, data->cs4362a_fm);
724 cs4362a_write(chip, 0x0c, data->cs4362a_fm);
725}
726
727static void set_hdmi_params(struct oxygen *chip,
728 struct snd_pcm_hw_params *params)
729{
730 struct xonar_data *data = chip->model_data;
731
732 data->hdmi_params[0] = 0; /* 1 = non-audio */
733 switch (params_rate(params)) {
734 case 44100:
735 data->hdmi_params[1] = IEC958_AES3_CON_FS_44100;
736 break;
737 case 48000:
738 data->hdmi_params[1] = IEC958_AES3_CON_FS_48000;
739 break;
740 default: /* 96000 */
741 data->hdmi_params[1] = IEC958_AES3_CON_FS_96000;
742 break;
743 case 192000:
744 data->hdmi_params[1] = IEC958_AES3_CON_FS_192000;
745 break;
746 }
747 data->hdmi_params[2] = params_channels(params) / 2 - 1;
748 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
749 data->hdmi_params[3] = 0;
750 else
751 data->hdmi_params[3] = 0xc0;
752 data->hdmi_params[4] = 1; /* ? */
753 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
754}
755
756static void set_hdav_params(struct oxygen *chip,
757 struct snd_pcm_hw_params *params)
758{
759 set_pcm1796_params(chip, params);
760 set_hdmi_params(chip, params);
761}
762
763static void xonar_gpio_changed(struct oxygen *chip)
764{
765 struct xonar_data *data = chip->model_data;
766 u8 has_power;
767
768 has_power = !!(oxygen_read8(chip, data->ext_power_reg)
769 & data->ext_power_bit);
770 if (has_power != data->has_power) {
771 data->has_power = has_power;
772 if (has_power) {
773 snd_printk(KERN_NOTICE "power restored\n");
774 } else {
775 snd_printk(KERN_CRIT
776 "Hey! Don't unplug the power cable!\n");
777 /* TODO: stop PCMs */
778 }
779 }
780}
781
782static void xonar_hdav_uart_input(struct oxygen *chip)
783{
784 if (chip->uart_input_count >= 2 &&
785 chip->uart_input[chip->uart_input_count - 2] == 'O' &&
786 chip->uart_input[chip->uart_input_count - 1] == 'K') {
787 printk(KERN_DEBUG "message from Xonar HDAV HDMI chip received:\n");
788 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
789 chip->uart_input, chip->uart_input_count);
790 chip->uart_input_count = 0;
791 }
792}
793
794static int gpio_bit_switch_get(struct snd_kcontrol *ctl,
795 struct snd_ctl_elem_value *value)
796{
797 struct oxygen *chip = ctl->private_data;
798 u16 bit = ctl->private_value;
799
800 value->value.integer.value[0] =
801 !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit);
802 return 0;
803}
804
805static int gpio_bit_switch_put(struct snd_kcontrol *ctl,
806 struct snd_ctl_elem_value *value)
807{
808 struct oxygen *chip = ctl->private_data;
809 u16 bit = ctl->private_value;
810 u16 old_bits, new_bits;
811 int changed;
812
813 spin_lock_irq(&chip->reg_lock);
814 old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
815 if (value->value.integer.value[0])
816 new_bits = old_bits | bit;
817 else
818 new_bits = old_bits & ~bit;
819 changed = new_bits != old_bits;
820 if (changed)
821 oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
822 spin_unlock_irq(&chip->reg_lock);
823 return changed;
824}
825
826static const struct snd_kcontrol_new alt_switch = {
827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
828 .name = "Analog Loopback Switch",
829 .info = snd_ctl_boolean_mono_info,
830 .get = gpio_bit_switch_get,
831 .put = gpio_bit_switch_put,
832 .private_value = GPIO_D2_ALT,
833};
834
835static const struct snd_kcontrol_new front_panel_switch = {
836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
837 .name = "Front Panel Switch",
838 .info = snd_ctl_boolean_mono_info,
839 .get = gpio_bit_switch_get,
840 .put = gpio_bit_switch_put,
841 .private_value = GPIO_DX_FRONT_PANEL,
842};
843
844static int st_output_switch_info(struct snd_kcontrol *ctl,
845 struct snd_ctl_elem_info *info)
846{
847 static const char *const names[3] = {
848 "Speakers", "Headphones", "FP Headphones"
849 };
850
851 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
852 info->count = 1;
853 info->value.enumerated.items = 3;
854 if (info->value.enumerated.item >= 3)
855 info->value.enumerated.item = 2;
856 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
857 return 0;
858}
859
860static int st_output_switch_get(struct snd_kcontrol *ctl,
861 struct snd_ctl_elem_value *value)
862{
863 struct oxygen *chip = ctl->private_data;
864 u16 gpio;
865
866 gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
867 if (!(gpio & GPIO_ST_HP))
868 value->value.enumerated.item[0] = 0;
869 else if (gpio & GPIO_ST_HP_REAR)
870 value->value.enumerated.item[0] = 1;
871 else
872 value->value.enumerated.item[0] = 2;
873 return 0;
874}
875
876
877static int st_output_switch_put(struct snd_kcontrol *ctl,
878 struct snd_ctl_elem_value *value)
879{
880 struct oxygen *chip = ctl->private_data;
881 u16 gpio_old, gpio;
882
883 mutex_lock(&chip->mutex);
884 gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
885 gpio = gpio_old;
886 switch (value->value.enumerated.item[0]) {
887 case 0:
888 gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
889 break;
890 case 1:
891 gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
892 break;
893 case 2:
894 gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
895 break;
896 }
897 oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
898 mutex_unlock(&chip->mutex);
899 return gpio != gpio_old;
900}
901
902static const struct snd_kcontrol_new st_output_switch = {
903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
904 .name = "Analog Output",
905 .info = st_output_switch_info,
906 .get = st_output_switch_get,
907 .put = st_output_switch_put,
908};
909
910static void xonar_line_mic_ac97_switch(struct oxygen *chip,
911 unsigned int reg, unsigned int mute)
912{
913 if (reg == AC97_LINE) {
914 spin_lock_irq(&chip->reg_lock);
915 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
916 mute ? GPIO_DX_INPUT_ROUTE : 0,
917 GPIO_DX_INPUT_ROUTE);
918 spin_unlock_irq(&chip->reg_lock);
919 }
920}
921
922static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0);
923static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
924
925static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
926{
927 if (!strncmp(template->name, "CD Capture ", 11))
928 /* CD in is actually connected to the video in pin */
929 template->private_value ^= AC97_CD ^ AC97_VIDEO;
930 return 0;
931}
932
933static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
934{
935 if (!strncmp(template->name, "CD Capture ", 11))
936 return 1; /* no CD input */
937 return 0;
938}
939
940static int xonar_st_control_filter(struct snd_kcontrol_new *template)
941{
942 if (!strncmp(template->name, "CD Capture ", 11))
943 return 1; /* no CD input */
944 if (!strcmp(template->name, "Stereo Upmixing"))
945 return 1; /* stereo only - we don't need upmixing */
946 return 0;
947}
948
949static int xonar_d2_mixer_init(struct oxygen *chip)
950{
951 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
952}
953
954static int xonar_d1_mixer_init(struct oxygen *chip)
955{
956 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
957}
958
959static int xonar_st_mixer_init(struct oxygen *chip)
960{
961 return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip));
962}
963
964static const struct oxygen_model model_xonar_d2 = {
965 .longname = "Asus Virtuoso 200",
966 .chip = "AV200",
967 .init = xonar_d2_init,
968 .control_filter = xonar_d2_control_filter,
969 .mixer_init = xonar_d2_mixer_init,
970 .cleanup = xonar_d2_cleanup,
971 .suspend = xonar_d2_suspend,
972 .resume = xonar_d2_resume,
973 .set_dac_params = set_pcm1796_params,
974 .set_adc_params = set_cs53x1_params,
975 .update_dac_volume = update_pcm1796_volume,
976 .update_dac_mute = update_pcm1796_mute,
977 .dac_tlv = pcm1796_db_scale,
978 .model_data_size = sizeof(struct xonar_data),
979 .device_config = PLAYBACK_0_TO_I2S |
980 PLAYBACK_1_TO_SPDIF |
981 CAPTURE_0_FROM_I2S_2 |
982 CAPTURE_1_FROM_SPDIF |
983 MIDI_OUTPUT |
984 MIDI_INPUT,
985 .dac_channels = 8,
986 .dac_volume_min = 255 - 2*60,
987 .dac_volume_max = 255,
988 .misc_flags = OXYGEN_MISC_MIDI,
989 .function_flags = OXYGEN_FUNCTION_SPI |
990 OXYGEN_FUNCTION_ENABLE_SPI_4_5,
991 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
992 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
993};
994
995static const struct oxygen_model model_xonar_d1 = {
996 .longname = "Asus Virtuoso 100",
997 .chip = "AV200",
998 .init = xonar_d1_init,
999 .control_filter = xonar_d1_control_filter,
1000 .mixer_init = xonar_d1_mixer_init,
1001 .cleanup = xonar_d1_cleanup,
1002 .suspend = xonar_d1_suspend,
1003 .resume = xonar_d1_resume,
1004 .set_dac_params = set_cs43xx_params,
1005 .set_adc_params = set_cs53x1_params,
1006 .update_dac_volume = update_cs43xx_volume,
1007 .update_dac_mute = update_cs43xx_mute,
1008 .ac97_switch = xonar_line_mic_ac97_switch,
1009 .dac_tlv = cs4362a_db_scale,
1010 .model_data_size = sizeof(struct xonar_data),
1011 .device_config = PLAYBACK_0_TO_I2S |
1012 PLAYBACK_1_TO_SPDIF |
1013 CAPTURE_0_FROM_I2S_2,
1014 .dac_channels = 8,
1015 .dac_volume_min = 127 - 60,
1016 .dac_volume_max = 127,
1017 .function_flags = OXYGEN_FUNCTION_2WIRE,
1018 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1019 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1020};
1021
1022static const struct oxygen_model model_xonar_hdav = {
1023 .longname = "Asus Virtuoso 200",
1024 .chip = "AV200",
1025 .init = xonar_hdav_init,
1026 .cleanup = xonar_hdav_cleanup,
1027 .suspend = xonar_hdav_suspend,
1028 .resume = xonar_hdav_resume,
1029 .pcm_hardware_filter = xonar_hdav_pcm_hardware_filter,
1030 .set_dac_params = set_hdav_params,
1031 .set_adc_params = set_cs53x1_params,
1032 .update_dac_volume = update_pcm1796_volume,
1033 .update_dac_mute = update_pcm1796_mute,
1034 .uart_input = xonar_hdav_uart_input,
1035 .ac97_switch = xonar_line_mic_ac97_switch,
1036 .dac_tlv = pcm1796_db_scale,
1037 .model_data_size = sizeof(struct xonar_data),
1038 .device_config = PLAYBACK_0_TO_I2S |
1039 PLAYBACK_1_TO_SPDIF |
1040 CAPTURE_0_FROM_I2S_2 |
1041 CAPTURE_1_FROM_SPDIF,
1042 .dac_channels = 8,
1043 .dac_volume_min = 255 - 2*60,
1044 .dac_volume_max = 255,
1045 .misc_flags = OXYGEN_MISC_MIDI,
1046 .function_flags = OXYGEN_FUNCTION_2WIRE,
1047 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1048 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1049};
1050
1051static const struct oxygen_model model_xonar_st = {
1052 .longname = "Asus Virtuoso 100",
1053 .chip = "AV200",
1054 .init = xonar_st_init,
1055 .control_filter = xonar_st_control_filter,
1056 .mixer_init = xonar_st_mixer_init,
1057 .cleanup = xonar_st_cleanup,
1058 .suspend = xonar_st_suspend,
1059 .resume = xonar_st_resume,
1060 .set_dac_params = set_pcm1796_params,
1061 .set_adc_params = set_cs53x1_params,
1062 .update_dac_volume = update_pcm1796_volume,
1063 .update_dac_mute = update_pcm1796_mute,
1064 .ac97_switch = xonar_line_mic_ac97_switch,
1065 .dac_tlv = pcm1796_db_scale,
1066 .model_data_size = sizeof(struct xonar_data),
1067 .device_config = PLAYBACK_0_TO_I2S |
1068 PLAYBACK_1_TO_SPDIF |
1069 CAPTURE_0_FROM_I2S_2,
1070 .dac_channels = 2,
1071 .dac_volume_min = 255 - 2*60,
1072 .dac_volume_max = 255,
1073 .function_flags = OXYGEN_FUNCTION_2WIRE,
1074 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1075 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1076};
1077
1078static int __devinit get_xonar_model(struct oxygen *chip, 57static int __devinit get_xonar_model(struct oxygen *chip,
1079 const struct pci_device_id *id) 58 const struct pci_device_id *id)
1080{ 59{
1081 static const struct oxygen_model *const models[] = { 60 if (get_xonar_pcm179x_model(chip, id) >= 0)
1082 [MODEL_D1] = &model_xonar_d1, 61 return 0;
1083 [MODEL_DX] = &model_xonar_d1, 62 if (get_xonar_cs43xx_model(chip, id) >= 0)
1084 [MODEL_D2] = &model_xonar_d2, 63 return 0;
1085 [MODEL_D2X] = &model_xonar_d2, 64 return -EINVAL;
1086 [MODEL_HDAV] = &model_xonar_hdav,
1087 [MODEL_ST] = &model_xonar_st,
1088 [MODEL_STX] = &model_xonar_st,
1089 };
1090 static const char *const names[] = {
1091 [MODEL_D1] = "Xonar D1",
1092 [MODEL_DX] = "Xonar DX",
1093 [MODEL_D2] = "Xonar D2",
1094 [MODEL_D2X] = "Xonar D2X",
1095 [MODEL_HDAV] = "Xonar HDAV1.3",
1096 [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6",
1097 [MODEL_ST] = "Xonar Essence ST",
1098 [MODEL_ST_H6] = "Xonar Essence ST+H6",
1099 [MODEL_STX] = "Xonar Essence STX",
1100 };
1101 unsigned int model = id->driver_data;
1102
1103 if (model >= ARRAY_SIZE(models) || !models[model])
1104 return -EINVAL;
1105 chip->model = *models[model];
1106
1107 switch (model) {
1108 case MODEL_D2X:
1109 chip->model.init = xonar_d2x_init;
1110 break;
1111 case MODEL_DX:
1112 chip->model.init = xonar_dx_init;
1113 break;
1114 case MODEL_HDAV:
1115 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
1116 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) {
1117 case GPIO_DB_H6:
1118 model = MODEL_HDAV_H6;
1119 break;
1120 case GPIO_DB_XX:
1121 snd_printk(KERN_ERR "unknown daughterboard\n");
1122 return -ENODEV;
1123 }
1124 break;
1125 case MODEL_ST:
1126 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
1127 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) {
1128 case GPIO_DB_H6:
1129 model = MODEL_ST_H6;
1130 break;
1131 }
1132 break;
1133 case MODEL_STX:
1134 chip->model.init = xonar_stx_init;
1135 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
1136 break;
1137 }
1138
1139 chip->model.shortname = names[model];
1140 chip->model.private_data = model;
1141 return 0;
1142} 65}
1143 66
1144static int __devinit xonar_probe(struct pci_dev *pci, 67static int __devinit xonar_probe(struct pci_dev *pci,
diff --git a/sound/pci/oxygen/xonar.h b/sound/pci/oxygen/xonar.h
new file mode 100644
index 000000000000..89b3ed814d64
--- /dev/null
+++ b/sound/pci/oxygen/xonar.h
@@ -0,0 +1,50 @@
1#ifndef XONAR_H_INCLUDED
2#define XONAR_H_INCLUDED
3
4#include "oxygen.h"
5
6struct xonar_generic {
7 unsigned int anti_pop_delay;
8 u16 output_enable_bit;
9 u8 ext_power_reg;
10 u8 ext_power_int_reg;
11 u8 ext_power_bit;
12 u8 has_power;
13};
14
15struct xonar_hdmi {
16 u8 params[5];
17};
18
19/* generic helper functions */
20
21void xonar_enable_output(struct oxygen *chip);
22void xonar_disable_output(struct oxygen *chip);
23void xonar_init_ext_power(struct oxygen *chip);
24void xonar_init_cs53x1(struct oxygen *chip);
25void xonar_set_cs53x1_params(struct oxygen *chip,
26 struct snd_pcm_hw_params *params);
27int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl,
28 struct snd_ctl_elem_value *value);
29int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl,
30 struct snd_ctl_elem_value *value);
31
32/* model-specific card drivers */
33
34int get_xonar_pcm179x_model(struct oxygen *chip,
35 const struct pci_device_id *id);
36int get_xonar_cs43xx_model(struct oxygen *chip,
37 const struct pci_device_id *id);
38
39/* HDMI helper functions */
40
41void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *data);
42void xonar_hdmi_cleanup(struct oxygen *chip);
43void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi);
44void xonar_hdmi_pcm_hardware_filter(unsigned int channel,
45 struct snd_pcm_hardware *hardware);
46void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi,
47 struct snd_pcm_hw_params *params);
48void xonar_hdmi_uart_input(struct oxygen *chip);
49
50#endif
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
new file mode 100644
index 000000000000..16c226bfcd2b
--- /dev/null
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -0,0 +1,434 @@
1/*
2 * card driver for models with CS4398/CS4362A DACs (Xonar D1/DX)
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Xonar D1/DX
21 * -----------
22 *
23 * CMI8788:
24 *
25 * I²C <-> CS4398 (front)
26 * <-> CS4362A (surround, center/LFE, back)
27 *
28 * GPI 0 <- external power present (DX only)
29 *
30 * GPIO 0 -> enable output to speakers
31 * GPIO 1 -> enable front panel I/O
32 * GPIO 2 -> M0 of CS5361
33 * GPIO 3 -> M1 of CS5361
34 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
35 *
36 * CS4398:
37 *
38 * AD0 <- 1
39 * AD1 <- 1
40 *
41 * CS4362A:
42 *
43 * AD0 <- 0
44 *
45 * CM9780:
46 *
47 * GPO 0 -> route line-in (0) or AC97 output (1) to CS5361 input
48 */
49
50#include <linux/pci.h>
51#include <linux/delay.h>
52#include <sound/ac97_codec.h>
53#include <sound/control.h>
54#include <sound/core.h>
55#include <sound/pcm.h>
56#include <sound/pcm_params.h>
57#include <sound/tlv.h>
58#include "xonar.h"
59#include "cs4398.h"
60#include "cs4362a.h"
61
62#define GPI_EXT_POWER 0x01
63#define GPIO_D1_OUTPUT_ENABLE 0x0001
64#define GPIO_D1_FRONT_PANEL 0x0002
65#define GPIO_D1_INPUT_ROUTE 0x0100
66
67#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
68#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
69
70struct xonar_cs43xx {
71 struct xonar_generic generic;
72 u8 cs4398_regs[8];
73 u8 cs4362a_regs[15];
74};
75
76static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
77{
78 struct xonar_cs43xx *data = chip->model_data;
79
80 oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
81 if (reg < ARRAY_SIZE(data->cs4398_regs))
82 data->cs4398_regs[reg] = value;
83}
84
85static void cs4398_write_cached(struct oxygen *chip, u8 reg, u8 value)
86{
87 struct xonar_cs43xx *data = chip->model_data;
88
89 if (value != data->cs4398_regs[reg])
90 cs4398_write(chip, reg, value);
91}
92
93static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
94{
95 struct xonar_cs43xx *data = chip->model_data;
96
97 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
98 if (reg < ARRAY_SIZE(data->cs4362a_regs))
99 data->cs4362a_regs[reg] = value;
100}
101
102static void cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value)
103{
104 struct xonar_cs43xx *data = chip->model_data;
105
106 if (value != data->cs4362a_regs[reg])
107 cs4362a_write(chip, reg, value);
108}
109
110static void cs43xx_registers_init(struct oxygen *chip)
111{
112 struct xonar_cs43xx *data = chip->model_data;
113 unsigned int i;
114
115 /* set CPEN (control port mode) and power down */
116 cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
117 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
118 /* configure */
119 cs4398_write(chip, 2, data->cs4398_regs[2]);
120 cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
121 cs4398_write(chip, 4, data->cs4398_regs[4]);
122 cs4398_write(chip, 5, data->cs4398_regs[5]);
123 cs4398_write(chip, 6, data->cs4398_regs[6]);
124 cs4398_write(chip, 7, data->cs4398_regs[7]);
125 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
126 cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
127 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
128 cs4362a_write(chip, 0x04, data->cs4362a_regs[0x04]);
129 cs4362a_write(chip, 0x05, 0);
130 for (i = 6; i <= 14; ++i)
131 cs4362a_write(chip, i, data->cs4362a_regs[i]);
132 /* clear power down */
133 cs4398_write(chip, 8, CS4398_CPEN);
134 cs4362a_write(chip, 0x01, CS4362A_CPEN);
135}
136
137static void xonar_d1_init(struct oxygen *chip)
138{
139 struct xonar_cs43xx *data = chip->model_data;
140
141 data->generic.anti_pop_delay = 800;
142 data->generic.output_enable_bit = GPIO_D1_OUTPUT_ENABLE;
143 data->cs4398_regs[2] =
144 CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
145 data->cs4398_regs[4] = CS4398_MUTEP_LOW |
146 CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE;
147 data->cs4398_regs[5] = 60 * 2;
148 data->cs4398_regs[6] = 60 * 2;
149 data->cs4398_regs[7] = CS4398_RMP_DN | CS4398_RMP_UP |
150 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP;
151 data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE;
152 data->cs4362a_regs[6] = CS4362A_FM_SINGLE |
153 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
154 data->cs4362a_regs[7] = 60 | CS4362A_MUTE;
155 data->cs4362a_regs[8] = 60 | CS4362A_MUTE;
156 data->cs4362a_regs[9] = data->cs4362a_regs[6];
157 data->cs4362a_regs[10] = 60 | CS4362A_MUTE;
158 data->cs4362a_regs[11] = 60 | CS4362A_MUTE;
159 data->cs4362a_regs[12] = data->cs4362a_regs[6];
160 data->cs4362a_regs[13] = 60 | CS4362A_MUTE;
161 data->cs4362a_regs[14] = 60 | CS4362A_MUTE;
162
163 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
164 OXYGEN_2WIRE_LENGTH_8 |
165 OXYGEN_2WIRE_INTERRUPT_MASK |
166 OXYGEN_2WIRE_SPEED_FAST);
167
168 cs43xx_registers_init(chip);
169
170 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
171 GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);
172 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
173 GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);
174
175 xonar_init_cs53x1(chip);
176 xonar_enable_output(chip);
177
178 snd_component_add(chip->card, "CS4398");
179 snd_component_add(chip->card, "CS4362A");
180 snd_component_add(chip->card, "CS5361");
181}
182
183static void xonar_dx_init(struct oxygen *chip)
184{
185 struct xonar_cs43xx *data = chip->model_data;
186
187 data->generic.ext_power_reg = OXYGEN_GPI_DATA;
188 data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
189 data->generic.ext_power_bit = GPI_EXT_POWER;
190 xonar_init_ext_power(chip);
191 xonar_d1_init(chip);
192}
193
194static void xonar_d1_cleanup(struct oxygen *chip)
195{
196 xonar_disable_output(chip);
197 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
198 oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
199}
200
201static void xonar_d1_suspend(struct oxygen *chip)
202{
203 xonar_d1_cleanup(chip);
204}
205
206static void xonar_d1_resume(struct oxygen *chip)
207{
208 oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
209 msleep(1);
210 cs43xx_registers_init(chip);
211 xonar_enable_output(chip);
212}
213
214static void set_cs43xx_params(struct oxygen *chip,
215 struct snd_pcm_hw_params *params)
216{
217 struct xonar_cs43xx *data = chip->model_data;
218 u8 cs4398_fm, cs4362a_fm;
219
220 if (params_rate(params) <= 50000) {
221 cs4398_fm = CS4398_FM_SINGLE;
222 cs4362a_fm = CS4362A_FM_SINGLE;
223 } else if (params_rate(params) <= 100000) {
224 cs4398_fm = CS4398_FM_DOUBLE;
225 cs4362a_fm = CS4362A_FM_DOUBLE;
226 } else {
227 cs4398_fm = CS4398_FM_QUAD;
228 cs4362a_fm = CS4362A_FM_QUAD;
229 }
230 cs4398_fm |= CS4398_DEM_NONE | CS4398_DIF_LJUST;
231 cs4398_write_cached(chip, 2, cs4398_fm);
232 cs4362a_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK;
233 cs4362a_write_cached(chip, 6, cs4362a_fm);
234 cs4362a_write_cached(chip, 12, cs4362a_fm);
235 cs4362a_fm &= CS4362A_FM_MASK;
236 cs4362a_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK;
237 cs4362a_write_cached(chip, 9, cs4362a_fm);
238}
239
240static void update_cs4362a_volumes(struct oxygen *chip)
241{
242 unsigned int i;
243 u8 mute;
244
245 mute = chip->dac_mute ? CS4362A_MUTE : 0;
246 for (i = 0; i < 6; ++i)
247 cs4362a_write_cached(chip, 7 + i + i / 2,
248 (127 - chip->dac_volume[2 + i]) | mute);
249}
250
251static void update_cs43xx_volume(struct oxygen *chip)
252{
253 cs4398_write_cached(chip, 5, (127 - chip->dac_volume[0]) * 2);
254 cs4398_write_cached(chip, 6, (127 - chip->dac_volume[1]) * 2);
255 update_cs4362a_volumes(chip);
256}
257
258static void update_cs43xx_mute(struct oxygen *chip)
259{
260 u8 reg;
261
262 reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
263 if (chip->dac_mute)
264 reg |= CS4398_MUTE_B | CS4398_MUTE_A;
265 cs4398_write_cached(chip, 4, reg);
266 update_cs4362a_volumes(chip);
267}
268
269static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed)
270{
271 struct xonar_cs43xx *data = chip->model_data;
272 u8 reg;
273
274 reg = data->cs4362a_regs[9] & ~CS4362A_ATAPI_MASK;
275 if (mixed)
276 reg |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR;
277 else
278 reg |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
279 cs4362a_write_cached(chip, 9, reg);
280}
281
282static const struct snd_kcontrol_new front_panel_switch = {
283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
284 .name = "Front Panel Switch",
285 .info = snd_ctl_boolean_mono_info,
286 .get = xonar_gpio_bit_switch_get,
287 .put = xonar_gpio_bit_switch_put,
288 .private_value = GPIO_D1_FRONT_PANEL,
289};
290
291static int rolloff_info(struct snd_kcontrol *ctl,
292 struct snd_ctl_elem_info *info)
293{
294 static const char *const names[2] = {
295 "Fast Roll-off", "Slow Roll-off"
296 };
297
298 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
299 info->count = 1;
300 info->value.enumerated.items = 2;
301 if (info->value.enumerated.item >= 2)
302 info->value.enumerated.item = 1;
303 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
304 return 0;
305}
306
307static int rolloff_get(struct snd_kcontrol *ctl,
308 struct snd_ctl_elem_value *value)
309{
310 struct oxygen *chip = ctl->private_data;
311 struct xonar_cs43xx *data = chip->model_data;
312
313 value->value.enumerated.item[0] =
314 (data->cs4398_regs[7] & CS4398_FILT_SEL) != 0;
315 return 0;
316}
317
318static int rolloff_put(struct snd_kcontrol *ctl,
319 struct snd_ctl_elem_value *value)
320{
321 struct oxygen *chip = ctl->private_data;
322 struct xonar_cs43xx *data = chip->model_data;
323 int changed;
324 u8 reg;
325
326 mutex_lock(&chip->mutex);
327 reg = data->cs4398_regs[7];
328 if (value->value.enumerated.item[0])
329 reg |= CS4398_FILT_SEL;
330 else
331 reg &= ~CS4398_FILT_SEL;
332 changed = reg != data->cs4398_regs[7];
333 if (changed) {
334 cs4398_write(chip, 7, reg);
335 if (reg & CS4398_FILT_SEL)
336 reg = data->cs4362a_regs[0x04] | CS4362A_FILT_SEL;
337 else
338 reg = data->cs4362a_regs[0x04] & ~CS4362A_FILT_SEL;
339 cs4362a_write(chip, 0x04, reg);
340 }
341 mutex_unlock(&chip->mutex);
342 return changed;
343}
344
345static const struct snd_kcontrol_new rolloff_control = {
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347 .name = "DAC Filter Playback Enum",
348 .info = rolloff_info,
349 .get = rolloff_get,
350 .put = rolloff_put,
351};
352
353static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip,
354 unsigned int reg, unsigned int mute)
355{
356 if (reg == AC97_LINE) {
357 spin_lock_irq(&chip->reg_lock);
358 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
359 mute ? GPIO_D1_INPUT_ROUTE : 0,
360 GPIO_D1_INPUT_ROUTE);
361 spin_unlock_irq(&chip->reg_lock);
362 }
363}
364
365static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
366
367static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
368{
369 if (!strncmp(template->name, "CD Capture ", 11))
370 return 1; /* no CD input */
371 return 0;
372}
373
374static int xonar_d1_mixer_init(struct oxygen *chip)
375{
376 int err;
377
378 err = snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
379 if (err < 0)
380 return err;
381 err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip));
382 if (err < 0)
383 return err;
384 return 0;
385}
386
387static const struct oxygen_model model_xonar_d1 = {
388 .longname = "Asus Virtuoso 100",
389 .chip = "AV200",
390 .init = xonar_d1_init,
391 .control_filter = xonar_d1_control_filter,
392 .mixer_init = xonar_d1_mixer_init,
393 .cleanup = xonar_d1_cleanup,
394 .suspend = xonar_d1_suspend,
395 .resume = xonar_d1_resume,
396 .get_i2s_mclk = oxygen_default_i2s_mclk,
397 .set_dac_params = set_cs43xx_params,
398 .set_adc_params = xonar_set_cs53x1_params,
399 .update_dac_volume = update_cs43xx_volume,
400 .update_dac_mute = update_cs43xx_mute,
401 .update_center_lfe_mix = update_cs43xx_center_lfe_mix,
402 .ac97_switch = xonar_d1_line_mic_ac97_switch,
403 .dac_tlv = cs4362a_db_scale,
404 .model_data_size = sizeof(struct xonar_cs43xx),
405 .device_config = PLAYBACK_0_TO_I2S |
406 PLAYBACK_1_TO_SPDIF |
407 CAPTURE_0_FROM_I2S_2,
408 .dac_channels = 8,
409 .dac_volume_min = 127 - 60,
410 .dac_volume_max = 127,
411 .function_flags = OXYGEN_FUNCTION_2WIRE,
412 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
413 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
414};
415
416int __devinit get_xonar_cs43xx_model(struct oxygen *chip,
417 const struct pci_device_id *id)
418{
419 switch (id->subdevice) {
420 case 0x834f:
421 chip->model = model_xonar_d1;
422 chip->model.shortname = "Xonar D1";
423 break;
424 case 0x8275:
425 case 0x8327:
426 chip->model = model_xonar_d1;
427 chip->model.shortname = "Xonar DX";
428 chip->model.init = xonar_dx_init;
429 break;
430 default:
431 return -EINVAL;
432 }
433 return 0;
434}
diff --git a/sound/pci/oxygen/xonar_hdmi.c b/sound/pci/oxygen/xonar_hdmi.c
new file mode 100644
index 000000000000..b12db1f1cea9
--- /dev/null
+++ b/sound/pci/oxygen/xonar_hdmi.c
@@ -0,0 +1,128 @@
1/*
2 * helper functions for HDMI models (Xonar HDAV1.3)
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/pci.h>
20#include <linux/delay.h>
21#include <sound/asoundef.h>
22#include <sound/control.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/tlv.h>
27#include "xonar.h"
28
29static void hdmi_write_command(struct oxygen *chip, u8 command,
30 unsigned int count, const u8 *params)
31{
32 unsigned int i;
33 u8 checksum;
34
35 oxygen_write_uart(chip, 0xfb);
36 oxygen_write_uart(chip, 0xef);
37 oxygen_write_uart(chip, command);
38 oxygen_write_uart(chip, count);
39 for (i = 0; i < count; ++i)
40 oxygen_write_uart(chip, params[i]);
41 checksum = 0xfb + 0xef + command + count;
42 for (i = 0; i < count; ++i)
43 checksum += params[i];
44 oxygen_write_uart(chip, checksum);
45}
46
47static void xonar_hdmi_init_commands(struct oxygen *chip,
48 struct xonar_hdmi *hdmi)
49{
50 u8 param;
51
52 oxygen_reset_uart(chip);
53 param = 0;
54 hdmi_write_command(chip, 0x61, 1, &param);
55 param = 1;
56 hdmi_write_command(chip, 0x74, 1, &param);
57 hdmi_write_command(chip, 0x54, 5, hdmi->params);
58}
59
60void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *hdmi)
61{
62 hdmi->params[1] = IEC958_AES3_CON_FS_48000;
63 hdmi->params[4] = 1;
64 xonar_hdmi_init_commands(chip, hdmi);
65}
66
67void xonar_hdmi_cleanup(struct oxygen *chip)
68{
69 u8 param = 0;
70
71 hdmi_write_command(chip, 0x74, 1, &param);
72}
73
74void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi)
75{
76 xonar_hdmi_init_commands(chip, hdmi);
77}
78
79void xonar_hdmi_pcm_hardware_filter(unsigned int channel,
80 struct snd_pcm_hardware *hardware)
81{
82 if (channel == PCM_MULTICH) {
83 hardware->rates = SNDRV_PCM_RATE_44100 |
84 SNDRV_PCM_RATE_48000 |
85 SNDRV_PCM_RATE_96000 |
86 SNDRV_PCM_RATE_192000;
87 hardware->rate_min = 44100;
88 }
89}
90
91void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi,
92 struct snd_pcm_hw_params *params)
93{
94 hdmi->params[0] = 0; /* 1 = non-audio */
95 switch (params_rate(params)) {
96 case 44100:
97 hdmi->params[1] = IEC958_AES3_CON_FS_44100;
98 break;
99 case 48000:
100 hdmi->params[1] = IEC958_AES3_CON_FS_48000;
101 break;
102 default: /* 96000 */
103 hdmi->params[1] = IEC958_AES3_CON_FS_96000;
104 break;
105 case 192000:
106 hdmi->params[1] = IEC958_AES3_CON_FS_192000;
107 break;
108 }
109 hdmi->params[2] = params_channels(params) / 2 - 1;
110 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
111 hdmi->params[3] = 0;
112 else
113 hdmi->params[3] = 0xc0;
114 hdmi->params[4] = 1; /* ? */
115 hdmi_write_command(chip, 0x54, 5, hdmi->params);
116}
117
118void xonar_hdmi_uart_input(struct oxygen *chip)
119{
120 if (chip->uart_input_count >= 2 &&
121 chip->uart_input[chip->uart_input_count - 2] == 'O' &&
122 chip->uart_input[chip->uart_input_count - 1] == 'K') {
123 printk(KERN_DEBUG "message from HDMI chip received:\n");
124 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
125 chip->uart_input, chip->uart_input_count);
126 chip->uart_input_count = 0;
127 }
128}
diff --git a/sound/pci/oxygen/xonar_lib.c b/sound/pci/oxygen/xonar_lib.c
new file mode 100644
index 000000000000..b3ff71316653
--- /dev/null
+++ b/sound/pci/oxygen/xonar_lib.c
@@ -0,0 +1,132 @@
1/*
2 * helper functions for Asus Xonar cards
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/delay.h>
20#include <sound/core.h>
21#include <sound/control.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include "xonar.h"
25
26
27#define GPIO_CS53x1_M_MASK 0x000c
28#define GPIO_CS53x1_M_SINGLE 0x0000
29#define GPIO_CS53x1_M_DOUBLE 0x0004
30#define GPIO_CS53x1_M_QUAD 0x0008
31
32
33void xonar_enable_output(struct oxygen *chip)
34{
35 struct xonar_generic *data = chip->model_data;
36
37 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
38 msleep(data->anti_pop_delay);
39 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
40}
41
42void xonar_disable_output(struct oxygen *chip)
43{
44 struct xonar_generic *data = chip->model_data;
45
46 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
47}
48
49static void xonar_ext_power_gpio_changed(struct oxygen *chip)
50{
51 struct xonar_generic *data = chip->model_data;
52 u8 has_power;
53
54 has_power = !!(oxygen_read8(chip, data->ext_power_reg)
55 & data->ext_power_bit);
56 if (has_power != data->has_power) {
57 data->has_power = has_power;
58 if (has_power) {
59 snd_printk(KERN_NOTICE "power restored\n");
60 } else {
61 snd_printk(KERN_CRIT
62 "Hey! Don't unplug the power cable!\n");
63 /* TODO: stop PCMs */
64 }
65 }
66}
67
68void xonar_init_ext_power(struct oxygen *chip)
69{
70 struct xonar_generic *data = chip->model_data;
71
72 oxygen_set_bits8(chip, data->ext_power_int_reg,
73 data->ext_power_bit);
74 chip->interrupt_mask |= OXYGEN_INT_GPIO;
75 chip->model.gpio_changed = xonar_ext_power_gpio_changed;
76 data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
77 & data->ext_power_bit);
78}
79
80void xonar_init_cs53x1(struct oxygen *chip)
81{
82 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
83 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
84 GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
85}
86
87void xonar_set_cs53x1_params(struct oxygen *chip,
88 struct snd_pcm_hw_params *params)
89{
90 unsigned int value;
91
92 if (params_rate(params) <= 54000)
93 value = GPIO_CS53x1_M_SINGLE;
94 else if (params_rate(params) <= 108000)
95 value = GPIO_CS53x1_M_DOUBLE;
96 else
97 value = GPIO_CS53x1_M_QUAD;
98 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
99 value, GPIO_CS53x1_M_MASK);
100}
101
102int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl,
103 struct snd_ctl_elem_value *value)
104{
105 struct oxygen *chip = ctl->private_data;
106 u16 bit = ctl->private_value;
107
108 value->value.integer.value[0] =
109 !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit);
110 return 0;
111}
112
113int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl,
114 struct snd_ctl_elem_value *value)
115{
116 struct oxygen *chip = ctl->private_data;
117 u16 bit = ctl->private_value;
118 u16 old_bits, new_bits;
119 int changed;
120
121 spin_lock_irq(&chip->reg_lock);
122 old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
123 if (value->value.integer.value[0])
124 new_bits = old_bits | bit;
125 else
126 new_bits = old_bits & ~bit;
127 changed = new_bits != old_bits;
128 if (changed)
129 oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
130 spin_unlock_irq(&chip->reg_lock);
131 return changed;
132}
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
new file mode 100644
index 000000000000..ba18fb546b4f
--- /dev/null
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -0,0 +1,1115 @@
1/*
2 * card driver for models with PCM1796 DACs (Xonar D2/D2X/HDAV1.3/ST/STX)
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Xonar D2/D2X
21 * ------------
22 *
23 * CMI8788:
24 *
25 * SPI 0 -> 1st PCM1796 (front)
26 * SPI 1 -> 2nd PCM1796 (surround)
27 * SPI 2 -> 3rd PCM1796 (center/LFE)
28 * SPI 4 -> 4th PCM1796 (back)
29 *
30 * GPIO 2 -> M0 of CS5381
31 * GPIO 3 -> M1 of CS5381
32 * GPIO 5 <- external power present (D2X only)
33 * GPIO 7 -> ALT
34 * GPIO 8 -> enable output to speakers
35 *
36 * CM9780:
37 *
38 * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
39 */
40
41/*
42 * Xonar HDAV1.3 (Deluxe)
43 * ----------------------
44 *
45 * CMI8788:
46 *
47 * I²C <-> PCM1796 (front)
48 *
49 * GPI 0 <- external power present
50 *
51 * GPIO 0 -> enable output to speakers
52 * GPIO 2 -> M0 of CS5381
53 * GPIO 3 -> M1 of CS5381
54 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
55 *
56 * TXD -> HDMI controller
57 * RXD <- HDMI controller
58 *
59 * PCM1796 front: AD1,0 <- 0,0
60 *
61 * CM9780:
62 *
63 * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
64 *
65 * no daughterboard
66 * ----------------
67 *
68 * GPIO 4 <- 1
69 *
70 * H6 daughterboard
71 * ----------------
72 *
73 * GPIO 4 <- 0
74 * GPIO 5 <- 0
75 *
76 * I²C <-> PCM1796 (surround)
77 * <-> PCM1796 (center/LFE)
78 * <-> PCM1796 (back)
79 *
80 * PCM1796 surround: AD1,0 <- 0,1
81 * PCM1796 center/LFE: AD1,0 <- 1,0
82 * PCM1796 back: AD1,0 <- 1,1
83 *
84 * unknown daughterboard
85 * ---------------------
86 *
87 * GPIO 4 <- 0
88 * GPIO 5 <- 1
89 *
90 * I²C <-> CS4362A (surround, center/LFE, back)
91 *
92 * CS4362A: AD0 <- 0
93 */
94
95/*
96 * Xonar Essence ST (Deluxe)/STX
97 * -----------------------------
98 *
99 * CMI8788:
100 *
101 * I²C <-> PCM1792A
102 * <-> CS2000 (ST only)
103 *
104 * ADC1 MCLK -> REF_CLK of CS2000 (ST only)
105 *
106 * GPI 0 <- external power present (STX only)
107 *
108 * GPIO 0 -> enable output to speakers
109 * GPIO 1 -> route HP to front panel (0) or rear jack (1)
110 * GPIO 2 -> M0 of CS5381
111 * GPIO 3 -> M1 of CS5381
112 * GPIO 7 -> route output to speaker jacks (0) or HP (1)
113 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
114 *
115 * PCM1792A:
116 *
117 * AD1,0 <- 0,0
118 * SCK <- CLK_OUT of CS2000 (ST only)
119 *
120 * CS2000:
121 *
122 * AD0 <- 0
123 *
124 * CM9780:
125 *
126 * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
127 *
128 * H6 daughterboard
129 * ----------------
130 *
131 * GPIO 4 <- 0
132 * GPIO 5 <- 0
133 */
134
135#include <linux/pci.h>
136#include <linux/delay.h>
137#include <linux/mutex.h>
138#include <sound/ac97_codec.h>
139#include <sound/control.h>
140#include <sound/core.h>
141#include <sound/pcm.h>
142#include <sound/pcm_params.h>
143#include <sound/tlv.h>
144#include "xonar.h"
145#include "cm9780.h"
146#include "pcm1796.h"
147#include "cs2000.h"
148
149
150#define GPIO_D2X_EXT_POWER 0x0020
151#define GPIO_D2_ALT 0x0080
152#define GPIO_D2_OUTPUT_ENABLE 0x0100
153
154#define GPI_EXT_POWER 0x01
155#define GPIO_INPUT_ROUTE 0x0100
156
157#define GPIO_HDAV_OUTPUT_ENABLE 0x0001
158
159#define GPIO_DB_MASK 0x0030
160#define GPIO_DB_H6 0x0000
161
162#define GPIO_ST_OUTPUT_ENABLE 0x0001
163#define GPIO_ST_HP_REAR 0x0002
164#define GPIO_ST_HP 0x0080
165
166#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */
167#define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */
168
169#define PCM1796_REG_BASE 16
170
171
172struct xonar_pcm179x {
173 struct xonar_generic generic;
174 unsigned int dacs;
175 u8 pcm1796_regs[4][5];
176 unsigned int current_rate;
177 bool os_128;
178 bool hp_active;
179 s8 hp_gain_offset;
180 bool has_cs2000;
181 u8 cs2000_fun_cfg_1;
182};
183
184struct xonar_hdav {
185 struct xonar_pcm179x pcm179x;
186 struct xonar_hdmi hdmi;
187};
188
189
190static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
191 u8 reg, u8 value)
192{
193 /* maps ALSA channel pair number to SPI output */
194 static const u8 codec_map[4] = {
195 0, 1, 2, 4
196 };
197 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
198 OXYGEN_SPI_DATA_LENGTH_2 |
199 OXYGEN_SPI_CLOCK_160 |
200 (codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
201 OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
202 (reg << 8) | value);
203}
204
205static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec,
206 u8 reg, u8 value)
207{
208 oxygen_write_i2c(chip, I2C_DEVICE_PCM1796(codec), reg, value);
209}
210
211static void pcm1796_write(struct oxygen *chip, unsigned int codec,
212 u8 reg, u8 value)
213{
214 struct xonar_pcm179x *data = chip->model_data;
215
216 if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) ==
217 OXYGEN_FUNCTION_SPI)
218 pcm1796_write_spi(chip, codec, reg, value);
219 else
220 pcm1796_write_i2c(chip, codec, reg, value);
221 if ((unsigned int)(reg - PCM1796_REG_BASE)
222 < ARRAY_SIZE(data->pcm1796_regs[codec]))
223 data->pcm1796_regs[codec][reg - PCM1796_REG_BASE] = value;
224}
225
226static void pcm1796_write_cached(struct oxygen *chip, unsigned int codec,
227 u8 reg, u8 value)
228{
229 struct xonar_pcm179x *data = chip->model_data;
230
231 if (value != data->pcm1796_regs[codec][reg - PCM1796_REG_BASE])
232 pcm1796_write(chip, codec, reg, value);
233}
234
235static void cs2000_write(struct oxygen *chip, u8 reg, u8 value)
236{
237 struct xonar_pcm179x *data = chip->model_data;
238
239 oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value);
240 if (reg == CS2000_FUN_CFG_1)
241 data->cs2000_fun_cfg_1 = value;
242}
243
244static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value)
245{
246 struct xonar_pcm179x *data = chip->model_data;
247
248 if (reg != CS2000_FUN_CFG_1 ||
249 value != data->cs2000_fun_cfg_1)
250 cs2000_write(chip, reg, value);
251}
252
253static void pcm1796_registers_init(struct oxygen *chip)
254{
255 struct xonar_pcm179x *data = chip->model_data;
256 unsigned int i;
257 s8 gain_offset;
258
259 gain_offset = data->hp_active ? data->hp_gain_offset : 0;
260 for (i = 0; i < data->dacs; ++i) {
261 /* set ATLD before ATL/ATR */
262 pcm1796_write(chip, i, 18,
263 data->pcm1796_regs[0][18 - PCM1796_REG_BASE]);
264 pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]
265 + gain_offset);
266 pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]
267 + gain_offset);
268 pcm1796_write(chip, i, 19,
269 data->pcm1796_regs[0][19 - PCM1796_REG_BASE]);
270 pcm1796_write(chip, i, 20,
271 data->pcm1796_regs[0][20 - PCM1796_REG_BASE]);
272 pcm1796_write(chip, i, 21, 0);
273 }
274}
275
276static void pcm1796_init(struct oxygen *chip)
277{
278 struct xonar_pcm179x *data = chip->model_data;
279
280 data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE |
281 PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
282 data->pcm1796_regs[0][19 - PCM1796_REG_BASE] =
283 PCM1796_FLT_SHARP | PCM1796_ATS_1;
284 data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64;
285 pcm1796_registers_init(chip);
286 data->current_rate = 48000;
287}
288
289static void xonar_d2_init(struct oxygen *chip)
290{
291 struct xonar_pcm179x *data = chip->model_data;
292
293 data->generic.anti_pop_delay = 300;
294 data->generic.output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
295 data->dacs = 4;
296
297 pcm1796_init(chip);
298
299 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
300 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
301
302 oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
303
304 xonar_init_cs53x1(chip);
305 xonar_enable_output(chip);
306
307 snd_component_add(chip->card, "PCM1796");
308 snd_component_add(chip->card, "CS5381");
309}
310
311static void xonar_d2x_init(struct oxygen *chip)
312{
313 struct xonar_pcm179x *data = chip->model_data;
314
315 data->generic.ext_power_reg = OXYGEN_GPIO_DATA;
316 data->generic.ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
317 data->generic.ext_power_bit = GPIO_D2X_EXT_POWER;
318 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
319 xonar_init_ext_power(chip);
320 xonar_d2_init(chip);
321}
322
323static void xonar_hdav_init(struct oxygen *chip)
324{
325 struct xonar_hdav *data = chip->model_data;
326
327 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
328 OXYGEN_2WIRE_LENGTH_8 |
329 OXYGEN_2WIRE_INTERRUPT_MASK |
330 OXYGEN_2WIRE_SPEED_FAST);
331
332 data->pcm179x.generic.anti_pop_delay = 100;
333 data->pcm179x.generic.output_enable_bit = GPIO_HDAV_OUTPUT_ENABLE;
334 data->pcm179x.generic.ext_power_reg = OXYGEN_GPI_DATA;
335 data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
336 data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER;
337 data->pcm179x.dacs = chip->model.private_data ? 4 : 1;
338
339 pcm1796_init(chip);
340
341 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_INPUT_ROUTE);
342 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE);
343
344 xonar_init_cs53x1(chip);
345 xonar_init_ext_power(chip);
346 xonar_hdmi_init(chip, &data->hdmi);
347 xonar_enable_output(chip);
348
349 snd_component_add(chip->card, "PCM1796");
350 snd_component_add(chip->card, "CS5381");
351}
352
353static void xonar_st_init_i2c(struct oxygen *chip)
354{
355 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
356 OXYGEN_2WIRE_LENGTH_8 |
357 OXYGEN_2WIRE_INTERRUPT_MASK |
358 OXYGEN_2WIRE_SPEED_FAST);
359}
360
361static void xonar_st_init_common(struct oxygen *chip)
362{
363 struct xonar_pcm179x *data = chip->model_data;
364
365 data->generic.anti_pop_delay = 100;
366 data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE;
367 data->dacs = chip->model.private_data ? 4 : 1;
368 data->hp_gain_offset = 2*-18;
369
370 pcm1796_init(chip);
371
372 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
373 GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
374 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
375 GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
376
377 xonar_init_cs53x1(chip);
378 xonar_enable_output(chip);
379
380 snd_component_add(chip->card, "PCM1792A");
381 snd_component_add(chip->card, "CS5381");
382}
383
384static void cs2000_registers_init(struct oxygen *chip)
385{
386 struct xonar_pcm179x *data = chip->model_data;
387
388 cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_FREEZE);
389 cs2000_write(chip, CS2000_DEV_CTRL, 0);
390 cs2000_write(chip, CS2000_DEV_CFG_1,
391 CS2000_R_MOD_SEL_1 |
392 (0 << CS2000_R_SEL_SHIFT) |
393 CS2000_AUX_OUT_SRC_REF_CLK |
394 CS2000_EN_DEV_CFG_1);
395 cs2000_write(chip, CS2000_DEV_CFG_2,
396 (0 << CS2000_LOCK_CLK_SHIFT) |
397 CS2000_FRAC_N_SRC_STATIC);
398 cs2000_write(chip, CS2000_RATIO_0 + 0, 0x00); /* 1.0 */
399 cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10);
400 cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00);
401 cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00);
402 cs2000_write(chip, CS2000_FUN_CFG_1, data->cs2000_fun_cfg_1);
403 cs2000_write(chip, CS2000_FUN_CFG_2, 0);
404 cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2);
405}
406
407static void xonar_st_init(struct oxygen *chip)
408{
409 struct xonar_pcm179x *data = chip->model_data;
410
411 data->has_cs2000 = 1;
412 data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1;
413
414 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
415 OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_I2S |
416 OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
417 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
418
419 xonar_st_init_i2c(chip);
420 cs2000_registers_init(chip);
421 xonar_st_init_common(chip);
422
423 snd_component_add(chip->card, "CS2000");
424}
425
426static void xonar_stx_init(struct oxygen *chip)
427{
428 struct xonar_pcm179x *data = chip->model_data;
429
430 xonar_st_init_i2c(chip);
431 data->generic.ext_power_reg = OXYGEN_GPI_DATA;
432 data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
433 data->generic.ext_power_bit = GPI_EXT_POWER;
434 xonar_init_ext_power(chip);
435 xonar_st_init_common(chip);
436}
437
438static void xonar_d2_cleanup(struct oxygen *chip)
439{
440 xonar_disable_output(chip);
441}
442
443static void xonar_hdav_cleanup(struct oxygen *chip)
444{
445 xonar_hdmi_cleanup(chip);
446 xonar_disable_output(chip);
447 msleep(2);
448}
449
450static void xonar_st_cleanup(struct oxygen *chip)
451{
452 xonar_disable_output(chip);
453}
454
455static void xonar_d2_suspend(struct oxygen *chip)
456{
457 xonar_d2_cleanup(chip);
458}
459
460static void xonar_hdav_suspend(struct oxygen *chip)
461{
462 xonar_hdav_cleanup(chip);
463}
464
465static void xonar_st_suspend(struct oxygen *chip)
466{
467 xonar_st_cleanup(chip);
468}
469
470static void xonar_d2_resume(struct oxygen *chip)
471{
472 pcm1796_registers_init(chip);
473 xonar_enable_output(chip);
474}
475
476static void xonar_hdav_resume(struct oxygen *chip)
477{
478 struct xonar_hdav *data = chip->model_data;
479
480 pcm1796_registers_init(chip);
481 xonar_hdmi_resume(chip, &data->hdmi);
482 xonar_enable_output(chip);
483}
484
485static void xonar_stx_resume(struct oxygen *chip)
486{
487 pcm1796_registers_init(chip);
488 xonar_enable_output(chip);
489}
490
491static void xonar_st_resume(struct oxygen *chip)
492{
493 cs2000_registers_init(chip);
494 xonar_stx_resume(chip);
495}
496
497static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate)
498{
499 struct xonar_pcm179x *data = chip->model_data;
500
501 if (rate <= 32000)
502 return OXYGEN_I2S_MCLK_512;
503 else if (rate <= 48000 && data->os_128)
504 return OXYGEN_I2S_MCLK_512;
505 else if (rate <= 96000)
506 return OXYGEN_I2S_MCLK_256;
507 else
508 return OXYGEN_I2S_MCLK_128;
509}
510
511static unsigned int get_pcm1796_i2s_mclk(struct oxygen *chip,
512 unsigned int channel,
513 struct snd_pcm_hw_params *params)
514{
515 if (channel == PCM_MULTICH)
516 return mclk_from_rate(chip, params_rate(params));
517 else
518 return oxygen_default_i2s_mclk(chip, channel, params);
519}
520
521static void update_pcm1796_oversampling(struct oxygen *chip)
522{
523 struct xonar_pcm179x *data = chip->model_data;
524 unsigned int i;
525 u8 reg;
526
527 if (data->current_rate <= 32000)
528 reg = PCM1796_OS_128;
529 else if (data->current_rate <= 48000 && data->os_128)
530 reg = PCM1796_OS_128;
531 else if (data->current_rate <= 96000 || data->os_128)
532 reg = PCM1796_OS_64;
533 else
534 reg = PCM1796_OS_32;
535 for (i = 0; i < data->dacs; ++i)
536 pcm1796_write_cached(chip, i, 20, reg);
537}
538
539static void set_pcm1796_params(struct oxygen *chip,
540 struct snd_pcm_hw_params *params)
541{
542 struct xonar_pcm179x *data = chip->model_data;
543
544 data->current_rate = params_rate(params);
545 update_pcm1796_oversampling(chip);
546}
547
548static void update_pcm1796_volume(struct oxygen *chip)
549{
550 struct xonar_pcm179x *data = chip->model_data;
551 unsigned int i;
552 s8 gain_offset;
553
554 gain_offset = data->hp_active ? data->hp_gain_offset : 0;
555 for (i = 0; i < data->dacs; ++i) {
556 pcm1796_write_cached(chip, i, 16, chip->dac_volume[i * 2]
557 + gain_offset);
558 pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1]
559 + gain_offset);
560 }
561}
562
563static void update_pcm1796_mute(struct oxygen *chip)
564{
565 struct xonar_pcm179x *data = chip->model_data;
566 unsigned int i;
567 u8 value;
568
569 value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
570 if (chip->dac_mute)
571 value |= PCM1796_MUTE;
572 for (i = 0; i < data->dacs; ++i)
573 pcm1796_write_cached(chip, i, 18, value);
574}
575
576static void update_cs2000_rate(struct oxygen *chip, unsigned int rate)
577{
578 struct xonar_pcm179x *data = chip->model_data;
579 u8 rate_mclk, reg;
580
581 switch (rate) {
582 /* XXX Why is the I2S A MCLK half the actual I2S MCLK? */
583 case 32000:
584 rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
585 break;
586 case 44100:
587 if (data->os_128)
588 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
589 else
590 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128;
591 break;
592 default: /* 48000 */
593 if (data->os_128)
594 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
595 else
596 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128;
597 break;
598 case 64000:
599 rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
600 break;
601 case 88200:
602 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
603 break;
604 case 96000:
605 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
606 break;
607 case 176400:
608 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
609 break;
610 case 192000:
611 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
612 break;
613 }
614 oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk,
615 OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK);
616 if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128)
617 reg = CS2000_REF_CLK_DIV_1;
618 else
619 reg = CS2000_REF_CLK_DIV_2;
620 cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg);
621}
622
623static void set_st_params(struct oxygen *chip,
624 struct snd_pcm_hw_params *params)
625{
626 update_cs2000_rate(chip, params_rate(params));
627 set_pcm1796_params(chip, params);
628}
629
630static void set_hdav_params(struct oxygen *chip,
631 struct snd_pcm_hw_params *params)
632{
633 struct xonar_hdav *data = chip->model_data;
634
635 set_pcm1796_params(chip, params);
636 xonar_set_hdmi_params(chip, &data->hdmi, params);
637}
638
639static const struct snd_kcontrol_new alt_switch = {
640 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
641 .name = "Analog Loopback Switch",
642 .info = snd_ctl_boolean_mono_info,
643 .get = xonar_gpio_bit_switch_get,
644 .put = xonar_gpio_bit_switch_put,
645 .private_value = GPIO_D2_ALT,
646};
647
648static int rolloff_info(struct snd_kcontrol *ctl,
649 struct snd_ctl_elem_info *info)
650{
651 static const char *const names[2] = {
652 "Sharp Roll-off", "Slow Roll-off"
653 };
654
655 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
656 info->count = 1;
657 info->value.enumerated.items = 2;
658 if (info->value.enumerated.item >= 2)
659 info->value.enumerated.item = 1;
660 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
661 return 0;
662}
663
664static int rolloff_get(struct snd_kcontrol *ctl,
665 struct snd_ctl_elem_value *value)
666{
667 struct oxygen *chip = ctl->private_data;
668 struct xonar_pcm179x *data = chip->model_data;
669
670 value->value.enumerated.item[0] =
671 (data->pcm1796_regs[0][19 - PCM1796_REG_BASE] &
672 PCM1796_FLT_MASK) != PCM1796_FLT_SHARP;
673 return 0;
674}
675
676static int rolloff_put(struct snd_kcontrol *ctl,
677 struct snd_ctl_elem_value *value)
678{
679 struct oxygen *chip = ctl->private_data;
680 struct xonar_pcm179x *data = chip->model_data;
681 unsigned int i;
682 int changed;
683 u8 reg;
684
685 mutex_lock(&chip->mutex);
686 reg = data->pcm1796_regs[0][19 - PCM1796_REG_BASE];
687 reg &= ~PCM1796_FLT_MASK;
688 if (!value->value.enumerated.item[0])
689 reg |= PCM1796_FLT_SHARP;
690 else
691 reg |= PCM1796_FLT_SLOW;
692 changed = reg != data->pcm1796_regs[0][19 - PCM1796_REG_BASE];
693 if (changed) {
694 for (i = 0; i < data->dacs; ++i)
695 pcm1796_write(chip, i, 19, reg);
696 }
697 mutex_unlock(&chip->mutex);
698 return changed;
699}
700
701static const struct snd_kcontrol_new rolloff_control = {
702 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
703 .name = "DAC Filter Playback Enum",
704 .info = rolloff_info,
705 .get = rolloff_get,
706 .put = rolloff_put,
707};
708
709static int os_128_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
710{
711 static const char *const names[2] = { "64x", "128x" };
712
713 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
714 info->count = 1;
715 info->value.enumerated.items = 2;
716 if (info->value.enumerated.item >= 2)
717 info->value.enumerated.item = 1;
718 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
719 return 0;
720}
721
722static int os_128_get(struct snd_kcontrol *ctl,
723 struct snd_ctl_elem_value *value)
724{
725 struct oxygen *chip = ctl->private_data;
726 struct xonar_pcm179x *data = chip->model_data;
727
728 value->value.enumerated.item[0] = data->os_128;
729 return 0;
730}
731
732static int os_128_put(struct snd_kcontrol *ctl,
733 struct snd_ctl_elem_value *value)
734{
735 struct oxygen *chip = ctl->private_data;
736 struct xonar_pcm179x *data = chip->model_data;
737 int changed;
738
739 mutex_lock(&chip->mutex);
740 changed = value->value.enumerated.item[0] != data->os_128;
741 if (changed) {
742 data->os_128 = value->value.enumerated.item[0];
743 if (data->has_cs2000)
744 update_cs2000_rate(chip, data->current_rate);
745 oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
746 mclk_from_rate(chip, data->current_rate),
747 OXYGEN_I2S_MCLK_MASK);
748 update_pcm1796_oversampling(chip);
749 }
750 mutex_unlock(&chip->mutex);
751 return changed;
752}
753
754static const struct snd_kcontrol_new os_128_control = {
755 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
756 .name = "DAC Oversampling Playback Enum",
757 .info = os_128_info,
758 .get = os_128_get,
759 .put = os_128_put,
760};
761
762static int st_output_switch_info(struct snd_kcontrol *ctl,
763 struct snd_ctl_elem_info *info)
764{
765 static const char *const names[3] = {
766 "Speakers", "Headphones", "FP Headphones"
767 };
768
769 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
770 info->count = 1;
771 info->value.enumerated.items = 3;
772 if (info->value.enumerated.item >= 3)
773 info->value.enumerated.item = 2;
774 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
775 return 0;
776}
777
778static int st_output_switch_get(struct snd_kcontrol *ctl,
779 struct snd_ctl_elem_value *value)
780{
781 struct oxygen *chip = ctl->private_data;
782 u16 gpio;
783
784 gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
785 if (!(gpio & GPIO_ST_HP))
786 value->value.enumerated.item[0] = 0;
787 else if (gpio & GPIO_ST_HP_REAR)
788 value->value.enumerated.item[0] = 1;
789 else
790 value->value.enumerated.item[0] = 2;
791 return 0;
792}
793
794
795static int st_output_switch_put(struct snd_kcontrol *ctl,
796 struct snd_ctl_elem_value *value)
797{
798 struct oxygen *chip = ctl->private_data;
799 struct xonar_pcm179x *data = chip->model_data;
800 u16 gpio_old, gpio;
801
802 mutex_lock(&chip->mutex);
803 gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
804 gpio = gpio_old;
805 switch (value->value.enumerated.item[0]) {
806 case 0:
807 gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
808 break;
809 case 1:
810 gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
811 break;
812 case 2:
813 gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
814 break;
815 }
816 oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
817 data->hp_active = gpio & GPIO_ST_HP;
818 update_pcm1796_volume(chip);
819 mutex_unlock(&chip->mutex);
820 return gpio != gpio_old;
821}
822
823static int st_hp_volume_offset_info(struct snd_kcontrol *ctl,
824 struct snd_ctl_elem_info *info)
825{
826 static const char *const names[3] = {
827 "< 64 ohms", "64-300 ohms", "300-600 ohms"
828 };
829
830 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
831 info->count = 1;
832 info->value.enumerated.items = 3;
833 if (info->value.enumerated.item > 2)
834 info->value.enumerated.item = 2;
835 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
836 return 0;
837}
838
839static int st_hp_volume_offset_get(struct snd_kcontrol *ctl,
840 struct snd_ctl_elem_value *value)
841{
842 struct oxygen *chip = ctl->private_data;
843 struct xonar_pcm179x *data = chip->model_data;
844
845 mutex_lock(&chip->mutex);
846 if (data->hp_gain_offset < 2*-6)
847 value->value.enumerated.item[0] = 0;
848 else if (data->hp_gain_offset < 0)
849 value->value.enumerated.item[0] = 1;
850 else
851 value->value.enumerated.item[0] = 2;
852 mutex_unlock(&chip->mutex);
853 return 0;
854}
855
856
857static int st_hp_volume_offset_put(struct snd_kcontrol *ctl,
858 struct snd_ctl_elem_value *value)
859{
860 static const s8 offsets[] = { 2*-18, 2*-6, 0 };
861 struct oxygen *chip = ctl->private_data;
862 struct xonar_pcm179x *data = chip->model_data;
863 s8 offset;
864 int changed;
865
866 if (value->value.enumerated.item[0] > 2)
867 return -EINVAL;
868 offset = offsets[value->value.enumerated.item[0]];
869 mutex_lock(&chip->mutex);
870 changed = offset != data->hp_gain_offset;
871 if (changed) {
872 data->hp_gain_offset = offset;
873 update_pcm1796_volume(chip);
874 }
875 mutex_unlock(&chip->mutex);
876 return changed;
877}
878
879static const struct snd_kcontrol_new st_controls[] = {
880 {
881 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
882 .name = "Analog Output",
883 .info = st_output_switch_info,
884 .get = st_output_switch_get,
885 .put = st_output_switch_put,
886 },
887 {
888 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
889 .name = "Headphones Impedance Playback Enum",
890 .info = st_hp_volume_offset_info,
891 .get = st_hp_volume_offset_get,
892 .put = st_hp_volume_offset_put,
893 },
894};
895
896static void xonar_line_mic_ac97_switch(struct oxygen *chip,
897 unsigned int reg, unsigned int mute)
898{
899 if (reg == AC97_LINE) {
900 spin_lock_irq(&chip->reg_lock);
901 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
902 mute ? GPIO_INPUT_ROUTE : 0,
903 GPIO_INPUT_ROUTE);
904 spin_unlock_irq(&chip->reg_lock);
905 }
906}
907
908static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0);
909
910static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
911{
912 if (!strncmp(template->name, "CD Capture ", 11))
913 /* CD in is actually connected to the video in pin */
914 template->private_value ^= AC97_CD ^ AC97_VIDEO;
915 return 0;
916}
917
918static int xonar_st_control_filter(struct snd_kcontrol_new *template)
919{
920 if (!strncmp(template->name, "CD Capture ", 11))
921 return 1; /* no CD input */
922 return 0;
923}
924
925static int add_pcm1796_controls(struct oxygen *chip)
926{
927 int err;
928
929 err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip));
930 if (err < 0)
931 return err;
932 err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip));
933 if (err < 0)
934 return err;
935 return 0;
936}
937
938static int xonar_d2_mixer_init(struct oxygen *chip)
939{
940 int err;
941
942 err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
943 if (err < 0)
944 return err;
945 err = add_pcm1796_controls(chip);
946 if (err < 0)
947 return err;
948 return 0;
949}
950
951static int xonar_hdav_mixer_init(struct oxygen *chip)
952{
953 return add_pcm1796_controls(chip);
954}
955
956static int xonar_st_mixer_init(struct oxygen *chip)
957{
958 unsigned int i;
959 int err;
960
961 for (i = 0; i < ARRAY_SIZE(st_controls); ++i) {
962 err = snd_ctl_add(chip->card,
963 snd_ctl_new1(&st_controls[i], chip));
964 if (err < 0)
965 return err;
966 }
967 err = add_pcm1796_controls(chip);
968 if (err < 0)
969 return err;
970 return 0;
971}
972
973static const struct oxygen_model model_xonar_d2 = {
974 .longname = "Asus Virtuoso 200",
975 .chip = "AV200",
976 .init = xonar_d2_init,
977 .control_filter = xonar_d2_control_filter,
978 .mixer_init = xonar_d2_mixer_init,
979 .cleanup = xonar_d2_cleanup,
980 .suspend = xonar_d2_suspend,
981 .resume = xonar_d2_resume,
982 .get_i2s_mclk = get_pcm1796_i2s_mclk,
983 .set_dac_params = set_pcm1796_params,
984 .set_adc_params = xonar_set_cs53x1_params,
985 .update_dac_volume = update_pcm1796_volume,
986 .update_dac_mute = update_pcm1796_mute,
987 .dac_tlv = pcm1796_db_scale,
988 .model_data_size = sizeof(struct xonar_pcm179x),
989 .device_config = PLAYBACK_0_TO_I2S |
990 PLAYBACK_1_TO_SPDIF |
991 CAPTURE_0_FROM_I2S_2 |
992 CAPTURE_1_FROM_SPDIF |
993 MIDI_OUTPUT |
994 MIDI_INPUT,
995 .dac_channels = 8,
996 .dac_volume_min = 255 - 2*60,
997 .dac_volume_max = 255,
998 .misc_flags = OXYGEN_MISC_MIDI,
999 .function_flags = OXYGEN_FUNCTION_SPI |
1000 OXYGEN_FUNCTION_ENABLE_SPI_4_5,
1001 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1002 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1003};
1004
1005static const struct oxygen_model model_xonar_hdav = {
1006 .longname = "Asus Virtuoso 200",
1007 .chip = "AV200",
1008 .init = xonar_hdav_init,
1009 .mixer_init = xonar_hdav_mixer_init,
1010 .cleanup = xonar_hdav_cleanup,
1011 .suspend = xonar_hdav_suspend,
1012 .resume = xonar_hdav_resume,
1013 .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter,
1014 .get_i2s_mclk = get_pcm1796_i2s_mclk,
1015 .set_dac_params = set_hdav_params,
1016 .set_adc_params = xonar_set_cs53x1_params,
1017 .update_dac_volume = update_pcm1796_volume,
1018 .update_dac_mute = update_pcm1796_mute,
1019 .uart_input = xonar_hdmi_uart_input,
1020 .ac97_switch = xonar_line_mic_ac97_switch,
1021 .dac_tlv = pcm1796_db_scale,
1022 .model_data_size = sizeof(struct xonar_hdav),
1023 .device_config = PLAYBACK_0_TO_I2S |
1024 PLAYBACK_1_TO_SPDIF |
1025 CAPTURE_0_FROM_I2S_2 |
1026 CAPTURE_1_FROM_SPDIF,
1027 .dac_channels = 8,
1028 .dac_volume_min = 255 - 2*60,
1029 .dac_volume_max = 255,
1030 .misc_flags = OXYGEN_MISC_MIDI,
1031 .function_flags = OXYGEN_FUNCTION_2WIRE,
1032 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1033 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1034};
1035
1036static const struct oxygen_model model_xonar_st = {
1037 .longname = "Asus Virtuoso 100",
1038 .chip = "AV200",
1039 .init = xonar_st_init,
1040 .control_filter = xonar_st_control_filter,
1041 .mixer_init = xonar_st_mixer_init,
1042 .cleanup = xonar_st_cleanup,
1043 .suspend = xonar_st_suspend,
1044 .resume = xonar_st_resume,
1045 .get_i2s_mclk = get_pcm1796_i2s_mclk,
1046 .set_dac_params = set_st_params,
1047 .set_adc_params = xonar_set_cs53x1_params,
1048 .update_dac_volume = update_pcm1796_volume,
1049 .update_dac_mute = update_pcm1796_mute,
1050 .ac97_switch = xonar_line_mic_ac97_switch,
1051 .dac_tlv = pcm1796_db_scale,
1052 .model_data_size = sizeof(struct xonar_pcm179x),
1053 .device_config = PLAYBACK_0_TO_I2S |
1054 PLAYBACK_1_TO_SPDIF |
1055 CAPTURE_0_FROM_I2S_2,
1056 .dac_channels = 2,
1057 .dac_volume_min = 255 - 2*60,
1058 .dac_volume_max = 255,
1059 .function_flags = OXYGEN_FUNCTION_2WIRE,
1060 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1061 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1062};
1063
1064int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
1065 const struct pci_device_id *id)
1066{
1067 switch (id->subdevice) {
1068 case 0x8269:
1069 chip->model = model_xonar_d2;
1070 chip->model.shortname = "Xonar D2";
1071 break;
1072 case 0x82b7:
1073 chip->model = model_xonar_d2;
1074 chip->model.shortname = "Xonar D2X";
1075 chip->model.init = xonar_d2x_init;
1076 break;
1077 case 0x8314:
1078 chip->model = model_xonar_hdav;
1079 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
1080 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) {
1081 default:
1082 chip->model.shortname = "Xonar HDAV1.3";
1083 break;
1084 case GPIO_DB_H6:
1085 chip->model.shortname = "Xonar HDAV1.3+H6";
1086 chip->model.private_data = 1;
1087 break;
1088 }
1089 break;
1090 case 0x835d:
1091 chip->model = model_xonar_st;
1092 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
1093 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) {
1094 default:
1095 chip->model.shortname = "Xonar ST";
1096 break;
1097 case GPIO_DB_H6:
1098 chip->model.shortname = "Xonar ST+H6";
1099 chip->model.dac_channels = 8;
1100 chip->model.private_data = 1;
1101 break;
1102 }
1103 break;
1104 case 0x835c:
1105 chip->model = model_xonar_st;
1106 chip->model.shortname = "Xonar STX";
1107 chip->model.init = xonar_stx_init;
1108 chip->model.resume = xonar_stx_resume;
1109 chip->model.set_dac_params = set_pcm1796_params;
1110 break;
1111 default:
1112 return -EINVAL;
1113 }
1114 return 0;
1115}
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 2cc0eda4f20e..2e156467b814 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -479,7 +479,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
479 479
480static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = { 480static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
481 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 481 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
482 .name = "PC Speaker Playback Volume", 482 .name = "Speaker Playback Volume",
483 .info = snd_pmac_awacs_info_volume_amp, 483 .info = snd_pmac_awacs_info_volume_amp,
484 .get = snd_pmac_awacs_get_volume_amp, 484 .get = snd_pmac_awacs_get_volume_amp,
485 .put = snd_pmac_awacs_put_volume_amp, 485 .put = snd_pmac_awacs_put_volume_amp,
@@ -525,7 +525,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
525 525
526static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = { 526static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = {
527 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 527 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
528 .name = "PC Speaker Playback Switch", 528 .name = "Speaker Playback Switch",
529 .info = snd_pmac_boolean_stereo_info, 529 .info = snd_pmac_boolean_stereo_info,
530 .get = snd_pmac_awacs_get_switch_amp, 530 .get = snd_pmac_awacs_get_switch_amp,
531 .put = snd_pmac_awacs_put_switch_amp, 531 .put = snd_pmac_awacs_put_switch_amp,
@@ -696,17 +696,17 @@ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata
696}; 696};
697 697
698static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = { 698static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = {
699 AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1), 699 AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
700}; 700};
701 701
702static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata = 702static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata =
703AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); 703AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
704 704
705static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata = 705static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata =
706AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 1); 706AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
707 707
708static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata = 708static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata =
709AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0); 709AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
710 710
711 711
712/* 712/*
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index 16ed240e423c..0accfe49735b 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -505,7 +505,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
505 MASK_ADDR_BURGUNDY_GAINLINE, 1, 0), 505 MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
506 BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0, 506 BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
507 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 507 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
508 BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0, 508 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0,
509 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 509 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
510 BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 510 BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
511 MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1), 511 MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
@@ -527,7 +527,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
527 MASK_ADDR_BURGUNDY_VOLMIC, 16), 527 MASK_ADDR_BURGUNDY_VOLMIC, 16),
528 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, 528 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
529 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 529 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
530 BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0, 530 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0,
531 MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1), 531 MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
532 BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 532 BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
533 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 533 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
@@ -549,11 +549,11 @@ BURGUNDY_SWITCH_B("Master Playback Switch", 0,
549 BURGUNDY_OUTPUT_INTERN 549 BURGUNDY_OUTPUT_INTERN
550 | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 550 | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
551static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata = 551static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata =
552BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0, 552BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
553 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 553 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
554 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 554 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
555static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata = 555static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata =
556BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0, 556BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
557 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 557 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
558 BURGUNDY_OUTPUT_INTERN, 0, 0); 558 BURGUNDY_OUTPUT_INTERN, 0, 0);
559static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata = 559static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata =
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 08e584d1453a..789f44f4ac78 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -905,7 +905,7 @@ static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
905}; 905};
906static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = { 906static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
907 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 907 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
908 .name = "PC Speaker Playback Switch", 908 .name = "Speaker Playback Switch",
909 .info = snd_pmac_boolean_mono_info, 909 .info = snd_pmac_boolean_mono_info,
910 .get = tumbler_get_mute_switch, 910 .get = tumbler_get_mute_switch,
911 .put = tumbler_put_mute_switch, 911 .put = tumbler_put_mute_switch,
diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig
index aed0f90c3919..61139f3c1614 100644
--- a/sound/sh/Kconfig
+++ b/sound/sh/Kconfig
@@ -19,5 +19,13 @@ config SND_AICA
19 help 19 help
20 ALSA Sound driver for the SEGA Dreamcast console. 20 ALSA Sound driver for the SEGA Dreamcast console.
21 21
22config SND_SH_DAC_AUDIO
23 tristate "SuperH DAC audio support"
24 depends on SND
25 depends on CPU_SH3 && HIGH_RES_TIMERS
26 select SND_PCM
27 help
28 Say Y here to include support for the on-chip DAC.
29
22endif # SND_SUPERH 30endif # SND_SUPERH
23 31
diff --git a/sound/sh/Makefile b/sound/sh/Makefile
index 8fdcb6e26f00..7d09b5188cf7 100644
--- a/sound/sh/Makefile
+++ b/sound/sh/Makefile
@@ -3,6 +3,8 @@
3# 3#
4 4
5snd-aica-objs := aica.o 5snd-aica-objs := aica.o
6snd-sh_dac_audio-objs := sh_dac_audio.o
6 7
7# Toplevel Module Dependency 8# Toplevel Module Dependency
8obj-$(CONFIG_SND_AICA) += snd-aica.o 9obj-$(CONFIG_SND_AICA) += snd-aica.o
10obj-$(CONFIG_SND_SH_DAC_AUDIO) += snd-sh_dac_audio.o
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
new file mode 100644
index 000000000000..76d9ad27d91c
--- /dev/null
+++ b/sound/sh/sh_dac_audio.c
@@ -0,0 +1,453 @@
1/*
2 * sh_dac_audio.c - SuperH DAC audio driver for ALSA
3 *
4 * Copyright (c) 2009 by Rafael Ignacio Zurita <rizurita@yahoo.com>
5 *
6 *
7 * Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include <linux/hrtimer.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/platform_device.h>
29#include <sound/core.h>
30#include <sound/initval.h>
31#include <sound/pcm.h>
32#include <sound/sh_dac_audio.h>
33#include <asm/clock.h>
34#include <asm/hd64461.h>
35#include <mach/hp6xx.h>
36#include <cpu/dac.h>
37
38MODULE_AUTHOR("Rafael Ignacio Zurita <rizurita@yahoo.com>");
39MODULE_DESCRIPTION("SuperH DAC audio driver");
40MODULE_LICENSE("GPL");
41MODULE_SUPPORTED_DEVICE("{{SuperH DAC audio support}}");
42
43/* Module Parameters */
44static int index = SNDRV_DEFAULT_IDX1;
45static char *id = SNDRV_DEFAULT_STR1;
46module_param(index, int, 0444);
47MODULE_PARM_DESC(index, "Index value for SuperH DAC audio.");
48module_param(id, charp, 0444);
49MODULE_PARM_DESC(id, "ID string for SuperH DAC audio.");
50
51/* main struct */
52struct snd_sh_dac {
53 struct snd_card *card;
54 struct snd_pcm_substream *substream;
55 struct hrtimer hrtimer;
56 ktime_t wakeups_per_second;
57
58 int rate;
59 int empty;
60 char *data_buffer, *buffer_begin, *buffer_end;
61 int processed; /* bytes proccesed, to compare with period_size */
62 int buffer_size;
63 struct dac_audio_pdata *pdata;
64};
65
66
67static void dac_audio_start_timer(struct snd_sh_dac *chip)
68{
69 hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
70 HRTIMER_MODE_REL);
71}
72
73static void dac_audio_stop_timer(struct snd_sh_dac *chip)
74{
75 hrtimer_cancel(&chip->hrtimer);
76}
77
78static void dac_audio_reset(struct snd_sh_dac *chip)
79{
80 dac_audio_stop_timer(chip);
81 chip->buffer_begin = chip->buffer_end = chip->data_buffer;
82 chip->processed = 0;
83 chip->empty = 1;
84}
85
86static void dac_audio_set_rate(struct snd_sh_dac *chip)
87{
88 chip->wakeups_per_second = ktime_set(0, 1000000000 / chip->rate);
89}
90
91
92/* PCM INTERFACE */
93
94static struct snd_pcm_hardware snd_sh_dac_pcm_hw = {
95 .info = (SNDRV_PCM_INFO_MMAP |
96 SNDRV_PCM_INFO_MMAP_VALID |
97 SNDRV_PCM_INFO_INTERLEAVED |
98 SNDRV_PCM_INFO_HALF_DUPLEX),
99 .formats = SNDRV_PCM_FMTBIT_U8,
100 .rates = SNDRV_PCM_RATE_8000,
101 .rate_min = 8000,
102 .rate_max = 8000,
103 .channels_min = 1,
104 .channels_max = 1,
105 .buffer_bytes_max = (48*1024),
106 .period_bytes_min = 1,
107 .period_bytes_max = (48*1024),
108 .periods_min = 1,
109 .periods_max = 1024,
110};
111
112static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream)
113{
114 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
115 struct snd_pcm_runtime *runtime = substream->runtime;
116
117 runtime->hw = snd_sh_dac_pcm_hw;
118
119 chip->substream = substream;
120 chip->buffer_begin = chip->buffer_end = chip->data_buffer;
121 chip->processed = 0;
122 chip->empty = 1;
123
124 chip->pdata->start(chip->pdata);
125
126 return 0;
127}
128
129static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream)
130{
131 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
132
133 chip->substream = NULL;
134
135 dac_audio_stop_timer(chip);
136 chip->pdata->stop(chip->pdata);
137
138 return 0;
139}
140
141static int snd_sh_dac_pcm_hw_params(struct snd_pcm_substream *substream,
142 struct snd_pcm_hw_params *hw_params)
143{
144 return snd_pcm_lib_malloc_pages(substream,
145 params_buffer_bytes(hw_params));
146}
147
148static int snd_sh_dac_pcm_hw_free(struct snd_pcm_substream *substream)
149{
150 return snd_pcm_lib_free_pages(substream);
151}
152
153static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream)
154{
155 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
156 struct snd_pcm_runtime *runtime = chip->substream->runtime;
157
158 chip->buffer_size = runtime->buffer_size;
159 memset(chip->data_buffer, 0, chip->pdata->buffer_size);
160
161 return 0;
162}
163
164static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
165{
166 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
167
168 switch (cmd) {
169 case SNDRV_PCM_TRIGGER_START:
170 dac_audio_start_timer(chip);
171 break;
172 case SNDRV_PCM_TRIGGER_STOP:
173 chip->buffer_begin = chip->buffer_end = chip->data_buffer;
174 chip->processed = 0;
175 chip->empty = 1;
176 dac_audio_stop_timer(chip);
177 break;
178 default:
179 return -EINVAL;
180 }
181
182 return 0;
183}
184
185static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel,
186 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
187{
188 /* channel is not used (interleaved data) */
189 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
190 struct snd_pcm_runtime *runtime = substream->runtime;
191 ssize_t b_count = frames_to_bytes(runtime , count);
192 ssize_t b_pos = frames_to_bytes(runtime , pos);
193
194 if (count < 0)
195 return -EINVAL;
196
197 if (!count)
198 return 0;
199
200 memcpy_toio(chip->data_buffer + b_pos, src, b_count);
201 chip->buffer_end = chip->data_buffer + b_pos + b_count;
202
203 if (chip->empty) {
204 chip->empty = 0;
205 dac_audio_start_timer(chip);
206 }
207
208 return 0;
209}
210
211static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
212 int channel, snd_pcm_uframes_t pos,
213 snd_pcm_uframes_t count)
214{
215 /* channel is not used (interleaved data) */
216 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
217 struct snd_pcm_runtime *runtime = substream->runtime;
218 ssize_t b_count = frames_to_bytes(runtime , count);
219 ssize_t b_pos = frames_to_bytes(runtime , pos);
220
221 if (count < 0)
222 return -EINVAL;
223
224 if (!count)
225 return 0;
226
227 memset_io(chip->data_buffer + b_pos, 0, b_count);
228 chip->buffer_end = chip->data_buffer + b_pos + b_count;
229
230 if (chip->empty) {
231 chip->empty = 0;
232 dac_audio_start_timer(chip);
233 }
234
235 return 0;
236}
237
238static
239snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream)
240{
241 struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
242 int pointer = chip->buffer_begin - chip->data_buffer;
243
244 return pointer;
245}
246
247/* pcm ops */
248static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
249 .open = snd_sh_dac_pcm_open,
250 .close = snd_sh_dac_pcm_close,
251 .ioctl = snd_pcm_lib_ioctl,
252 .hw_params = snd_sh_dac_pcm_hw_params,
253 .hw_free = snd_sh_dac_pcm_hw_free,
254 .prepare = snd_sh_dac_pcm_prepare,
255 .trigger = snd_sh_dac_pcm_trigger,
256 .pointer = snd_sh_dac_pcm_pointer,
257 .copy = snd_sh_dac_pcm_copy,
258 .silence = snd_sh_dac_pcm_silence,
259 .mmap = snd_pcm_lib_mmap_iomem,
260};
261
262static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
263{
264 int err;
265 struct snd_pcm *pcm;
266
267 /* device should be always 0 for us */
268 err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm);
269 if (err < 0)
270 return err;
271
272 pcm->private_data = chip;
273 strcpy(pcm->name, "SH_DAC PCM");
274 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops);
275
276 /* buffer size=48K */
277 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
278 snd_dma_continuous_data(GFP_KERNEL),
279 48 * 1024,
280 48 * 1024);
281
282 return 0;
283}
284/* END OF PCM INTERFACE */
285
286
287/* driver .remove -- destructor */
288static int snd_sh_dac_remove(struct platform_device *devptr)
289{
290 snd_card_free(platform_get_drvdata(devptr));
291 platform_set_drvdata(devptr, NULL);
292
293 return 0;
294}
295
296/* free -- it has been defined by create */
297static int snd_sh_dac_free(struct snd_sh_dac *chip)
298{
299 /* release the data */
300 kfree(chip->data_buffer);
301 kfree(chip);
302
303 return 0;
304}
305
306static int snd_sh_dac_dev_free(struct snd_device *device)
307{
308 struct snd_sh_dac *chip = device->device_data;
309
310 return snd_sh_dac_free(chip);
311}
312
313static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
314{
315 struct snd_sh_dac *chip = container_of(handle, struct snd_sh_dac,
316 hrtimer);
317 struct snd_pcm_runtime *runtime = chip->substream->runtime;
318 ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size);
319
320 if (!chip->empty) {
321 sh_dac_output(*chip->buffer_begin, chip->pdata->channel);
322 chip->buffer_begin++;
323
324 chip->processed++;
325 if (chip->processed >= b_ps) {
326 chip->processed -= b_ps;
327 snd_pcm_period_elapsed(chip->substream);
328 }
329
330 if (chip->buffer_begin == (chip->data_buffer +
331 chip->buffer_size - 1))
332 chip->buffer_begin = chip->data_buffer;
333
334 if (chip->buffer_begin == chip->buffer_end)
335 chip->empty = 1;
336
337 }
338
339 if (!chip->empty)
340 hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
341 HRTIMER_MODE_REL);
342
343 return HRTIMER_NORESTART;
344}
345
346/* create -- chip-specific constructor for the cards components */
347static int __devinit snd_sh_dac_create(struct snd_card *card,
348 struct platform_device *devptr,
349 struct snd_sh_dac **rchip)
350{
351 struct snd_sh_dac *chip;
352 int err;
353
354 static struct snd_device_ops ops = {
355 .dev_free = snd_sh_dac_dev_free,
356 };
357
358 *rchip = NULL;
359
360 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
361 if (chip == NULL)
362 return -ENOMEM;
363
364 chip->card = card;
365
366 hrtimer_init(&chip->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
367 chip->hrtimer.function = sh_dac_audio_timer;
368
369 dac_audio_reset(chip);
370 chip->rate = 8000;
371 dac_audio_set_rate(chip);
372
373 chip->pdata = devptr->dev.platform_data;
374
375 chip->data_buffer = kmalloc(chip->pdata->buffer_size, GFP_KERNEL);
376 if (chip->data_buffer == NULL) {
377 kfree(chip);
378 return -ENOMEM;
379 }
380
381 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
382 if (err < 0) {
383 snd_sh_dac_free(chip);
384 return err;
385 }
386
387 *rchip = chip;
388
389 return 0;
390}
391
392/* driver .probe -- constructor */
393static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
394{
395 struct snd_sh_dac *chip;
396 struct snd_card *card;
397 int err;
398
399 err = snd_card_create(index, id, THIS_MODULE, 0, &card);
400 if (err < 0) {
401 snd_printk(KERN_ERR "cannot allocate the card\n");
402 return err;
403 }
404
405 err = snd_sh_dac_create(card, devptr, &chip);
406 if (err < 0)
407 goto probe_error;
408
409 err = snd_sh_dac_pcm(chip, 0);
410 if (err < 0)
411 goto probe_error;
412
413 strcpy(card->driver, "snd_sh_dac");
414 strcpy(card->shortname, "SuperH DAC audio driver");
415 printk(KERN_INFO "%s %s", card->longname, card->shortname);
416
417 err = snd_card_register(card);
418 if (err < 0)
419 goto probe_error;
420
421 snd_printk("ALSA driver for SuperH DAC audio");
422
423 platform_set_drvdata(devptr, card);
424 return 0;
425
426probe_error:
427 snd_card_free(card);
428 return err;
429}
430
431/*
432 * "driver" definition
433 */
434static struct platform_driver driver = {
435 .probe = snd_sh_dac_probe,
436 .remove = snd_sh_dac_remove,
437 .driver = {
438 .name = "dac_audio",
439 },
440};
441
442static int __init sh_dac_init(void)
443{
444 return platform_driver_register(&driver);
445}
446
447static void __exit sh_dac_exit(void)
448{
449 platform_driver_unregister(&driver);
450}
451
452module_init(sh_dac_init);
453module_exit(sh_dac_exit);
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 0c5eac01bf2e..1470141d4167 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ 4obj-$(CONFIG_SND_SOC) += codecs/
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 9eb610c2ba91..9df4c68ef000 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -268,7 +268,7 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
269 269
270 270
271 ret = snd_soc_dai_set_pll(codec_dai, 0, 271 ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
272 clk_get_rate(CODEC_CLK), pll_out); 272 clk_get_rate(CODEC_CLK), pll_out);
273 if (ret < 0) { 273 if (ret < 0) {
274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", 274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 885ba012557e..e028744c32ce 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -207,7 +207,7 @@ static int __init at91sam9g20ek_init(void)
207 struct clk *pllb; 207 struct clk *pllb;
208 int ret; 208 int ret;
209 209
210 if (!machine_is_at91sam9g20ek()) 210 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
211 return -ENODEV; 211 return -ENODEV;
212 212
213 /* 213 /*
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 594c6c5b7838..19e4d37eba1c 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -333,6 +333,30 @@ static int au1xpsc_pcm_new(struct snd_card *card,
333 333
334static int au1xpsc_pcm_probe(struct platform_device *pdev) 334static int au1xpsc_pcm_probe(struct platform_device *pdev)
335{ 335{
336 if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
337 return -ENODEV;
338
339 return 0;
340}
341
342static int au1xpsc_pcm_remove(struct platform_device *pdev)
343{
344 return 0;
345}
346
347/* au1xpsc audio platform */
348struct snd_soc_platform au1xpsc_soc_platform = {
349 .name = "au1xpsc-pcm-dbdma",
350 .probe = au1xpsc_pcm_probe,
351 .remove = au1xpsc_pcm_remove,
352 .pcm_ops = &au1xpsc_pcm_ops,
353 .pcm_new = au1xpsc_pcm_new,
354 .pcm_free = au1xpsc_pcm_free_dma_buffers,
355};
356EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
357
358static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
359{
336 struct resource *r; 360 struct resource *r;
337 int ret; 361 int ret;
338 362
@@ -365,7 +389,9 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)
365 } 389 }
366 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; 390 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
367 391
368 return 0; 392 ret = snd_soc_register_platform(&au1xpsc_soc_platform);
393 if (!ret)
394 return ret;
369 395
370out2: 396out2:
371 kfree(au1xpsc_audio_pcmdma[PCM_RX]); 397 kfree(au1xpsc_audio_pcmdma[PCM_RX]);
@@ -376,10 +402,12 @@ out1:
376 return ret; 402 return ret;
377} 403}
378 404
379static int au1xpsc_pcm_remove(struct platform_device *pdev) 405static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
380{ 406{
381 int i; 407 int i;
382 408
409 snd_soc_unregister_platform(&au1xpsc_soc_platform);
410
383 for (i = 0; i < 2; i++) { 411 for (i = 0; i < 2; i++) {
384 if (au1xpsc_audio_pcmdma[i]) { 412 if (au1xpsc_audio_pcmdma[i]) {
385 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]); 413 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
@@ -391,32 +419,81 @@ static int au1xpsc_pcm_remove(struct platform_device *pdev)
391 return 0; 419 return 0;
392} 420}
393 421
394/* au1xpsc audio platform */ 422static struct platform_driver au1xpsc_pcm_driver = {
395struct snd_soc_platform au1xpsc_soc_platform = { 423 .driver = {
396 .name = "au1xpsc-pcm-dbdma", 424 .name = "au1xpsc-pcm",
397 .probe = au1xpsc_pcm_probe, 425 .owner = THIS_MODULE,
398 .remove = au1xpsc_pcm_remove, 426 },
399 .pcm_ops = &au1xpsc_pcm_ops, 427 .probe = au1xpsc_pcm_drvprobe,
400 .pcm_new = au1xpsc_pcm_new, 428 .remove = __devexit_p(au1xpsc_pcm_drvremove),
401 .pcm_free = au1xpsc_pcm_free_dma_buffers,
402}; 429};
403EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
404 430
405static int __init au1xpsc_audio_dbdma_init(void) 431static int __init au1xpsc_audio_dbdma_load(void)
406{ 432{
407 au1xpsc_audio_pcmdma[PCM_TX] = NULL; 433 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
408 au1xpsc_audio_pcmdma[PCM_RX] = NULL; 434 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
409 return snd_soc_register_platform(&au1xpsc_soc_platform); 435 return platform_driver_register(&au1xpsc_pcm_driver);
410} 436}
411 437
412static void __exit au1xpsc_audio_dbdma_exit(void) 438static void __exit au1xpsc_audio_dbdma_unload(void)
413{ 439{
414 snd_soc_unregister_platform(&au1xpsc_soc_platform); 440 platform_driver_unregister(&au1xpsc_pcm_driver);
415} 441}
416 442
417module_init(au1xpsc_audio_dbdma_init); 443module_init(au1xpsc_audio_dbdma_load);
418module_exit(au1xpsc_audio_dbdma_exit); 444module_exit(au1xpsc_audio_dbdma_unload);
445
446
447struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
448{
449 struct resource *res, *r;
450 struct platform_device *pd;
451 int id[2];
452 int ret;
453
454 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
455 if (!r)
456 return NULL;
457 id[0] = r->start;
458
459 r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
460 if (!r)
461 return NULL;
462 id[1] = r->start;
463
464 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
465 if (!res)
466 return NULL;
467
468 res[0].start = res[0].end = id[0];
469 res[1].start = res[1].end = id[1];
470 res[0].flags = res[1].flags = IORESOURCE_DMA;
471
472 pd = platform_device_alloc("au1xpsc-pcm", -1);
473 if (!pd)
474 goto out;
475
476 pd->resource = res;
477 pd->num_resources = 2;
478
479 ret = platform_device_add(pd);
480 if (!ret)
481 return pd;
482
483 platform_device_put(pd);
484out:
485 kfree(res);
486 return NULL;
487}
488EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
489
490void au1xpsc_pcm_destroy(struct platform_device *dmapd)
491{
492 if (dmapd)
493 platform_device_unregister(dmapd);
494}
495EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
419 496
420MODULE_LICENSE("GPL"); 497MODULE_LICENSE("GPL");
421MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); 498MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
422MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 499MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index a521aa90ddee..340311d7fed5 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -61,7 +61,8 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
61{ 61{
62 /* FIXME */ 62 /* FIXME */
63 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 63 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
64 unsigned short data, retry, tmo; 64 unsigned short retry, tmo;
65 unsigned long data;
65 66
66 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 67 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
67 au_sync(); 68 au_sync();
@@ -74,20 +75,26 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
74 AC97_CDC(pscdata)); 75 AC97_CDC(pscdata));
75 au_sync(); 76 au_sync();
76 77
77 tmo = 2000; 78 tmo = 20;
78 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) 79 do {
79 && --tmo) 80 udelay(21);
80 udelay(2); 81 if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
82 break;
83 } while (--tmo);
81 84
82 data = au_readl(AC97_CDC(pscdata)) & 0xffff; 85 data = au_readl(AC97_CDC(pscdata));
83 86
84 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 87 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
85 au_sync(); 88 au_sync();
86 89
87 mutex_unlock(&pscdata->lock); 90 mutex_unlock(&pscdata->lock);
91
92 if (reg != ((data >> 16) & 0x7f))
93 tmo = 1; /* wrong register, try again */
94
88 } while (--retry && !tmo); 95 } while (--retry && !tmo);
89 96
90 return retry ? data : 0xffff; 97 return retry ? data & 0xffff : 0xffff;
91} 98}
92 99
93/* AC97 controller writes to codec register */ 100/* AC97 controller writes to codec register */
@@ -109,10 +116,12 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
109 AC97_CDC(pscdata)); 116 AC97_CDC(pscdata));
110 au_sync(); 117 au_sync();
111 118
112 tmo = 2000; 119 tmo = 20;
113 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) 120 do {
114 && --tmo) 121 udelay(21);
115 udelay(2); 122 if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
123 break;
124 } while (--tmo);
116 125
117 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 126 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
118 au_sync(); 127 au_sync();
@@ -195,7 +204,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
195 /* FIXME */ 204 /* FIXME */
196 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 205 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
197 unsigned long r, ro, stat; 206 unsigned long r, ro, stat;
198 int chans, stype = SUBSTREAM_TYPE(substream); 207 int chans, t, stype = SUBSTREAM_TYPE(substream);
199 208
200 chans = params_channels(params); 209 chans = params_channels(params);
201 210
@@ -237,8 +246,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
237 au_sync(); 246 au_sync();
238 247
239 /* ...wait for it... */ 248 /* ...wait for it... */
240 while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) 249 t = 100;
241 asm volatile ("nop"); 250 while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
251 msleep(1);
252
253 if (!t)
254 printk(KERN_ERR "PSC-AC97: can't disable!\n");
242 255
243 /* ...write config... */ 256 /* ...write config... */
244 au_writel(r, AC97_CFG(pscdata)); 257 au_writel(r, AC97_CFG(pscdata));
@@ -249,8 +262,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
249 au_sync(); 262 au_sync();
250 263
251 /* ...and wait for ready bit */ 264 /* ...and wait for ready bit */
252 while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) 265 t = 100;
253 asm volatile ("nop"); 266 while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
267 msleep(1);
268
269 if (!t)
270 printk(KERN_ERR "PSC-AC97: can't enable!\n");
254 271
255 mutex_unlock(&pscdata->lock); 272 mutex_unlock(&pscdata->lock);
256 273
@@ -300,19 +317,55 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
300static int au1xpsc_ac97_probe(struct platform_device *pdev, 317static int au1xpsc_ac97_probe(struct platform_device *pdev,
301 struct snd_soc_dai *dai) 318 struct snd_soc_dai *dai)
302{ 319{
320 return au1xpsc_ac97_workdata ? 0 : -ENODEV;
321}
322
323static void au1xpsc_ac97_remove(struct platform_device *pdev,
324 struct snd_soc_dai *dai)
325{
326}
327
328static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
329 .trigger = au1xpsc_ac97_trigger,
330 .hw_params = au1xpsc_ac97_hw_params,
331};
332
333struct snd_soc_dai au1xpsc_ac97_dai = {
334 .name = "au1xpsc_ac97",
335 .ac97_control = 1,
336 .probe = au1xpsc_ac97_probe,
337 .remove = au1xpsc_ac97_remove,
338 .playback = {
339 .rates = AC97_RATES,
340 .formats = AC97_FMTS,
341 .channels_min = 2,
342 .channels_max = 2,
343 },
344 .capture = {
345 .rates = AC97_RATES,
346 .formats = AC97_FMTS,
347 .channels_min = 2,
348 .channels_max = 2,
349 },
350 .ops = &au1xpsc_ac97_dai_ops,
351};
352EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
353
354static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
355{
303 int ret; 356 int ret;
304 struct resource *r; 357 struct resource *r;
305 unsigned long sel; 358 unsigned long sel;
359 struct au1xpsc_audio_data *wd;
306 360
307 if (au1xpsc_ac97_workdata) 361 if (au1xpsc_ac97_workdata)
308 return -EBUSY; 362 return -EBUSY;
309 363
310 au1xpsc_ac97_workdata = 364 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
311 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 365 if (!wd)
312 if (!au1xpsc_ac97_workdata)
313 return -ENOMEM; 366 return -ENOMEM;
314 367
315 mutex_init(&au1xpsc_ac97_workdata->lock); 368 mutex_init(&wd->lock);
316 369
317 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 370 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
318 if (!r) { 371 if (!r) {
@@ -321,81 +374,95 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
321 } 374 }
322 375
323 ret = -EBUSY; 376 ret = -EBUSY;
324 au1xpsc_ac97_workdata->ioarea = 377 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
325 request_mem_region(r->start, r->end - r->start + 1,
326 "au1xpsc_ac97"); 378 "au1xpsc_ac97");
327 if (!au1xpsc_ac97_workdata->ioarea) 379 if (!wd->ioarea)
328 goto out0; 380 goto out0;
329 381
330 au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff); 382 wd->mmio = ioremap(r->start, 0xffff);
331 if (!au1xpsc_ac97_workdata->mmio) 383 if (!wd->mmio)
332 goto out1; 384 goto out1;
333 385
334 /* configuration: max dma trigger threshold, enable ac97 */ 386 /* configuration: max dma trigger threshold, enable ac97 */
335 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | 387 wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
336 PSC_AC97CFG_TT_FIFO8 | 388 PSC_AC97CFG_DE_ENABLE;
337 PSC_AC97CFG_DE_ENABLE;
338 389
339 /* preserve PSC clock source set up by platform (dev.platform_data 390 /* preserve PSC clock source set up by platform */
340 * is already occupied by soc layer) 391 sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
341 */ 392 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
342 sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
343 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
344 au_sync(); 393 au_sync();
345 au_writel(0, PSC_SEL(au1xpsc_ac97_workdata)); 394 au_writel(0, PSC_SEL(wd));
346 au_sync(); 395 au_sync();
347 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata)); 396 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
348 au_sync(); 397 au_sync();
349 /* next up: cold reset. Dont check for PSC-ready now since
350 * there may not be any codec clock yet.
351 */
352 398
353 return 0; 399 ret = snd_soc_register_dai(&au1xpsc_ac97_dai);
400 if (ret)
401 goto out1;
354 402
403 wd->dmapd = au1xpsc_pcm_add(pdev);
404 if (wd->dmapd) {
405 platform_set_drvdata(pdev, wd);
406 au1xpsc_ac97_workdata = wd; /* MDEV */
407 return 0;
408 }
409
410 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
355out1: 411out1:
356 release_resource(au1xpsc_ac97_workdata->ioarea); 412 release_resource(wd->ioarea);
357 kfree(au1xpsc_ac97_workdata->ioarea); 413 kfree(wd->ioarea);
358out0: 414out0:
359 kfree(au1xpsc_ac97_workdata); 415 kfree(wd);
360 au1xpsc_ac97_workdata = NULL;
361 return ret; 416 return ret;
362} 417}
363 418
364static void au1xpsc_ac97_remove(struct platform_device *pdev, 419static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
365 struct snd_soc_dai *dai)
366{ 420{
421 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
422
423 if (wd->dmapd)
424 au1xpsc_pcm_destroy(wd->dmapd);
425
426 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
427
367 /* disable PSC completely */ 428 /* disable PSC completely */
368 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 429 au_writel(0, AC97_CFG(wd));
369 au_sync(); 430 au_sync();
370 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 431 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
371 au_sync(); 432 au_sync();
372 433
373 iounmap(au1xpsc_ac97_workdata->mmio); 434 iounmap(wd->mmio);
374 release_resource(au1xpsc_ac97_workdata->ioarea); 435 release_resource(wd->ioarea);
375 kfree(au1xpsc_ac97_workdata->ioarea); 436 kfree(wd->ioarea);
376 kfree(au1xpsc_ac97_workdata); 437 kfree(wd);
377 au1xpsc_ac97_workdata = NULL; 438
439 au1xpsc_ac97_workdata = NULL; /* MDEV */
440
441 return 0;
378} 442}
379 443
380static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai) 444#ifdef CONFIG_PM
445static int au1xpsc_ac97_drvsuspend(struct device *dev)
381{ 446{
447 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
448
382 /* save interesting registers and disable PSC */ 449 /* save interesting registers and disable PSC */
383 au1xpsc_ac97_workdata->pm[0] = 450 wd->pm[0] = au_readl(PSC_SEL(wd));
384 au_readl(PSC_SEL(au1xpsc_ac97_workdata));
385 451
386 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 452 au_writel(0, AC97_CFG(wd));
387 au_sync(); 453 au_sync();
388 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 454 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
389 au_sync(); 455 au_sync();
390 456
391 return 0; 457 return 0;
392} 458}
393 459
394static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) 460static int au1xpsc_ac97_drvresume(struct device *dev)
395{ 461{
462 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
463
396 /* restore PSC clock config */ 464 /* restore PSC clock config */
397 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, 465 au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
398 PSC_SEL(au1xpsc_ac97_workdata));
399 au_sync(); 466 au_sync();
400 467
401 /* after this point the ac97 core will cold-reset the codec. 468 /* after this point the ac97 core will cold-reset the codec.
@@ -405,48 +472,44 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
405 return 0; 472 return 0;
406} 473}
407 474
408static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { 475static struct dev_pm_ops au1xpscac97_pmops = {
409 .trigger = au1xpsc_ac97_trigger, 476 .suspend = au1xpsc_ac97_drvsuspend,
410 .hw_params = au1xpsc_ac97_hw_params, 477 .resume = au1xpsc_ac97_drvresume,
411}; 478};
412 479
413struct snd_soc_dai au1xpsc_ac97_dai = { 480#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops
414 .name = "au1xpsc_ac97", 481
415 .ac97_control = 1, 482#else
416 .probe = au1xpsc_ac97_probe, 483
417 .remove = au1xpsc_ac97_remove, 484#define AU1XPSCAC97_PMOPS NULL
418 .suspend = au1xpsc_ac97_suspend, 485
419 .resume = au1xpsc_ac97_resume, 486#endif
420 .playback = { 487
421 .rates = AC97_RATES, 488static struct platform_driver au1xpsc_ac97_driver = {
422 .formats = AC97_FMTS, 489 .driver = {
423 .channels_min = 2, 490 .name = "au1xpsc_ac97",
424 .channels_max = 2, 491 .owner = THIS_MODULE,
425 }, 492 .pm = AU1XPSCAC97_PMOPS,
426 .capture = {
427 .rates = AC97_RATES,
428 .formats = AC97_FMTS,
429 .channels_min = 2,
430 .channels_max = 2,
431 }, 493 },
432 .ops = &au1xpsc_ac97_dai_ops, 494 .probe = au1xpsc_ac97_drvprobe,
495 .remove = __devexit_p(au1xpsc_ac97_drvremove),
433}; 496};
434EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
435 497
436static int __init au1xpsc_ac97_init(void) 498static int __init au1xpsc_ac97_load(void)
437{ 499{
438 au1xpsc_ac97_workdata = NULL; 500 au1xpsc_ac97_workdata = NULL;
439 return snd_soc_register_dai(&au1xpsc_ac97_dai); 501 return platform_driver_register(&au1xpsc_ac97_driver);
440} 502}
441 503
442static void __exit au1xpsc_ac97_exit(void) 504static void __exit au1xpsc_ac97_unload(void)
443{ 505{
444 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 506 platform_driver_unregister(&au1xpsc_ac97_driver);
445} 507}
446 508
447module_init(au1xpsc_ac97_init); 509module_init(au1xpsc_ac97_load);
448module_exit(au1xpsc_ac97_exit); 510module_exit(au1xpsc_ac97_unload);
449 511
450MODULE_LICENSE("GPL"); 512MODULE_LICENSE("GPL");
451MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); 513MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
452MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>"); 514MODULE_AUTHOR("Manuel Lauss");
515
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index bb589327ee32..0cf2ca61c776 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -265,16 +265,52 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
265static int au1xpsc_i2s_probe(struct platform_device *pdev, 265static int au1xpsc_i2s_probe(struct platform_device *pdev,
266 struct snd_soc_dai *dai) 266 struct snd_soc_dai *dai)
267{ 267{
268 return au1xpsc_i2s_workdata ? 0 : -ENODEV;
269}
270
271static void au1xpsc_i2s_remove(struct platform_device *pdev,
272 struct snd_soc_dai *dai)
273{
274}
275
276static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
277 .trigger = au1xpsc_i2s_trigger,
278 .hw_params = au1xpsc_i2s_hw_params,
279 .set_fmt = au1xpsc_i2s_set_fmt,
280};
281
282struct snd_soc_dai au1xpsc_i2s_dai = {
283 .name = "au1xpsc_i2s",
284 .probe = au1xpsc_i2s_probe,
285 .remove = au1xpsc_i2s_remove,
286 .playback = {
287 .rates = AU1XPSC_I2S_RATES,
288 .formats = AU1XPSC_I2S_FMTS,
289 .channels_min = 2,
290 .channels_max = 8, /* 2 without external help */
291 },
292 .capture = {
293 .rates = AU1XPSC_I2S_RATES,
294 .formats = AU1XPSC_I2S_FMTS,
295 .channels_min = 2,
296 .channels_max = 8, /* 2 without external help */
297 },
298 .ops = &au1xpsc_i2s_dai_ops,
299};
300EXPORT_SYMBOL(au1xpsc_i2s_dai);
301
302static int __init au1xpsc_i2s_drvprobe(struct platform_device *pdev)
303{
268 struct resource *r; 304 struct resource *r;
269 unsigned long sel; 305 unsigned long sel;
270 int ret; 306 int ret;
307 struct au1xpsc_audio_data *wd;
271 308
272 if (au1xpsc_i2s_workdata) 309 if (au1xpsc_i2s_workdata)
273 return -EBUSY; 310 return -EBUSY;
274 311
275 au1xpsc_i2s_workdata = 312 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
276 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 313 if (!wd)
277 if (!au1xpsc_i2s_workdata)
278 return -ENOMEM; 314 return -ENOMEM;
279 315
280 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 316 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -284,131 +320,146 @@ static int au1xpsc_i2s_probe(struct platform_device *pdev,
284 } 320 }
285 321
286 ret = -EBUSY; 322 ret = -EBUSY;
287 au1xpsc_i2s_workdata->ioarea = 323 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
288 request_mem_region(r->start, r->end - r->start + 1,
289 "au1xpsc_i2s"); 324 "au1xpsc_i2s");
290 if (!au1xpsc_i2s_workdata->ioarea) 325 if (!wd->ioarea)
291 goto out0; 326 goto out0;
292 327
293 au1xpsc_i2s_workdata->mmio = ioremap(r->start, 0xffff); 328 wd->mmio = ioremap(r->start, 0xffff);
294 if (!au1xpsc_i2s_workdata->mmio) 329 if (!wd->mmio)
295 goto out1; 330 goto out1;
296 331
297 /* preserve PSC clock source set up by platform (dev.platform_data 332 /* preserve PSC clock source set up by platform (dev.platform_data
298 * is already occupied by soc layer) 333 * is already occupied by soc layer)
299 */ 334 */
300 sel = au_readl(PSC_SEL(au1xpsc_i2s_workdata)) & PSC_SEL_CLK_MASK; 335 sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
301 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 336 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
302 au_sync(); 337 au_sync();
303 au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(au1xpsc_i2s_workdata)); 338 au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
304 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 339 au_writel(0, I2S_CFG(wd));
305 au_sync(); 340 au_sync();
306 341
307 /* preconfigure: set max rx/tx fifo depths */ 342 /* preconfigure: set max rx/tx fifo depths */
308 au1xpsc_i2s_workdata->cfg |= 343 wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
309 PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
310 344
311 /* don't wait for I2S core to become ready now; clocks may not 345 /* don't wait for I2S core to become ready now; clocks may not
312 * be running yet; depending on clock input for PSC a wait might 346 * be running yet; depending on clock input for PSC a wait might
313 * time out. 347 * time out.
314 */ 348 */
315 349
316 return 0; 350 ret = snd_soc_register_dai(&au1xpsc_i2s_dai);
351 if (ret)
352 goto out1;
317 353
354 /* finally add the DMA device for this PSC */
355 wd->dmapd = au1xpsc_pcm_add(pdev);
356 if (wd->dmapd) {
357 platform_set_drvdata(pdev, wd);
358 au1xpsc_i2s_workdata = wd;
359 return 0;
360 }
361
362 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
318out1: 363out1:
319 release_resource(au1xpsc_i2s_workdata->ioarea); 364 release_resource(wd->ioarea);
320 kfree(au1xpsc_i2s_workdata->ioarea); 365 kfree(wd->ioarea);
321out0: 366out0:
322 kfree(au1xpsc_i2s_workdata); 367 kfree(wd);
323 au1xpsc_i2s_workdata = NULL;
324 return ret; 368 return ret;
325} 369}
326 370
327static void au1xpsc_i2s_remove(struct platform_device *pdev, 371static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
328 struct snd_soc_dai *dai)
329{ 372{
330 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 373 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
374
375 if (wd->dmapd)
376 au1xpsc_pcm_destroy(wd->dmapd);
377
378 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
379
380 au_writel(0, I2S_CFG(wd));
331 au_sync(); 381 au_sync();
332 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 382 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
333 au_sync(); 383 au_sync();
334 384
335 iounmap(au1xpsc_i2s_workdata->mmio); 385 iounmap(wd->mmio);
336 release_resource(au1xpsc_i2s_workdata->ioarea); 386 release_resource(wd->ioarea);
337 kfree(au1xpsc_i2s_workdata->ioarea); 387 kfree(wd->ioarea);
338 kfree(au1xpsc_i2s_workdata); 388 kfree(wd);
339 au1xpsc_i2s_workdata = NULL; 389
390 au1xpsc_i2s_workdata = NULL; /* MDEV */
391
392 return 0;
340} 393}
341 394
342static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai) 395#ifdef CONFIG_PM
396static int au1xpsc_i2s_drvsuspend(struct device *dev)
343{ 397{
398 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
399
344 /* save interesting register and disable PSC */ 400 /* save interesting register and disable PSC */
345 au1xpsc_i2s_workdata->pm[0] = 401 wd->pm[0] = au_readl(PSC_SEL(wd));
346 au_readl(PSC_SEL(au1xpsc_i2s_workdata));
347 402
348 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 403 au_writel(0, I2S_CFG(wd));
349 au_sync(); 404 au_sync();
350 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 405 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
351 au_sync(); 406 au_sync();
352 407
353 return 0; 408 return 0;
354} 409}
355 410
356static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai) 411static int au1xpsc_i2s_drvresume(struct device *dev)
357{ 412{
413 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
414
358 /* select I2S mode and PSC clock */ 415 /* select I2S mode and PSC clock */
359 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 416 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
360 au_sync(); 417 au_sync();
361 au_writel(0, PSC_SEL(au1xpsc_i2s_workdata)); 418 au_writel(0, PSC_SEL(wd));
362 au_sync(); 419 au_sync();
363 au_writel(au1xpsc_i2s_workdata->pm[0], 420 au_writel(wd->pm[0], PSC_SEL(wd));
364 PSC_SEL(au1xpsc_i2s_workdata));
365 au_sync(); 421 au_sync();
366 422
367 return 0; 423 return 0;
368} 424}
369 425
370static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { 426static struct dev_pm_ops au1xpsci2s_pmops = {
371 .trigger = au1xpsc_i2s_trigger, 427 .suspend = au1xpsc_i2s_drvsuspend,
372 .hw_params = au1xpsc_i2s_hw_params, 428 .resume = au1xpsc_i2s_drvresume,
373 .set_fmt = au1xpsc_i2s_set_fmt,
374}; 429};
375 430
376struct snd_soc_dai au1xpsc_i2s_dai = { 431#define AU1XPSCI2S_PMOPS &au1xpsci2s_pmops
377 .name = "au1xpsc_i2s", 432
378 .probe = au1xpsc_i2s_probe, 433#else
379 .remove = au1xpsc_i2s_remove, 434
380 .suspend = au1xpsc_i2s_suspend, 435#define AU1XPSCI2S_PMOPS NULL
381 .resume = au1xpsc_i2s_resume, 436
382 .playback = { 437#endif
383 .rates = AU1XPSC_I2S_RATES, 438
384 .formats = AU1XPSC_I2S_FMTS, 439static struct platform_driver au1xpsc_i2s_driver = {
385 .channels_min = 2, 440 .driver = {
386 .channels_max = 8, /* 2 without external help */ 441 .name = "au1xpsc_i2s",
387 }, 442 .owner = THIS_MODULE,
388 .capture = { 443 .pm = AU1XPSCI2S_PMOPS,
389 .rates = AU1XPSC_I2S_RATES,
390 .formats = AU1XPSC_I2S_FMTS,
391 .channels_min = 2,
392 .channels_max = 8, /* 2 without external help */
393 }, 444 },
394 .ops = &au1xpsc_i2s_dai_ops, 445 .probe = au1xpsc_i2s_drvprobe,
446 .remove = __devexit_p(au1xpsc_i2s_drvremove),
395}; 447};
396EXPORT_SYMBOL(au1xpsc_i2s_dai);
397 448
398static int __init au1xpsc_i2s_init(void) 449static int __init au1xpsc_i2s_load(void)
399{ 450{
400 au1xpsc_i2s_workdata = NULL; 451 au1xpsc_i2s_workdata = NULL;
401 return snd_soc_register_dai(&au1xpsc_i2s_dai); 452 return platform_driver_register(&au1xpsc_i2s_driver);
402} 453}
403 454
404static void __exit au1xpsc_i2s_exit(void) 455static void __exit au1xpsc_i2s_unload(void)
405{ 456{
406 snd_soc_unregister_dai(&au1xpsc_i2s_dai); 457 platform_driver_unregister(&au1xpsc_i2s_driver);
407} 458}
408 459
409module_init(au1xpsc_i2s_init); 460module_init(au1xpsc_i2s_load);
410module_exit(au1xpsc_i2s_exit); 461module_exit(au1xpsc_i2s_unload);
411 462
412MODULE_LICENSE("GPL"); 463MODULE_LICENSE("GPL");
413MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver"); 464MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
414MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 465MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index 3f474e8ed4f6..32d3807d3f5a 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,10 @@ extern struct snd_soc_dai au1xpsc_i2s_dai;
21extern struct snd_soc_platform au1xpsc_soc_platform; 21extern struct snd_soc_platform au1xpsc_soc_platform;
22extern struct snd_ac97_bus_ops soc_ac97_ops; 22extern struct snd_ac97_bus_ops soc_ac97_ops;
23 23
24/* DBDMA helpers */
25extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
26extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
27
24struct au1xpsc_audio_data { 28struct au1xpsc_audio_data {
25 void __iomem *mmio; 29 void __iomem *mmio;
26 30
@@ -30,6 +34,7 @@ struct au1xpsc_audio_data {
30 unsigned long pm[2]; 34 unsigned long pm[2];
31 struct resource *ioarea; 35 struct resource *ioarea;
32 struct mutex lock; 36 struct mutex lock;
37 struct platform_device *dmapd;
33}; 38};
34 39
35#define PCM_TX 0 40#define PCM_TX 0
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index cd361e304b0f..0f45a3f56be8 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -52,6 +52,7 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
52 struct snd_soc_pcm_runtime *rtd = substream->private_data; 52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
55 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
55 int ret = 0; 56 int ret = 0;
56 /* set cpu DAI configuration */ 57 /* set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 58 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
@@ -65,6 +66,12 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
65 if (ret < 0) 66 if (ret < 0)
66 return ret; 67 return ret;
67 68
69 /* set cpu DAI channel mapping */
70 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
71 channel_map, ARRAY_SIZE(channel_map), channel_map);
72 if (ret < 0)
73 return ret;
74
68 return 0; 75 return 0;
69} 76}
70 77
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
index 08269e91810c..2ef1e5013b8c 100644
--- a/sound/soc/blackfin/bf5xx-ad1938.c
+++ b/sound/soc/blackfin/bf5xx-ad1938.c
@@ -61,6 +61,7 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
64 int ret = 0; 65 int ret = 0;
65 /* set cpu DAI configuration */ 66 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 67 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
@@ -75,7 +76,13 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
75 return ret; 76 return ret;
76 77
77 /* set codec DAI slots, 8 channels, all channels are enabled */ 78 /* set codec DAI slots, 8 channels, all channels are enabled */
78 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); 79 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32);
80 if (ret < 0)
81 return ret;
82
83 /* set cpu DAI channel mapping */
84 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
85 channel_map, ARRAY_SIZE(channel_map), channel_map);
79 if (ret < 0) 86 if (ret < 0)
80 return ret; 87 return ret;
81 88
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 084b68884ada..3e6ada0dd1c4 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -49,7 +49,6 @@ struct bf5xx_i2s_port {
49 u16 rcr1; 49 u16 rcr1;
50 u16 tcr2; 50 u16 tcr2;
51 u16 rcr2; 51 u16 rcr2;
52 int counter;
53 int configured; 52 int configured;
54}; 53};
55 54
@@ -133,16 +132,6 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
133 return ret; 132 return ret;
134} 133}
135 134
136static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
137 struct snd_soc_dai *dai)
138{
139 pr_debug("%s enter\n", __func__);
140
141 /*this counter is used for counting how many pcm streams are opened*/
142 bf5xx_i2s.counter++;
143 return 0;
144}
145
146static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, 135static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
147 struct snd_pcm_hw_params *params, 136 struct snd_pcm_hw_params *params,
148 struct snd_soc_dai *dai) 137 struct snd_soc_dai *dai)
@@ -201,9 +190,8 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
201 struct snd_soc_dai *dai) 190 struct snd_soc_dai *dai)
202{ 191{
203 pr_debug("%s enter\n", __func__); 192 pr_debug("%s enter\n", __func__);
204 bf5xx_i2s.counter--;
205 /* No active stream, SPORT is allowed to be configured again. */ 193 /* No active stream, SPORT is allowed to be configured again. */
206 if (!bf5xx_i2s.counter) 194 if (!dai->active)
207 bf5xx_i2s.configured = 0; 195 bf5xx_i2s.configured = 0;
208} 196}
209 197
@@ -284,7 +272,6 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
284 SNDRV_PCM_FMTBIT_S32_LE) 272 SNDRV_PCM_FMTBIT_S32_LE)
285 273
286static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { 274static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
287 .startup = bf5xx_i2s_startup,
288 .shutdown = bf5xx_i2s_shutdown, 275 .shutdown = bf5xx_i2s_shutdown,
289 .hw_params = bf5xx_i2s_hw_params, 276 .hw_params = bf5xx_i2s_hw_params,
290 .set_fmt = bf5xx_i2s_set_dai_fmt, 277 .set_fmt = bf5xx_i2s_set_dai_fmt,
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index ccb5e823bd18..a8c73cbbd685 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -43,7 +43,7 @@
43#include "bf5xx-tdm.h" 43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45 45
46#define PCM_BUFFER_MAX 0x10000 46#define PCM_BUFFER_MAX 0x8000
47#define FRAGMENT_SIZE_MIN (4*1024) 47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2 48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32 49#define FRAGMENTS_MAX 32
@@ -177,6 +177,9 @@ out:
177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, 177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) 178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
179{ 179{
180 struct snd_pcm_runtime *runtime = substream->runtime;
181 struct sport_device *sport = runtime->private_data;
182 struct bf5xx_tdm_port *tdm_port = sport->private_data;
180 unsigned int *src; 183 unsigned int *src;
181 unsigned int *dst; 184 unsigned int *dst;
182 int i; 185 int i;
@@ -188,7 +191,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
188 dst += pos * 8; 191 dst += pos * 8;
189 while (count--) { 192 while (count--) {
190 for (i = 0; i < substream->runtime->channels; i++) 193 for (i = 0; i < substream->runtime->channels; i++)
191 *(dst + i) = *src++; 194 *(dst + tdm_port->tx_map[i]) = *src++;
192 dst += 8; 195 dst += 8;
193 } 196 }
194 } else { 197 } else {
@@ -198,7 +201,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
198 src += pos * 8; 201 src += pos * 8;
199 while (count--) { 202 while (count--) {
200 for (i = 0; i < substream->runtime->channels; i++) 203 for (i = 0; i < substream->runtime->channels; i++)
201 *dst++ = *(src+i); 204 *dst++ = *(src + tdm_port->rx_map[i]);
202 src += 8; 205 src += 8;
203 } 206 }
204 } 207 }
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index ff546e91a22e..4b360124083e 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -46,14 +46,6 @@
46#include "bf5xx-sport.h" 46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h" 47#include "bf5xx-tdm.h"
48 48
49struct bf5xx_tdm_port {
50 u16 tcr1;
51 u16 rcr1;
52 u16 tcr2;
53 u16 rcr2;
54 int configured;
55};
56
57static struct bf5xx_tdm_port bf5xx_tdm; 49static struct bf5xx_tdm_port bf5xx_tdm;
58static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; 50static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
59 51
@@ -181,6 +173,40 @@ static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
181 bf5xx_tdm.configured = 0; 173 bf5xx_tdm.configured = 0;
182} 174}
183 175
176static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
177 unsigned int tx_num, unsigned int *tx_slot,
178 unsigned int rx_num, unsigned int *rx_slot)
179{
180 int i;
181 unsigned int slot;
182 unsigned int tx_mapped = 0, rx_mapped = 0;
183
184 if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
185 (rx_num > BFIN_TDM_DAI_MAX_SLOTS))
186 return -EINVAL;
187
188 for (i = 0; i < tx_num; i++) {
189 slot = tx_slot[i];
190 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
191 (!(tx_mapped & (1 << slot)))) {
192 bf5xx_tdm.tx_map[i] = slot;
193 tx_mapped |= 1 << slot;
194 } else
195 return -EINVAL;
196 }
197 for (i = 0; i < rx_num; i++) {
198 slot = rx_slot[i];
199 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
200 (!(rx_mapped & (1 << slot)))) {
201 bf5xx_tdm.rx_map[i] = slot;
202 rx_mapped |= 1 << slot;
203 } else
204 return -EINVAL;
205 }
206
207 return 0;
208}
209
184#ifdef CONFIG_PM 210#ifdef CONFIG_PM
185static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) 211static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
186{ 212{
@@ -235,6 +261,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
235 .hw_params = bf5xx_tdm_hw_params, 261 .hw_params = bf5xx_tdm_hw_params,
236 .set_fmt = bf5xx_tdm_set_dai_fmt, 262 .set_fmt = bf5xx_tdm_set_dai_fmt,
237 .shutdown = bf5xx_tdm_shutdown, 263 .shutdown = bf5xx_tdm_shutdown,
264 .set_channel_map = bf5xx_tdm_set_channel_map,
238}; 265};
239 266
240struct snd_soc_dai bf5xx_tdm_dai = { 267struct snd_soc_dai bf5xx_tdm_dai = {
@@ -300,6 +327,8 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
300 pr_err("Failed to register DAI: %d\n", ret); 327 pr_err("Failed to register DAI: %d\n", ret);
301 goto sport_config_err; 328 goto sport_config_err;
302 } 329 }
330
331 sport_handle->private_data = &bf5xx_tdm;
303 return 0; 332 return 0;
304 333
305sport_config_err: 334sport_config_err:
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
index 618ec3d90cd4..04189a18c1ba 100644
--- a/sound/soc/blackfin/bf5xx-tdm.h
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -9,6 +9,17 @@
9#ifndef _BF5XX_TDM_H 9#ifndef _BF5XX_TDM_H
10#define _BF5XX_TDM_H 10#define _BF5XX_TDM_H
11 11
12#define BFIN_TDM_DAI_MAX_SLOTS 8
13struct bf5xx_tdm_port {
14 u16 tcr1;
15 u16 rcr1;
16 u16 tcr2;
17 u16 rcr2;
18 unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS];
19 unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS];
20 int configured;
21};
22
12extern struct snd_soc_dai bf5xx_tdm_dai; 23extern struct snd_soc_dai bf5xx_tdm_dai;
13 24
14#endif 25#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0edca93af3b0..52b005f8fed4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -15,10 +15,12 @@ config SND_SOC_ALL_CODECS
15 select SND_SOC_AD1836 if SPI_MASTER 15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER 16 select SND_SOC_AD1938 if SPI_MASTER
17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
18 select SND_SOC_ADS117X
18 select SND_SOC_AD73311 if I2C 19 select SND_SOC_AD73311 if I2C
19 select SND_SOC_AK4104 if SPI_MASTER 20 select SND_SOC_AK4104 if SPI_MASTER
20 select SND_SOC_AK4535 if I2C 21 select SND_SOC_AK4535 if I2C
21 select SND_SOC_AK4642 if I2C 22 select SND_SOC_AK4642 if I2C
23 select SND_SOC_AK4671 if I2C
22 select SND_SOC_CS4270 if I2C 24 select SND_SOC_CS4270 if I2C
23 select SND_SOC_MAX9877 if I2C 25 select SND_SOC_MAX9877 if I2C
24 select SND_SOC_PCM3008 26 select SND_SOC_PCM3008
@@ -28,6 +30,8 @@ config SND_SOC_ALL_CODECS
28 select SND_SOC_TLV320AIC23 if I2C 30 select SND_SOC_TLV320AIC23 if I2C
29 select SND_SOC_TLV320AIC26 if SPI_MASTER 31 select SND_SOC_TLV320AIC26 if SPI_MASTER
30 select SND_SOC_TLV320AIC3X if I2C 32 select SND_SOC_TLV320AIC3X if I2C
33 select SND_SOC_TPA6130A2 if I2C
34 select SND_SOC_TLV320DAC33 if I2C
31 select SND_SOC_TWL4030 if TWL4030_CORE 35 select SND_SOC_TWL4030 if TWL4030_CORE
32 select SND_SOC_UDA134X 36 select SND_SOC_UDA134X
33 select SND_SOC_UDA1380 if I2C 37 select SND_SOC_UDA1380 if I2C
@@ -36,6 +40,8 @@ config SND_SOC_ALL_CODECS
36 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 40 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
37 select SND_SOC_WM8523 if I2C 41 select SND_SOC_WM8523 if I2C
38 select SND_SOC_WM8580 if I2C 42 select SND_SOC_WM8580 if I2C
43 select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI
44 select SND_SOC_WM8727
39 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 45 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
40 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 46 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
41 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 47 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
@@ -86,6 +92,9 @@ config SND_SOC_AD1980
86 92
87config SND_SOC_AD73311 93config SND_SOC_AD73311
88 tristate 94 tristate
95
96config SND_SOC_ADS117X
97 tristate
89 98
90config SND_SOC_AK4104 99config SND_SOC_AK4104
91 tristate 100 tristate
@@ -96,6 +105,9 @@ config SND_SOC_AK4535
96config SND_SOC_AK4642 105config SND_SOC_AK4642
97 tristate 106 tristate
98 107
108config SND_SOC_AK4671
109 tristate
110
99# Cirrus Logic CS4270 Codec 111# Cirrus Logic CS4270 Codec
100config SND_SOC_CS4270 112config SND_SOC_CS4270
101 tristate 113 tristate
@@ -136,7 +148,11 @@ config SND_SOC_TLV320AIC26
136config SND_SOC_TLV320AIC3X 148config SND_SOC_TLV320AIC3X
137 tristate 149 tristate
138 150
151config SND_SOC_TLV320DAC33
152 tristate
153
139config SND_SOC_TWL4030 154config SND_SOC_TWL4030
155 select TWL4030_CODEC
140 tristate 156 tristate
141 157
142config SND_SOC_UDA134X 158config SND_SOC_UDA134X
@@ -160,6 +176,12 @@ config SND_SOC_WM8523
160config SND_SOC_WM8580 176config SND_SOC_WM8580
161 tristate 177 tristate
162 178
179config SND_SOC_WM8711
180 tristate
181
182config SND_SOC_WM8727
183 tristate
184
163config SND_SOC_WM8728 185config SND_SOC_WM8728
164 tristate 186 tristate
165 187
@@ -220,3 +242,6 @@ config SND_SOC_WM9713
220# Amp 242# Amp
221config SND_SOC_MAX9877 243config SND_SOC_MAX9877
222 tristate 244 tristate
245
246config SND_SOC_TPA6130A2
247 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fb4af28486ba..dbaecb133ac7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,9 +3,11 @@ snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o 3snd-soc-ad1938-objs := ad1938.o
4snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
5snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
6snd-soc-ads117x-objs := ads117x.o
6snd-soc-ak4104-objs := ak4104.o 7snd-soc-ak4104-objs := ak4104.o
7snd-soc-ak4535-objs := ak4535.o 8snd-soc-ak4535-objs := ak4535.o
8snd-soc-ak4642-objs := ak4642.o 9snd-soc-ak4642-objs := ak4642.o
10snd-soc-ak4671-objs := ak4671.o
9snd-soc-cs4270-objs := cs4270.o 11snd-soc-cs4270-objs := cs4270.o
10snd-soc-cx20442-objs := cx20442.o 12snd-soc-cx20442-objs := cx20442.o
11snd-soc-l3-objs := l3.o 13snd-soc-l3-objs := l3.o
@@ -16,6 +18,7 @@ snd-soc-stac9766-objs := stac9766.o
16snd-soc-tlv320aic23-objs := tlv320aic23.o 18snd-soc-tlv320aic23-objs := tlv320aic23.o
17snd-soc-tlv320aic26-objs := tlv320aic26.o 19snd-soc-tlv320aic26-objs := tlv320aic26.o
18snd-soc-tlv320aic3x-objs := tlv320aic3x.o 20snd-soc-tlv320aic3x-objs := tlv320aic3x.o
21snd-soc-tlv320dac33-objs := tlv320dac33.o
19snd-soc-twl4030-objs := twl4030.o 22snd-soc-twl4030-objs := twl4030.o
20snd-soc-uda134x-objs := uda134x.o 23snd-soc-uda134x-objs := uda134x.o
21snd-soc-uda1380-objs := uda1380.o 24snd-soc-uda1380-objs := uda1380.o
@@ -24,6 +27,8 @@ snd-soc-wm8400-objs := wm8400.o
24snd-soc-wm8510-objs := wm8510.o 27snd-soc-wm8510-objs := wm8510.o
25snd-soc-wm8523-objs := wm8523.o 28snd-soc-wm8523-objs := wm8523.o
26snd-soc-wm8580-objs := wm8580.o 29snd-soc-wm8580-objs := wm8580.o
30snd-soc-wm8711-objs := wm8711.o
31snd-soc-wm8727-objs := wm8727.o
27snd-soc-wm8728-objs := wm8728.o 32snd-soc-wm8728-objs := wm8728.o
28snd-soc-wm8731-objs := wm8731.o 33snd-soc-wm8731-objs := wm8731.o
29snd-soc-wm8750-objs := wm8750.o 34snd-soc-wm8750-objs := wm8750.o
@@ -47,15 +52,18 @@ snd-soc-wm-hubs-objs := wm_hubs.o
47 52
48# Amp 53# Amp
49snd-soc-max9877-objs := max9877.o 54snd-soc-max9877-objs := max9877.o
55snd-soc-tpa6130a2-objs := tpa6130a2.o
50 56
51obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 57obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
52obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 58obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
53obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o 59obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o
54obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 60obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
55obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 61obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
62obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
56obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 63obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
57obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 64obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
58obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 65obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
66obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
59obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 67obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
60obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 68obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
61obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 69obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
@@ -66,6 +74,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
66obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 74obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
67obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 75obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
68obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 76obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
77obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
69obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o 78obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
70obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 79obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
71obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 80obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
@@ -74,6 +83,8 @@ obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
74obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 83obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
75obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o 84obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
76obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 85obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
86obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
87obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
77obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 88obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
78obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 89obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
79obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 90obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
@@ -97,3 +108,4 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
97 108
98# Amp 109# Amp
99obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o 110obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
111obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 932299bb5d1e..69bd0acc81c8 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -117,9 +117,6 @@ static int ac97_soc_probe(struct platform_device *pdev)
117 if (ret < 0) 117 if (ret < 0)
118 goto bus_err; 118 goto bus_err;
119 119
120 ret = snd_soc_init_card(socdev);
121 if (ret < 0)
122 goto bus_err;
123 return 0; 120 return 0;
124 121
125bus_err: 122bus_err:
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index c48485f2c55d..2c18e3d1b71e 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -385,19 +385,7 @@ static int ad1836_probe(struct platform_device *pdev)
385 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, 385 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
386 ARRAY_SIZE(ad1836_dapm_widgets)); 386 ARRAY_SIZE(ad1836_dapm_widgets));
387 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 387 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
388 snd_soc_dapm_new_widgets(codec);
389 388
390 ret = snd_soc_init_card(socdev);
391 if (ret < 0) {
392 dev_err(codec->dev, "failed to register card: %d\n", ret);
393 goto card_err;
394 }
395
396 return ret;
397
398card_err:
399 snd_soc_free_pcms(socdev);
400 snd_soc_dapm_free(socdev);
401pcm_err: 389pcm_err:
402 return ret; 390 return ret;
403} 391}
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index 34b30efc3cb0..5d489186c05b 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -592,21 +592,9 @@ static int ad1938_probe(struct platform_device *pdev)
592 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, 592 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
593 ARRAY_SIZE(ad1938_dapm_widgets)); 593 ARRAY_SIZE(ad1938_dapm_widgets));
594 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 594 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
595 snd_soc_dapm_new_widgets(codec);
596 595
597 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 596 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
598 597
599 ret = snd_soc_init_card(socdev);
600 if (ret < 0) {
601 dev_err(codec->dev, "failed to register card: %d\n", ret);
602 goto card_err;
603 }
604
605 return ret;
606
607card_err:
608 snd_soc_free_pcms(socdev);
609 snd_soc_dapm_free(socdev);
610pcm_err: 598pcm_err:
611 return ret; 599 return ret;
612} 600}
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index d7440a982d22..39c0f7584e65 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -257,11 +257,6 @@ static int ad1980_soc_probe(struct platform_device *pdev)
257 257
258 snd_soc_add_controls(codec, ad1980_snd_ac97_controls, 258 snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
259 ARRAY_SIZE(ad1980_snd_ac97_controls)); 259 ARRAY_SIZE(ad1980_snd_ac97_controls));
260 ret = snd_soc_init_card(socdev);
261 if (ret < 0) {
262 printk(KERN_ERR "ad1980: failed to register card\n");
263 goto reset_err;
264 }
265 260
266 return 0; 261 return 0;
267 262
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index e61dac5e7b8f..d2fcc601722c 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -64,16 +64,8 @@ static int ad73311_soc_probe(struct platform_device *pdev)
64 goto pcm_err; 64 goto pcm_err;
65 } 65 }
66 66
67 ret = snd_soc_init_card(socdev);
68 if (ret < 0) {
69 printk(KERN_ERR "ad73311: failed to register card\n");
70 goto register_err;
71 }
72
73 return ret; 67 return ret;
74 68
75register_err:
76 snd_soc_free_pcms(socdev);
77pcm_err: 69pcm_err:
78 kfree(socdev->card->codec); 70 kfree(socdev->card->codec);
79 socdev->card->codec = NULL; 71 socdev->card->codec = NULL;
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
new file mode 100644
index 000000000000..cc96411ca3e6
--- /dev/null
+++ b/sound/soc/codecs/ads117x.c
@@ -0,0 +1,123 @@
1/*
2 * ads117x.c -- Driver for ads1174/8 ADC chips
3 *
4 * Copyright 2009 ShotSpotter Inc.
5 * Author: Graeme Gregory <gg@slimlogic.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/device.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/initval.h>
19#include <sound/soc.h>
20
21#include "ads117x.h"
22
23#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
24
25#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
26
27struct snd_soc_dai ads117x_dai = {
28/* ADC */
29 .name = "ADS117X ADC",
30 .id = 1,
31 .capture = {
32 .stream_name = "Capture",
33 .channels_min = 1,
34 .channels_max = 32,
35 .rates = ADS117X_RATES,
36 .formats = ADS117X_FORMATS,},
37};
38EXPORT_SYMBOL_GPL(ads117x_dai);
39
40static int ads117x_probe(struct platform_device *pdev)
41{
42 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
43 struct snd_soc_codec *codec;
44 int ret;
45
46 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
47 if (codec == NULL)
48 return -ENOMEM;
49
50 socdev->card->codec = codec;
51 mutex_init(&codec->mutex);
52 INIT_LIST_HEAD(&codec->dapm_widgets);
53 INIT_LIST_HEAD(&codec->dapm_paths);
54 codec->name = "ADS117X";
55 codec->owner = THIS_MODULE;
56 codec->dai = &ads117x_dai;
57 codec->num_dai = 1;
58
59 /* register pcms */
60 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
61 if (ret < 0) {
62 printk(KERN_ERR "ads117x: failed to create pcms\n");
63 kfree(codec);
64 return ret;
65 }
66
67 return 0;
68}
69
70static int ads117x_remove(struct platform_device *pdev)
71{
72 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
73 struct snd_soc_codec *codec = socdev->card->codec;
74
75 snd_soc_free_pcms(socdev);
76 kfree(codec);
77
78 return 0;
79}
80
81struct snd_soc_codec_device soc_codec_dev_ads117x = {
82 .probe = ads117x_probe,
83 .remove = ads117x_remove,
84};
85EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x);
86
87static __devinit int ads117x_platform_probe(struct platform_device *pdev)
88{
89 ads117x_dai.dev = &pdev->dev;
90 return snd_soc_register_dai(&ads117x_dai);
91}
92
93static int __devexit ads117x_platform_remove(struct platform_device *pdev)
94{
95 snd_soc_unregister_dai(&ads117x_dai);
96 return 0;
97}
98
99static struct platform_driver ads117x_codec_driver = {
100 .driver = {
101 .name = "ads117x",
102 .owner = THIS_MODULE,
103 },
104
105 .probe = ads117x_platform_probe,
106 .remove = __devexit_p(ads117x_platform_remove),
107};
108
109static int __init ads117x_init(void)
110{
111 return platform_driver_register(&ads117x_codec_driver);
112}
113module_init(ads117x_init);
114
115static void __exit ads117x_exit(void)
116{
117 platform_driver_unregister(&ads117x_codec_driver);
118}
119module_exit(ads117x_exit);
120
121MODULE_DESCRIPTION("ASoC ads117x driver");
122MODULE_AUTHOR("Graeme Gregory");
123MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
new file mode 100644
index 000000000000..dbcf50ec9bd1
--- /dev/null
+++ b/sound/soc/codecs/ads117x.h
@@ -0,0 +1,13 @@
1/*
2 * ads117x.h -- Driver for ads1174/8 ADC chips
3 *
4 * Copyright 2009 ShotSpotter Inc.
5 * Author: Graeme Gregory <gg@slimlogic.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12extern struct snd_soc_dai ads117x_dai;
13extern struct snd_soc_codec_device soc_codec_dev_ads117x;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 4d47bc4f7428..3a14c6fc4f5e 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -313,14 +313,6 @@ static int ak4104_probe(struct platform_device *pdev)
313 return ret; 313 return ret;
314 } 314 }
315 315
316 /* Register the socdev */
317 ret = snd_soc_init_card(socdev);
318 if (ret < 0) {
319 dev_err(codec->dev, "failed to register card\n");
320 snd_soc_free_pcms(socdev);
321 return ret;
322 }
323
324 return 0; 316 return 0;
325} 317}
326 318
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 0abec0d29a96..ff966567e2ba 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -294,7 +294,6 @@ static int ak4535_add_widgets(struct snd_soc_codec *codec)
294 294
295 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 295 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
296 296
297 snd_soc_dapm_new_widgets(codec);
298 return 0; 297 return 0;
299} 298}
300 299
@@ -485,17 +484,9 @@ static int ak4535_init(struct snd_soc_device *socdev)
485 snd_soc_add_controls(codec, ak4535_snd_controls, 484 snd_soc_add_controls(codec, ak4535_snd_controls,
486 ARRAY_SIZE(ak4535_snd_controls)); 485 ARRAY_SIZE(ak4535_snd_controls));
487 ak4535_add_widgets(codec); 486 ak4535_add_widgets(codec);
488 ret = snd_soc_init_card(socdev);
489 if (ret < 0) {
490 printk(KERN_ERR "ak4535: failed to register card\n");
491 goto card_err;
492 }
493 487
494 return ret; 488 return ret;
495 489
496card_err:
497 snd_soc_free_pcms(socdev);
498 snd_soc_dapm_free(socdev);
499pcm_err: 490pcm_err:
500 kfree(codec->reg_cache); 491 kfree(codec->reg_cache);
501 492
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index e057c7b578df..b69861d52161 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -442,18 +442,9 @@ static int ak4642_probe(struct platform_device *pdev)
442 goto pcm_err; 442 goto pcm_err;
443 } 443 }
444 444
445 ret = snd_soc_init_card(socdev);
446 if (ret < 0) {
447 printk(KERN_ERR "ak4642: failed to register card\n");
448 goto card_err;
449 }
450
451 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); 445 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
452 return ret; 446 return ret;
453 447
454card_err:
455 snd_soc_free_pcms(socdev);
456 snd_soc_dapm_free(socdev);
457pcm_err: 448pcm_err:
458 return ret; 449 return ret;
459 450
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
new file mode 100644
index 000000000000..82fca284d007
--- /dev/null
+++ b/sound/soc/codecs/ak4671.c
@@ -0,0 +1,815 @@
1/*
2 * ak4671.c -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/i2c.h>
17#include <linux/delay.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/initval.h>
21#include <sound/tlv.h>
22
23#include "ak4671.h"
24
25static struct snd_soc_codec *ak4671_codec;
26
27/* codec private data */
28struct ak4671_priv {
29 struct snd_soc_codec codec;
30 u8 reg_cache[AK4671_CACHEREGNUM];
31};
32
33/* ak4671 register cache & default register settings */
34static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
35 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
36 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
37 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
38 0x02, /* AK4671_FORMAT_SELECT (0x03) */
39 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
40 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
41 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
42 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
43 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
44 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
45 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
46 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
47 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
48 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
49 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
50 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
51 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
52 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
53 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
54 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
55 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
56 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
57 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
58 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
59 0x02, /* AK4671_MODE_CONTROL1 (0x18) */
60 0x01, /* AK4671_MODE_CONTROL2 (0x19) */
61 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
62 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
63 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
64 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
65 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
66 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
67 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
68 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
69 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
70 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
71 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
72 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
73 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
74 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
75 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
76 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
77 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
78 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
79 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
80 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
81 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
82 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
83 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
84 0x00, /* this register not used */
85 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
86 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
87 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
88 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
89 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
90 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
91 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
92 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
93 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
94 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
95 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
96 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
97 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
98 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
99 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
100 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
101 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
102 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
103 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
104 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
105 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
106 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
107 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
108 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
109 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
110 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
111 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
112 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
113 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
114 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
115 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
116 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
117 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
118 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
119 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
120 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
121 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
122 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
123 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
124 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
125 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
126};
127
128/*
129 * LOUT1/ROUT1 output volume control:
130 * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB)
131 */
132static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1);
133
134/*
135 * LOUT2/ROUT2 output volume control:
136 * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB)
137 */
138static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1);
139
140/*
141 * LOUT3/ROUT3 output volume control:
142 * from -6 to 3 dB in 3 dB steps
143 */
144static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0);
145
146/*
147 * Mic amp gain control:
148 * from -15 to 30 dB in 3 dB steps
149 * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not
150 * available
151 */
152static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0);
153
154static const struct snd_kcontrol_new ak4671_snd_controls[] = {
155 /* Common playback gain controls */
156 SOC_SINGLE_TLV("Line Output1 Playback Volume",
157 AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv),
158 SOC_SINGLE_TLV("Headphone Output2 Playback Volume",
159 AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv),
160 SOC_SINGLE_TLV("Line Output3 Playback Volume",
161 AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv),
162
163 /* Common capture gain controls */
164 SOC_DOUBLE_TLV("Mic Amp Capture Volume",
165 AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv),
166};
167
168/* event handlers */
169static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
170 struct snd_kcontrol *kcontrol, int event)
171{
172 struct snd_soc_codec *codec = w->codec;
173 u8 reg;
174
175 switch (event) {
176 case SND_SOC_DAPM_POST_PMU:
177 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
178 reg |= AK4671_MUTEN;
179 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
180 break;
181 case SND_SOC_DAPM_PRE_PMD:
182 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
183 reg &= ~AK4671_MUTEN;
184 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
185 break;
186 }
187
188 return 0;
189}
190
191/* Output Mixers */
192static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = {
193 SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0),
194 SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0),
195 SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0),
196 SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0),
197 SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0),
198 SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0),
199};
200
201static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = {
202 SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0),
203 SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0),
204 SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0),
205 SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0),
206 SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0),
207 SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0),
208};
209
210static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = {
211 SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0),
212 SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0),
213 SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0),
214 SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0),
215 SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0),
216 SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0),
217};
218
219static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = {
220 SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0),
221 SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0),
222 SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0),
223 SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0),
224 SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0),
225 SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0),
226};
227
228static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = {
229 SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0),
230 SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0),
231 SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0),
232 SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0),
233 SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0),
234 SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0),
235};
236
237static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = {
238 SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0),
239 SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0),
240 SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0),
241 SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0),
242 SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0),
243 SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0),
244};
245
246/* Input MUXs */
247static const char *ak4671_lin_mux_texts[] =
248 {"LIN1", "LIN2", "LIN3", "LIN4"};
249static const struct soc_enum ak4671_lin_mux_enum =
250 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
251 ARRAY_SIZE(ak4671_lin_mux_texts),
252 ak4671_lin_mux_texts);
253static const struct snd_kcontrol_new ak4671_lin_mux_control =
254 SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
255
256static const char *ak4671_rin_mux_texts[] =
257 {"RIN1", "RIN2", "RIN3", "RIN4"};
258static const struct soc_enum ak4671_rin_mux_enum =
259 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
260 ARRAY_SIZE(ak4671_rin_mux_texts),
261 ak4671_rin_mux_texts);
262static const struct snd_kcontrol_new ak4671_rin_mux_control =
263 SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
264
265static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = {
266 /* Inputs */
267 SND_SOC_DAPM_INPUT("LIN1"),
268 SND_SOC_DAPM_INPUT("RIN1"),
269 SND_SOC_DAPM_INPUT("LIN2"),
270 SND_SOC_DAPM_INPUT("RIN2"),
271 SND_SOC_DAPM_INPUT("LIN3"),
272 SND_SOC_DAPM_INPUT("RIN3"),
273 SND_SOC_DAPM_INPUT("LIN4"),
274 SND_SOC_DAPM_INPUT("RIN4"),
275
276 /* Outputs */
277 SND_SOC_DAPM_OUTPUT("LOUT1"),
278 SND_SOC_DAPM_OUTPUT("ROUT1"),
279 SND_SOC_DAPM_OUTPUT("LOUT2"),
280 SND_SOC_DAPM_OUTPUT("ROUT2"),
281 SND_SOC_DAPM_OUTPUT("LOUT3"),
282 SND_SOC_DAPM_OUTPUT("ROUT3"),
283
284 /* DAC */
285 SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback",
286 AK4671_AD_DA_POWER_MANAGEMENT, 6, 0),
287 SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback",
288 AK4671_AD_DA_POWER_MANAGEMENT, 7, 0),
289
290 /* ADC */
291 SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture",
292 AK4671_AD_DA_POWER_MANAGEMENT, 4, 0),
293 SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture",
294 AK4671_AD_DA_POWER_MANAGEMENT, 5, 0),
295
296 /* PGA */
297 SND_SOC_DAPM_PGA("LOUT2 Mix Amp",
298 AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0),
299 SND_SOC_DAPM_PGA("ROUT2 Mix Amp",
300 AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0),
301
302 SND_SOC_DAPM_PGA("LIN1 Mixing Circuit",
303 AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0),
304 SND_SOC_DAPM_PGA("RIN1 Mixing Circuit",
305 AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0),
306 SND_SOC_DAPM_PGA("LIN2 Mixing Circuit",
307 AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0),
308 SND_SOC_DAPM_PGA("RIN2 Mixing Circuit",
309 AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0),
310 SND_SOC_DAPM_PGA("LIN3 Mixing Circuit",
311 AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0),
312 SND_SOC_DAPM_PGA("RIN3 Mixing Circuit",
313 AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0),
314 SND_SOC_DAPM_PGA("LIN4 Mixing Circuit",
315 AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0),
316 SND_SOC_DAPM_PGA("RIN4 Mixing Circuit",
317 AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0),
318
319 /* Output Mixers */
320 SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0,
321 &ak4671_lout1_mixer_controls[0],
322 ARRAY_SIZE(ak4671_lout1_mixer_controls)),
323 SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0,
324 &ak4671_rout1_mixer_controls[0],
325 ARRAY_SIZE(ak4671_rout1_mixer_controls)),
326 SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
327 0, 0, &ak4671_lout2_mixer_controls[0],
328 ARRAY_SIZE(ak4671_lout2_mixer_controls),
329 ak4671_out2_event,
330 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
331 SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
332 1, 0, &ak4671_rout2_mixer_controls[0],
333 ARRAY_SIZE(ak4671_rout2_mixer_controls),
334 ak4671_out2_event,
335 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
336 SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0,
337 &ak4671_lout3_mixer_controls[0],
338 ARRAY_SIZE(ak4671_lout3_mixer_controls)),
339 SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0,
340 &ak4671_rout3_mixer_controls[0],
341 ARRAY_SIZE(ak4671_rout3_mixer_controls)),
342
343 /* Input MUXs */
344 SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0,
345 &ak4671_lin_mux_control),
346 SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0,
347 &ak4671_rin_mux_control),
348
349 /* Mic Power */
350 SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0),
351
352 /* Supply */
353 SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0),
354};
355
356static const struct snd_soc_dapm_route intercon[] = {
357 {"DAC Left", "NULL", "PMPLL"},
358 {"DAC Right", "NULL", "PMPLL"},
359 {"ADC Left", "NULL", "PMPLL"},
360 {"ADC Right", "NULL", "PMPLL"},
361
362 /* Outputs */
363 {"LOUT1", "NULL", "LOUT1 Mixer"},
364 {"ROUT1", "NULL", "ROUT1 Mixer"},
365 {"LOUT2", "NULL", "LOUT2 Mix Amp"},
366 {"ROUT2", "NULL", "ROUT2 Mix Amp"},
367 {"LOUT3", "NULL", "LOUT3 Mixer"},
368 {"ROUT3", "NULL", "ROUT3 Mixer"},
369
370 {"LOUT1 Mixer", "DACL", "DAC Left"},
371 {"ROUT1 Mixer", "DACR", "DAC Right"},
372 {"LOUT2 Mixer", "DACHL", "DAC Left"},
373 {"ROUT2 Mixer", "DACHR", "DAC Right"},
374 {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"},
375 {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"},
376 {"LOUT3 Mixer", "DACSL", "DAC Left"},
377 {"ROUT3 Mixer", "DACSR", "DAC Right"},
378
379 /* Inputs */
380 {"LIN MUX", "LIN1", "LIN1"},
381 {"LIN MUX", "LIN2", "LIN2"},
382 {"LIN MUX", "LIN3", "LIN3"},
383 {"LIN MUX", "LIN4", "LIN4"},
384
385 {"RIN MUX", "RIN1", "RIN1"},
386 {"RIN MUX", "RIN2", "RIN2"},
387 {"RIN MUX", "RIN3", "RIN3"},
388 {"RIN MUX", "RIN4", "RIN4"},
389
390 {"LIN1", NULL, "Mic Bias"},
391 {"RIN1", NULL, "Mic Bias"},
392 {"LIN2", NULL, "Mic Bias"},
393 {"RIN2", NULL, "Mic Bias"},
394
395 {"ADC Left", "NULL", "LIN MUX"},
396 {"ADC Right", "NULL", "RIN MUX"},
397
398 /* Analog Loops */
399 {"LIN1 Mixing Circuit", "NULL", "LIN1"},
400 {"RIN1 Mixing Circuit", "NULL", "RIN1"},
401 {"LIN2 Mixing Circuit", "NULL", "LIN2"},
402 {"RIN2 Mixing Circuit", "NULL", "RIN2"},
403 {"LIN3 Mixing Circuit", "NULL", "LIN3"},
404 {"RIN3 Mixing Circuit", "NULL", "RIN3"},
405 {"LIN4 Mixing Circuit", "NULL", "LIN4"},
406 {"RIN4 Mixing Circuit", "NULL", "RIN4"},
407
408 {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"},
409 {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"},
410 {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"},
411 {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"},
412 {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"},
413 {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"},
414
415 {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"},
416 {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"},
417 {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"},
418 {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"},
419 {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"},
420 {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"},
421
422 {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"},
423 {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"},
424 {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"},
425 {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"},
426 {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"},
427 {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"},
428
429 {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"},
430 {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"},
431 {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"},
432 {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"},
433 {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"},
434 {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"},
435};
436
437static int ak4671_add_widgets(struct snd_soc_codec *codec)
438{
439 snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets,
440 ARRAY_SIZE(ak4671_dapm_widgets));
441
442 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
443
444 return 0;
445}
446
447static int ak4671_hw_params(struct snd_pcm_substream *substream,
448 struct snd_pcm_hw_params *params,
449 struct snd_soc_dai *dai)
450{
451 struct snd_soc_codec *codec = dai->codec;
452 u8 fs;
453
454 fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
455 fs &= ~AK4671_FS;
456
457 switch (params_rate(params)) {
458 case 8000:
459 fs |= AK4671_FS_8KHZ;
460 break;
461 case 12000:
462 fs |= AK4671_FS_12KHZ;
463 break;
464 case 16000:
465 fs |= AK4671_FS_16KHZ;
466 break;
467 case 24000:
468 fs |= AK4671_FS_24KHZ;
469 break;
470 case 11025:
471 fs |= AK4671_FS_11_025KHZ;
472 break;
473 case 22050:
474 fs |= AK4671_FS_22_05KHZ;
475 break;
476 case 32000:
477 fs |= AK4671_FS_32KHZ;
478 break;
479 case 44100:
480 fs |= AK4671_FS_44_1KHZ;
481 break;
482 case 48000:
483 fs |= AK4671_FS_48KHZ;
484 break;
485 default:
486 return -EINVAL;
487 }
488
489 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs);
490
491 return 0;
492}
493
494static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
495 unsigned int freq, int dir)
496{
497 struct snd_soc_codec *codec = dai->codec;
498 u8 pll;
499
500 pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
501 pll &= ~AK4671_PLL;
502
503 switch (freq) {
504 case 11289600:
505 pll |= AK4671_PLL_11_2896MHZ;
506 break;
507 case 12000000:
508 pll |= AK4671_PLL_12MHZ;
509 break;
510 case 12288000:
511 pll |= AK4671_PLL_12_288MHZ;
512 break;
513 case 13000000:
514 pll |= AK4671_PLL_13MHZ;
515 break;
516 case 13500000:
517 pll |= AK4671_PLL_13_5MHZ;
518 break;
519 case 19200000:
520 pll |= AK4671_PLL_19_2MHZ;
521 break;
522 case 24000000:
523 pll |= AK4671_PLL_24MHZ;
524 break;
525 case 26000000:
526 pll |= AK4671_PLL_26MHZ;
527 break;
528 case 27000000:
529 pll |= AK4671_PLL_27MHZ;
530 break;
531 default:
532 return -EINVAL;
533 }
534
535 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll);
536
537 return 0;
538}
539
540static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
541{
542 struct snd_soc_codec *codec = dai->codec;
543 u8 mode;
544 u8 format;
545
546 /* set master/slave audio interface */
547 mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1);
548
549 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
550 case SND_SOC_DAIFMT_CBM_CFM:
551 mode |= AK4671_M_S;
552 break;
553 case SND_SOC_DAIFMT_CBM_CFS:
554 mode &= ~(AK4671_M_S);
555 break;
556 default:
557 return -EINVAL;
558 }
559
560 /* interface format */
561 format = snd_soc_read(codec, AK4671_FORMAT_SELECT);
562 format &= ~AK4671_DIF;
563
564 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
565 case SND_SOC_DAIFMT_I2S:
566 format |= AK4671_DIF_I2S_MODE;
567 break;
568 case SND_SOC_DAIFMT_LEFT_J:
569 format |= AK4671_DIF_MSB_MODE;
570 break;
571 case SND_SOC_DAIFMT_DSP_A:
572 format |= AK4671_DIF_DSP_MODE;
573 format |= AK4671_BCKP;
574 format |= AK4671_MSBS;
575 break;
576 default:
577 return -EINVAL;
578 }
579
580 /* set mode and format */
581 snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode);
582 snd_soc_write(codec, AK4671_FORMAT_SELECT, format);
583
584 return 0;
585}
586
587static int ak4671_set_bias_level(struct snd_soc_codec *codec,
588 enum snd_soc_bias_level level)
589{
590 u8 reg;
591
592 switch (level) {
593 case SND_SOC_BIAS_ON:
594 case SND_SOC_BIAS_PREPARE:
595 case SND_SOC_BIAS_STANDBY:
596 reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
597 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
598 reg | AK4671_PMVCM);
599 break;
600 case SND_SOC_BIAS_OFF:
601 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
602 break;
603 }
604 codec->bias_level = level;
605 return 0;
606}
607
608#define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
609 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
610 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
611 SNDRV_PCM_RATE_48000)
612
613#define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE
614
615static struct snd_soc_dai_ops ak4671_dai_ops = {
616 .hw_params = ak4671_hw_params,
617 .set_sysclk = ak4671_set_dai_sysclk,
618 .set_fmt = ak4671_set_dai_fmt,
619};
620
621struct snd_soc_dai ak4671_dai = {
622 .name = "AK4671",
623 .playback = {
624 .stream_name = "Playback",
625 .channels_min = 1,
626 .channels_max = 2,
627 .rates = AK4671_RATES,
628 .formats = AK4671_FORMATS,},
629 .capture = {
630 .stream_name = "Capture",
631 .channels_min = 1,
632 .channels_max = 2,
633 .rates = AK4671_RATES,
634 .formats = AK4671_FORMATS,},
635 .ops = &ak4671_dai_ops,
636};
637EXPORT_SYMBOL_GPL(ak4671_dai);
638
639static int ak4671_probe(struct platform_device *pdev)
640{
641 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
642 struct snd_soc_codec *codec;
643 int ret = 0;
644
645 if (ak4671_codec == NULL) {
646 dev_err(&pdev->dev, "Codec device not registered\n");
647 return -ENODEV;
648 }
649
650 socdev->card->codec = ak4671_codec;
651 codec = ak4671_codec;
652
653 /* register pcms */
654 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
655 if (ret < 0) {
656 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
657 goto pcm_err;
658 }
659
660 snd_soc_add_controls(codec, ak4671_snd_controls,
661 ARRAY_SIZE(ak4671_snd_controls));
662 ak4671_add_widgets(codec);
663
664 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
665
666 return ret;
667
668pcm_err:
669 return ret;
670}
671
672static int ak4671_remove(struct platform_device *pdev)
673{
674 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
675
676 snd_soc_free_pcms(socdev);
677 snd_soc_dapm_free(socdev);
678
679 return 0;
680}
681
682struct snd_soc_codec_device soc_codec_dev_ak4671 = {
683 .probe = ak4671_probe,
684 .remove = ak4671_remove,
685};
686EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
687
688static int ak4671_register(struct ak4671_priv *ak4671,
689 enum snd_soc_control_type control)
690{
691 int ret;
692 struct snd_soc_codec *codec = &ak4671->codec;
693
694 if (ak4671_codec) {
695 dev_err(codec->dev, "Another AK4671 is registered\n");
696 ret = -EINVAL;
697 goto err;
698 }
699
700 mutex_init(&codec->mutex);
701 INIT_LIST_HEAD(&codec->dapm_widgets);
702 INIT_LIST_HEAD(&codec->dapm_paths);
703
704 codec->private_data = ak4671;
705 codec->name = "AK4671";
706 codec->owner = THIS_MODULE;
707 codec->bias_level = SND_SOC_BIAS_OFF;
708 codec->set_bias_level = ak4671_set_bias_level;
709 codec->dai = &ak4671_dai;
710 codec->num_dai = 1;
711 codec->reg_cache_size = AK4671_CACHEREGNUM;
712 codec->reg_cache = &ak4671->reg_cache;
713
714 memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
715
716 ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
717 if (ret < 0) {
718 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
719 goto err;
720 }
721
722 ak4671_dai.dev = codec->dev;
723 ak4671_codec = codec;
724
725 ret = snd_soc_register_codec(codec);
726 if (ret != 0) {
727 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
728 goto err;
729 }
730
731 ret = snd_soc_register_dai(&ak4671_dai);
732 if (ret != 0) {
733 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
734 goto err_codec;
735 }
736
737 return 0;
738
739err_codec:
740 snd_soc_unregister_codec(codec);
741err:
742 kfree(ak4671);
743 return ret;
744}
745
746static void ak4671_unregister(struct ak4671_priv *ak4671)
747{
748 ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
749 snd_soc_unregister_dai(&ak4671_dai);
750 snd_soc_unregister_codec(&ak4671->codec);
751 kfree(ak4671);
752 ak4671_codec = NULL;
753}
754
755static int __devinit ak4671_i2c_probe(struct i2c_client *client,
756 const struct i2c_device_id *id)
757{
758 struct ak4671_priv *ak4671;
759 struct snd_soc_codec *codec;
760
761 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
762 if (ak4671 == NULL)
763 return -ENOMEM;
764
765 codec = &ak4671->codec;
766 codec->hw_write = (hw_write_t)i2c_master_send;
767
768 i2c_set_clientdata(client, ak4671);
769 codec->control_data = client;
770
771 codec->dev = &client->dev;
772
773 return ak4671_register(ak4671, SND_SOC_I2C);
774}
775
776static __devexit int ak4671_i2c_remove(struct i2c_client *client)
777{
778 struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
779
780 ak4671_unregister(ak4671);
781
782 return 0;
783}
784
785static const struct i2c_device_id ak4671_i2c_id[] = {
786 { "ak4671", 0 },
787 { }
788};
789MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
790
791static struct i2c_driver ak4671_i2c_driver = {
792 .driver = {
793 .name = "ak4671",
794 .owner = THIS_MODULE,
795 },
796 .probe = ak4671_i2c_probe,
797 .remove = __devexit_p(ak4671_i2c_remove),
798 .id_table = ak4671_i2c_id,
799};
800
801static int __init ak4671_modinit(void)
802{
803 return i2c_add_driver(&ak4671_i2c_driver);
804}
805module_init(ak4671_modinit);
806
807static void __exit ak4671_exit(void)
808{
809 i2c_del_driver(&ak4671_i2c_driver);
810}
811module_exit(ak4671_exit);
812
813MODULE_DESCRIPTION("ASoC AK4671 codec driver");
814MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
815MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
new file mode 100644
index 000000000000..e2fad964e88b
--- /dev/null
+++ b/sound/soc/codecs/ak4671.h
@@ -0,0 +1,156 @@
1/*
2 * ak4671.h -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#ifndef _AK4671_H
15#define _AK4671_H
16
17#define AK4671_AD_DA_POWER_MANAGEMENT 0x00
18#define AK4671_PLL_MODE_SELECT0 0x01
19#define AK4671_PLL_MODE_SELECT1 0x02
20#define AK4671_FORMAT_SELECT 0x03
21#define AK4671_MIC_SIGNAL_SELECT 0x04
22#define AK4671_MIC_AMP_GAIN 0x05
23#define AK4671_MIXING_POWER_MANAGEMENT0 0x06
24#define AK4671_MIXING_POWER_MANAGEMENT1 0x07
25#define AK4671_OUTPUT_VOLUME_CONTROL 0x08
26#define AK4671_LOUT1_SIGNAL_SELECT 0x09
27#define AK4671_ROUT1_SIGNAL_SELECT 0x0a
28#define AK4671_LOUT2_SIGNAL_SELECT 0x0b
29#define AK4671_ROUT2_SIGNAL_SELECT 0x0c
30#define AK4671_LOUT3_SIGNAL_SELECT 0x0d
31#define AK4671_ROUT3_SIGNAL_SELECT 0x0e
32#define AK4671_LOUT1_POWER_MANAGERMENT 0x0f
33#define AK4671_LOUT2_POWER_MANAGERMENT 0x10
34#define AK4671_LOUT3_POWER_MANAGERMENT 0x11
35#define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12
36#define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13
37#define AK4671_ALC_REFERENCE_SELECT 0x14
38#define AK4671_DIGITAL_MIXING_CONTROL 0x15
39#define AK4671_ALC_TIMER_SELECT 0x16
40#define AK4671_ALC_MODE_CONTROL 0x17
41#define AK4671_MODE_CONTROL1 0x18
42#define AK4671_MODE_CONTROL2 0x19
43#define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a
44#define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b
45#define AK4671_SIDETONE_A_CONTROL 0x1c
46#define AK4671_DIGITAL_FILTER_SELECT 0x1d
47#define AK4671_FIL3_COEFFICIENT0 0x1e
48#define AK4671_FIL3_COEFFICIENT1 0x1f
49#define AK4671_FIL3_COEFFICIENT2 0x20
50#define AK4671_FIL3_COEFFICIENT3 0x21
51#define AK4671_EQ_COEFFICIENT0 0x22
52#define AK4671_EQ_COEFFICIENT1 0x23
53#define AK4671_EQ_COEFFICIENT2 0x24
54#define AK4671_EQ_COEFFICIENT3 0x25
55#define AK4671_EQ_COEFFICIENT4 0x26
56#define AK4671_EQ_COEFFICIENT5 0x27
57#define AK4671_FIL1_COEFFICIENT0 0x28
58#define AK4671_FIL1_COEFFICIENT1 0x29
59#define AK4671_FIL1_COEFFICIENT2 0x2a
60#define AK4671_FIL1_COEFFICIENT3 0x2b
61#define AK4671_FIL2_COEFFICIENT0 0x2c
62#define AK4671_FIL2_COEFFICIENT1 0x2d
63#define AK4671_FIL2_COEFFICIENT2 0x2e
64#define AK4671_FIL2_COEFFICIENT3 0x2f
65#define AK4671_DIGITAL_FILTER_SELECT2 0x30
66#define AK4671_E1_COEFFICIENT0 0x32
67#define AK4671_E1_COEFFICIENT1 0x33
68#define AK4671_E1_COEFFICIENT2 0x34
69#define AK4671_E1_COEFFICIENT3 0x35
70#define AK4671_E1_COEFFICIENT4 0x36
71#define AK4671_E1_COEFFICIENT5 0x37
72#define AK4671_E2_COEFFICIENT0 0x38
73#define AK4671_E2_COEFFICIENT1 0x39
74#define AK4671_E2_COEFFICIENT2 0x3a
75#define AK4671_E2_COEFFICIENT3 0x3b
76#define AK4671_E2_COEFFICIENT4 0x3c
77#define AK4671_E2_COEFFICIENT5 0x3d
78#define AK4671_E3_COEFFICIENT0 0x3e
79#define AK4671_E3_COEFFICIENT1 0x3f
80#define AK4671_E3_COEFFICIENT2 0x40
81#define AK4671_E3_COEFFICIENT3 0x41
82#define AK4671_E3_COEFFICIENT4 0x42
83#define AK4671_E3_COEFFICIENT5 0x43
84#define AK4671_E4_COEFFICIENT0 0x44
85#define AK4671_E4_COEFFICIENT1 0x45
86#define AK4671_E4_COEFFICIENT2 0x46
87#define AK4671_E4_COEFFICIENT3 0x47
88#define AK4671_E4_COEFFICIENT4 0x48
89#define AK4671_E4_COEFFICIENT5 0x49
90#define AK4671_E5_COEFFICIENT0 0x4a
91#define AK4671_E5_COEFFICIENT1 0x4b
92#define AK4671_E5_COEFFICIENT2 0x4c
93#define AK4671_E5_COEFFICIENT3 0x4d
94#define AK4671_E5_COEFFICIENT4 0x4e
95#define AK4671_E5_COEFFICIENT5 0x4f
96#define AK4671_EQ_CONTROL_250HZ_100HZ 0x50
97#define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51
98#define AK4671_EQ_CONTRO_10KHZ 0x52
99#define AK4671_PCM_IF_CONTROL0 0x53
100#define AK4671_PCM_IF_CONTROL1 0x54
101#define AK4671_PCM_IF_CONTROL2 0x55
102#define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56
103#define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57
104#define AK4671_SIDETONE_VOLUME_CONTROL 0x58
105#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
106#define AK4671_SAR_ADC_CONTROL 0x5a
107
108#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
109
110/* Bitfield Definitions */
111
112/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
113#define AK4671_PMVCM 0x01
114
115/* AK4671_PLL_MODE_SELECT0 (0x01) Fields */
116#define AK4671_PLL 0x0f
117#define AK4671_PLL_11_2896MHZ (4 << 0)
118#define AK4671_PLL_12_288MHZ (5 << 0)
119#define AK4671_PLL_12MHZ (6 << 0)
120#define AK4671_PLL_24MHZ (7 << 0)
121#define AK4671_PLL_19_2MHZ (8 << 0)
122#define AK4671_PLL_13_5MHZ (12 << 0)
123#define AK4671_PLL_27MHZ (13 << 0)
124#define AK4671_PLL_13MHZ (14 << 0)
125#define AK4671_PLL_26MHZ (15 << 0)
126#define AK4671_FS 0xf0
127#define AK4671_FS_8KHZ (0 << 4)
128#define AK4671_FS_12KHZ (1 << 4)
129#define AK4671_FS_16KHZ (2 << 4)
130#define AK4671_FS_24KHZ (3 << 4)
131#define AK4671_FS_11_025KHZ (5 << 4)
132#define AK4671_FS_22_05KHZ (7 << 4)
133#define AK4671_FS_32KHZ (10 << 4)
134#define AK4671_FS_48KHZ (11 << 4)
135#define AK4671_FS_44_1KHZ (15 << 4)
136
137/* AK4671_PLL_MODE_SELECT1 (0x02) Fields */
138#define AK4671_PMPLL 0x01
139#define AK4671_M_S 0x02
140
141/* AK4671_FORMAT_SELECT (0x03) Fields */
142#define AK4671_DIF 0x03
143#define AK4671_DIF_DSP_MODE (0 << 0)
144#define AK4671_DIF_MSB_MODE (2 << 0)
145#define AK4671_DIF_I2S_MODE (3 << 0)
146#define AK4671_BCKP 0x04
147#define AK4671_MSBS 0x08
148#define AK4671_SDOD 0x10
149
150/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
151#define AK4671_MUTEN 0x04
152
153extern struct snd_soc_dai ak4671_dai;
154extern struct snd_soc_codec_device soc_codec_dev_ak4671;
155
156#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index ca1e24a8f12a..ffe122d1cd76 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -520,6 +520,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
520 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), 520 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0),
521 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), 521 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0),
522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), 522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
523 SOC_SINGLE("De-emphasis filter", CS4270_TRANS, 0, 1, 0),
523 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), 524 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
524 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), 525 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
525 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), 526 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
@@ -598,13 +599,6 @@ static int cs4270_probe(struct platform_device *pdev)
598 goto error_free_pcms; 599 goto error_free_pcms;
599 } 600 }
600 601
601 /* And finally, register the socdev */
602 ret = snd_soc_init_card(socdev);
603 if (ret < 0) {
604 dev_err(codec->dev, "failed to register card\n");
605 goto error_free_pcms;
606 }
607
608 return 0; 602 return 0;
609 603
610error_free_pcms: 604error_free_pcms:
@@ -802,22 +796,6 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
802 * and all registers are written back to the hardware when resuming. 796 * and all registers are written back to the hardware when resuming.
803 */ 797 */
804 798
805static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
806{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
808 struct snd_soc_codec *codec = &cs4270->codec;
809
810 return snd_soc_suspend_device(codec->dev);
811}
812
813static int cs4270_i2c_resume(struct i2c_client *client)
814{
815 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
816 struct snd_soc_codec *codec = &cs4270->codec;
817
818 return snd_soc_resume_device(codec->dev);
819}
820
821static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 799static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
822{ 800{
823 struct snd_soc_codec *codec = cs4270_codec; 801 struct snd_soc_codec *codec = cs4270_codec;
@@ -853,8 +831,6 @@ static int cs4270_soc_resume(struct platform_device *pdev)
853 return snd_soc_write(codec, CS4270_PWRCTL, reg); 831 return snd_soc_write(codec, CS4270_PWRCTL, reg);
854} 832}
855#else 833#else
856#define cs4270_i2c_suspend NULL
857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL 834#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL 835#define cs4270_soc_resume NULL
860#endif /* CONFIG_PM */ 836#endif /* CONFIG_PM */
@@ -873,8 +849,6 @@ static struct i2c_driver cs4270_i2c_driver = {
873 .id_table = cs4270_id, 849 .id_table = cs4270_id,
874 .probe = cs4270_i2c_probe, 850 .probe = cs4270_i2c_probe,
875 .remove = cs4270_i2c_remove, 851 .remove = cs4270_i2c_remove,
876 .suspend = cs4270_i2c_suspend,
877 .resume = cs4270_i2c_resume,
878}; 852};
879 853
880/* 854/*
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 38eac9c866e1..e000cdfec1ec 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -93,7 +93,6 @@ static int cx20442_add_widgets(struct snd_soc_codec *codec)
93 snd_soc_dapm_add_routes(codec, cx20442_audio_map, 93 snd_soc_dapm_add_routes(codec, cx20442_audio_map,
94 ARRAY_SIZE(cx20442_audio_map)); 94 ARRAY_SIZE(cx20442_audio_map));
95 95
96 snd_soc_dapm_new_widgets(codec);
97 return 0; 96 return 0;
98} 97}
99 98
@@ -355,17 +354,6 @@ static int cx20442_codec_probe(struct platform_device *pdev)
355 354
356 cx20442_add_widgets(codec); 355 cx20442_add_widgets(codec);
357 356
358 ret = snd_soc_init_card(socdev);
359 if (ret < 0) {
360 dev_err(&pdev->dev, "failed to register card\n");
361 goto card_err;
362 }
363
364 return ret;
365
366card_err:
367 snd_soc_free_pcms(socdev);
368 snd_soc_dapm_free(socdev);
369pcm_err: 357pcm_err:
370 return ret; 358 return ret;
371} 359}
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 5cda9e6b5a74..2afcd0a8669d 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -90,13 +90,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
90 goto pcm_err; 90 goto pcm_err;
91 } 91 }
92 92
93 /* Register Card. */
94 ret = snd_soc_init_card(socdev);
95 if (ret < 0) {
96 printk(KERN_ERR "pcm3008: failed to register card\n");
97 goto card_err;
98 }
99
100 /* DEM1 DEM0 DE-EMPHASIS_MODE 93 /* DEM1 DEM0 DE-EMPHASIS_MODE
101 * Low Low De-emphasis 44.1 kHz ON 94 * Low Low De-emphasis 44.1 kHz ON
102 * Low High De-emphasis OFF 95 * Low High De-emphasis OFF
@@ -136,8 +129,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
136 129
137gpio_err: 130gpio_err:
138 pcm3008_gpio_free(setup); 131 pcm3008_gpio_free(setup);
139card_err:
140 snd_soc_free_pcms(socdev);
141pcm_err: 132pcm_err:
142 kfree(socdev->card->codec); 133 kfree(socdev->card->codec);
143 134
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index c550750c79c0..d2ff1cde6883 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -210,7 +210,6 @@ static int ssm2602_add_widgets(struct snd_soc_codec *codec)
210 210
211 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn)); 211 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn));
212 212
213 snd_soc_dapm_new_widgets(codec);
214 return 0; 213 return 0;
215} 214}
216 215
@@ -613,17 +612,9 @@ static int ssm2602_init(struct snd_soc_device *socdev)
613 snd_soc_add_controls(codec, ssm2602_snd_controls, 612 snd_soc_add_controls(codec, ssm2602_snd_controls,
614 ARRAY_SIZE(ssm2602_snd_controls)); 613 ARRAY_SIZE(ssm2602_snd_controls));
615 ssm2602_add_widgets(codec); 614 ssm2602_add_widgets(codec);
616 ret = snd_soc_init_card(socdev);
617 if (ret < 0) {
618 pr_err("ssm2602: failed to register card\n");
619 goto card_err;
620 }
621 615
622 return ret; 616 return ret;
623 617
624card_err:
625 snd_soc_free_pcms(socdev);
626 snd_soc_dapm_free(socdev);
627pcm_err: 618pcm_err:
628 kfree(codec->reg_cache); 619 kfree(codec->reg_cache);
629 return ret; 620 return ret;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index befc6488c39a..bbc72c2ddfca 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -418,9 +418,6 @@ static int stac9766_codec_probe(struct platform_device *pdev)
418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls, 418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
419 ARRAY_SIZE(stac9766_snd_ac97_controls)); 419 ARRAY_SIZE(stac9766_snd_ac97_controls));
420 420
421 ret = snd_soc_init_card(socdev);
422 if (ret < 0)
423 goto reset_err;
424 return 0; 421 return 0;
425 422
426reset_err: 423reset_err:
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 90a0264f7538..a9dc5fb54774 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -85,7 +85,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
85 * of data into val 85 * of data into val
86 */ 86 */
87 87
88 if ((reg < 0 || reg > 9) && (reg != 15)) { 88 if (reg > 9 && reg != 15) {
89 printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg); 89 printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
90 return -1; 90 return -1;
91 } 91 }
@@ -395,7 +395,6 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
395 /* set up audio path interconnects */ 395 /* set up audio path interconnects */
396 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 396 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
397 397
398 snd_soc_dapm_new_widgets(codec);
399 return 0; 398 return 0;
400} 399}
401 400
@@ -706,17 +705,9 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
706 snd_soc_add_controls(codec, tlv320aic23_snd_controls, 705 snd_soc_add_controls(codec, tlv320aic23_snd_controls,
707 ARRAY_SIZE(tlv320aic23_snd_controls)); 706 ARRAY_SIZE(tlv320aic23_snd_controls));
708 tlv320aic23_add_widgets(codec); 707 tlv320aic23_add_widgets(codec);
709 ret = snd_soc_init_card(socdev);
710 if (ret < 0) {
711 printk(KERN_ERR "tlv320aic23: failed to register card\n");
712 goto card_err;
713 }
714 708
715 return ret; 709 return ret;
716 710
717card_err:
718 snd_soc_free_pcms(socdev);
719 snd_soc_dapm_free(socdev);
720pcm_err: 711pcm_err:
721 kfree(codec->reg_cache); 712 kfree(codec->reg_cache);
722 return ret; 713 return ret;
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 3387d9e736ea..357b609196e3 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -356,18 +356,7 @@ static int aic26_probe(struct platform_device *pdev)
356 ARRAY_SIZE(aic26_snd_controls)); 356 ARRAY_SIZE(aic26_snd_controls));
357 WARN_ON(err < 0); 357 WARN_ON(err < 0);
358 358
359 /* CODEC is setup, we can register the card now */
360 dev_dbg(&pdev->dev, "Registering card\n");
361 ret = snd_soc_init_card(socdev);
362 if (ret < 0) {
363 dev_err(&pdev->dev, "aic26: failed to register card\n");
364 goto card_err;
365 }
366 return 0; 359 return 0;
367
368 card_err:
369 snd_soc_free_pcms(socdev);
370 return ret;
371} 360}
372 361
373static int aic26_remove(struct platform_device *pdev) 362static int aic26_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 3395cf945d56..2b4dc2b0b017 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -753,7 +753,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
753 /* set up audio path interconnects */ 753 /* set up audio path interconnects */
754 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 754 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
755 755
756 snd_soc_dapm_new_widgets(codec);
757 return 0; 756 return 0;
758} 757}
759 758
@@ -1405,18 +1404,8 @@ static int aic3x_probe(struct platform_device *pdev)
1405 1404
1406 aic3x_add_widgets(codec); 1405 aic3x_add_widgets(codec);
1407 1406
1408 ret = snd_soc_init_card(socdev);
1409 if (ret < 0) {
1410 printk(KERN_ERR "aic3x: failed to register card\n");
1411 goto card_err;
1412 }
1413
1414 return ret; 1407 return ret;
1415 1408
1416card_err:
1417 snd_soc_free_pcms(socdev);
1418 snd_soc_dapm_free(socdev);
1419
1420pcm_err: 1409pcm_err:
1421 kfree(codec->reg_cache); 1410 kfree(codec->reg_cache);
1422 return ret; 1411 return ret;
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
new file mode 100644
index 000000000000..9c8903dbe647
--- /dev/null
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -0,0 +1,1229 @@
1/*
2 * ALSA SoC Texas Instruments TLV320DAC33 codec driver
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/pm.h>
29#include <linux/i2c.h>
30#include <linux/platform_device.h>
31#include <linux/interrupt.h>
32#include <linux/gpio.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38#include <sound/initval.h>
39#include <sound/tlv.h>
40
41#include <sound/tlv320dac33-plat.h>
42#include "tlv320dac33.h"
43
44#define DAC33_BUFFER_SIZE_BYTES 24576 /* bytes, 12288 16 bit words,
45 * 6144 stereo */
46#define DAC33_BUFFER_SIZE_SAMPLES 6144
47
48#define NSAMPLE_MAX 5700
49
50#define LATENCY_TIME_MS 20
51
52static struct snd_soc_codec *tlv320dac33_codec;
53
54enum dac33_state {
55 DAC33_IDLE = 0,
56 DAC33_PREFILL,
57 DAC33_PLAYBACK,
58 DAC33_FLUSH,
59};
60
61struct tlv320dac33_priv {
62 struct mutex mutex;
63 struct workqueue_struct *dac33_wq;
64 struct work_struct work;
65 struct snd_soc_codec codec;
66 int power_gpio;
67 int chip_power;
68 int irq;
69 unsigned int refclk;
70
71 unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */
72 unsigned int nsample_min; /* nsample should not be lower than
73 * this */
74 unsigned int nsample_max; /* nsample should not be higher than
75 * this */
76 unsigned int nsample_switch; /* Use FIFO or bypass FIFO switch */
77 unsigned int nsample; /* burst read amount from host */
78
79 enum dac33_state state;
80};
81
82static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
830x00, 0x00, 0x00, 0x00, /* 0x00 - 0x03 */
840x00, 0x00, 0x00, 0x00, /* 0x04 - 0x07 */
850x00, 0x00, 0x00, 0x00, /* 0x08 - 0x0b */
860x00, 0x00, 0x00, 0x00, /* 0x0c - 0x0f */
870x00, 0x00, 0x00, 0x00, /* 0x10 - 0x13 */
880x00, 0x00, 0x00, 0x00, /* 0x14 - 0x17 */
890x00, 0x00, 0x00, 0x00, /* 0x18 - 0x1b */
900x00, 0x00, 0x00, 0x00, /* 0x1c - 0x1f */
910x00, 0x00, 0x00, 0x00, /* 0x20 - 0x23 */
920x00, 0x00, 0x00, 0x00, /* 0x24 - 0x27 */
930x00, 0x00, 0x00, 0x00, /* 0x28 - 0x2b */
940x00, 0x00, 0x00, 0x80, /* 0x2c - 0x2f */
950x80, 0x00, 0x00, 0x00, /* 0x30 - 0x33 */
960x00, 0x00, 0x00, 0x00, /* 0x34 - 0x37 */
970x00, 0x00, /* 0x38 - 0x39 */
98/* Registers 0x3a - 0x3f are reserved */
99 0x00, 0x00, /* 0x3a - 0x3b */
1000x00, 0x00, 0x00, 0x00, /* 0x3c - 0x3f */
101
1020x00, 0x00, 0x00, 0x00, /* 0x40 - 0x43 */
1030x00, 0x80, /* 0x44 - 0x45 */
104/* Registers 0x46 - 0x47 are reserved */
105 0x80, 0x80, /* 0x46 - 0x47 */
106
1070x80, 0x00, 0x00, /* 0x48 - 0x4a */
108/* Registers 0x4b - 0x7c are reserved */
109 0x00, /* 0x4b */
1100x00, 0x00, 0x00, 0x00, /* 0x4c - 0x4f */
1110x00, 0x00, 0x00, 0x00, /* 0x50 - 0x53 */
1120x00, 0x00, 0x00, 0x00, /* 0x54 - 0x57 */
1130x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5b */
1140x00, 0x00, 0x00, 0x00, /* 0x5c - 0x5f */
1150x00, 0x00, 0x00, 0x00, /* 0x60 - 0x63 */
1160x00, 0x00, 0x00, 0x00, /* 0x64 - 0x67 */
1170x00, 0x00, 0x00, 0x00, /* 0x68 - 0x6b */
1180x00, 0x00, 0x00, 0x00, /* 0x6c - 0x6f */
1190x00, 0x00, 0x00, 0x00, /* 0x70 - 0x73 */
1200x00, 0x00, 0x00, 0x00, /* 0x74 - 0x77 */
1210x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7b */
1220x00, /* 0x7c */
123
124 0xda, 0x33, 0x03, /* 0x7d - 0x7f */
125};
126
127/* Register read and write */
128static inline unsigned int dac33_read_reg_cache(struct snd_soc_codec *codec,
129 unsigned reg)
130{
131 u8 *cache = codec->reg_cache;
132 if (reg >= DAC33_CACHEREGNUM)
133 return 0;
134
135 return cache[reg];
136}
137
138static inline void dac33_write_reg_cache(struct snd_soc_codec *codec,
139 u8 reg, u8 value)
140{
141 u8 *cache = codec->reg_cache;
142 if (reg >= DAC33_CACHEREGNUM)
143 return;
144
145 cache[reg] = value;
146}
147
148static int dac33_read(struct snd_soc_codec *codec, unsigned int reg,
149 u8 *value)
150{
151 struct tlv320dac33_priv *dac33 = codec->private_data;
152 int val;
153
154 *value = reg & 0xff;
155
156 /* If powered off, return the cached value */
157 if (dac33->chip_power) {
158 val = i2c_smbus_read_byte_data(codec->control_data, value[0]);
159 if (val < 0) {
160 dev_err(codec->dev, "Read failed (%d)\n", val);
161 value[0] = dac33_read_reg_cache(codec, reg);
162 } else {
163 value[0] = val;
164 dac33_write_reg_cache(codec, reg, val);
165 }
166 } else {
167 value[0] = dac33_read_reg_cache(codec, reg);
168 }
169
170 return 0;
171}
172
173static int dac33_write(struct snd_soc_codec *codec, unsigned int reg,
174 unsigned int value)
175{
176 struct tlv320dac33_priv *dac33 = codec->private_data;
177 u8 data[2];
178 int ret = 0;
179
180 /*
181 * data is
182 * D15..D8 dac33 register offset
183 * D7...D0 register data
184 */
185 data[0] = reg & 0xff;
186 data[1] = value & 0xff;
187
188 dac33_write_reg_cache(codec, data[0], data[1]);
189 if (dac33->chip_power) {
190 ret = codec->hw_write(codec->control_data, data, 2);
191 if (ret != 2)
192 dev_err(codec->dev, "Write failed (%d)\n", ret);
193 else
194 ret = 0;
195 }
196
197 return ret;
198}
199
200static int dac33_write_locked(struct snd_soc_codec *codec, unsigned int reg,
201 unsigned int value)
202{
203 struct tlv320dac33_priv *dac33 = codec->private_data;
204 int ret;
205
206 mutex_lock(&dac33->mutex);
207 ret = dac33_write(codec, reg, value);
208 mutex_unlock(&dac33->mutex);
209
210 return ret;
211}
212
213#define DAC33_I2C_ADDR_AUTOINC 0x80
214static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg,
215 unsigned int value)
216{
217 struct tlv320dac33_priv *dac33 = codec->private_data;
218 u8 data[3];
219 int ret = 0;
220
221 /*
222 * data is
223 * D23..D16 dac33 register offset
224 * D15..D8 register data MSB
225 * D7...D0 register data LSB
226 */
227 data[0] = reg & 0xff;
228 data[1] = (value >> 8) & 0xff;
229 data[2] = value & 0xff;
230
231 dac33_write_reg_cache(codec, data[0], data[1]);
232 dac33_write_reg_cache(codec, data[0] + 1, data[2]);
233
234 if (dac33->chip_power) {
235 /* We need to set autoincrement mode for 16 bit writes */
236 data[0] |= DAC33_I2C_ADDR_AUTOINC;
237 ret = codec->hw_write(codec->control_data, data, 3);
238 if (ret != 3)
239 dev_err(codec->dev, "Write failed (%d)\n", ret);
240 else
241 ret = 0;
242 }
243
244 return ret;
245}
246
247static void dac33_restore_regs(struct snd_soc_codec *codec)
248{
249 struct tlv320dac33_priv *dac33 = codec->private_data;
250 u8 *cache = codec->reg_cache;
251 u8 data[2];
252 int i, ret;
253
254 if (!dac33->chip_power)
255 return;
256
257 for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) {
258 data[0] = i;
259 data[1] = cache[i];
260 /* Skip the read only registers */
261 if ((i >= DAC33_INT_OSC_STATUS &&
262 i <= DAC33_INT_OSC_FREQ_RAT_READ_B) ||
263 (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) ||
264 i == DAC33_DAC_STATUS_FLAGS ||
265 i == DAC33_SRC_EST_REF_CLK_RATIO_A ||
266 i == DAC33_SRC_EST_REF_CLK_RATIO_B)
267 continue;
268 ret = codec->hw_write(codec->control_data, data, 2);
269 if (ret != 2)
270 dev_err(codec->dev, "Write failed (%d)\n", ret);
271 }
272 for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) {
273 data[0] = i;
274 data[1] = cache[i];
275 ret = codec->hw_write(codec->control_data, data, 2);
276 if (ret != 2)
277 dev_err(codec->dev, "Write failed (%d)\n", ret);
278 }
279 for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) {
280 data[0] = i;
281 data[1] = cache[i];
282 ret = codec->hw_write(codec->control_data, data, 2);
283 if (ret != 2)
284 dev_err(codec->dev, "Write failed (%d)\n", ret);
285 }
286}
287
288static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
289{
290 u8 reg;
291
292 reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
293 if (power)
294 reg |= DAC33_PDNALLB;
295 else
296 reg &= ~DAC33_PDNALLB;
297 dac33_write(codec, DAC33_PWR_CTRL, reg);
298}
299
300static void dac33_hard_power(struct snd_soc_codec *codec, int power)
301{
302 struct tlv320dac33_priv *dac33 = codec->private_data;
303
304 mutex_lock(&dac33->mutex);
305 if (power) {
306 if (dac33->power_gpio >= 0) {
307 gpio_set_value(dac33->power_gpio, 1);
308 dac33->chip_power = 1;
309 /* Restore registers */
310 dac33_restore_regs(codec);
311 }
312 dac33_soft_power(codec, 1);
313 } else {
314 dac33_soft_power(codec, 0);
315 if (dac33->power_gpio >= 0) {
316 gpio_set_value(dac33->power_gpio, 0);
317 dac33->chip_power = 0;
318 }
319 }
320 mutex_unlock(&dac33->mutex);
321
322}
323
324static int dac33_get_nsample(struct snd_kcontrol *kcontrol,
325 struct snd_ctl_elem_value *ucontrol)
326{
327 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
328 struct tlv320dac33_priv *dac33 = codec->private_data;
329
330 ucontrol->value.integer.value[0] = dac33->nsample;
331
332 return 0;
333}
334
335static int dac33_set_nsample(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_value *ucontrol)
337{
338 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
339 struct tlv320dac33_priv *dac33 = codec->private_data;
340 int ret = 0;
341
342 if (dac33->nsample == ucontrol->value.integer.value[0])
343 return 0;
344
345 if (ucontrol->value.integer.value[0] < dac33->nsample_min ||
346 ucontrol->value.integer.value[0] > dac33->nsample_max)
347 ret = -EINVAL;
348 else
349 dac33->nsample = ucontrol->value.integer.value[0];
350
351 return ret;
352}
353
354static int dac33_get_nsample_switch(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
358 struct tlv320dac33_priv *dac33 = codec->private_data;
359
360 ucontrol->value.integer.value[0] = dac33->nsample_switch;
361
362 return 0;
363}
364
365static int dac33_set_nsample_switch(struct snd_kcontrol *kcontrol,
366 struct snd_ctl_elem_value *ucontrol)
367{
368 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
369 struct tlv320dac33_priv *dac33 = codec->private_data;
370 int ret = 0;
371
372 if (dac33->nsample_switch == ucontrol->value.integer.value[0])
373 return 0;
374 /* Do not allow changes while stream is running*/
375 if (codec->active)
376 return -EPERM;
377
378 if (ucontrol->value.integer.value[0] < 0 ||
379 ucontrol->value.integer.value[0] > 1)
380 ret = -EINVAL;
381 else
382 dac33->nsample_switch = ucontrol->value.integer.value[0];
383
384 return ret;
385}
386
387/*
388 * DACL/R digital volume control:
389 * from 0 dB to -63.5 in 0.5 dB steps
390 * Need to be inverted later on:
391 * 0x00 == 0 dB
392 * 0x7f == -63.5 dB
393 */
394static DECLARE_TLV_DB_SCALE(dac_digivol_tlv, -6350, 50, 0);
395
396static const struct snd_kcontrol_new dac33_snd_controls[] = {
397 SOC_DOUBLE_R_TLV("DAC Digital Playback Volume",
398 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL,
399 0, 0x7f, 1, dac_digivol_tlv),
400 SOC_DOUBLE_R("DAC Digital Playback Switch",
401 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
402 SOC_DOUBLE_R("Line to Line Out Volume",
403 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
404};
405
406static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = {
407 SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
408 dac33_get_nsample, dac33_set_nsample),
409 SOC_SINGLE_EXT("nSample Switch", 0, 0, 1, 0,
410 dac33_get_nsample_switch, dac33_set_nsample_switch),
411};
412
413/* Analog bypass */
414static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
415 SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1);
416
417static const struct snd_kcontrol_new dac33_dapm_abypassr_control =
418 SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1);
419
420static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
421 SND_SOC_DAPM_OUTPUT("LEFT_LO"),
422 SND_SOC_DAPM_OUTPUT("RIGHT_LO"),
423
424 SND_SOC_DAPM_INPUT("LINEL"),
425 SND_SOC_DAPM_INPUT("LINER"),
426
427 SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0),
428 SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0),
429
430 /* Analog bypass */
431 SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0,
432 &dac33_dapm_abypassl_control),
433 SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0,
434 &dac33_dapm_abypassr_control),
435
436 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power",
437 DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
438 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power",
439 DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
440};
441
442static const struct snd_soc_dapm_route audio_map[] = {
443 /* Analog bypass */
444 {"Analog Left Bypass", "Switch", "LINEL"},
445 {"Analog Right Bypass", "Switch", "LINER"},
446
447 {"Output Left Amp Power", NULL, "DACL"},
448 {"Output Right Amp Power", NULL, "DACR"},
449
450 {"Output Left Amp Power", NULL, "Analog Left Bypass"},
451 {"Output Right Amp Power", NULL, "Analog Right Bypass"},
452
453 /* output */
454 {"LEFT_LO", NULL, "Output Left Amp Power"},
455 {"RIGHT_LO", NULL, "Output Right Amp Power"},
456};
457
458static int dac33_add_widgets(struct snd_soc_codec *codec)
459{
460 snd_soc_dapm_new_controls(codec, dac33_dapm_widgets,
461 ARRAY_SIZE(dac33_dapm_widgets));
462
463 /* set up audio path interconnects */
464 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
465
466 return 0;
467}
468
469static int dac33_set_bias_level(struct snd_soc_codec *codec,
470 enum snd_soc_bias_level level)
471{
472 switch (level) {
473 case SND_SOC_BIAS_ON:
474 dac33_soft_power(codec, 1);
475 break;
476 case SND_SOC_BIAS_PREPARE:
477 break;
478 case SND_SOC_BIAS_STANDBY:
479 if (codec->bias_level == SND_SOC_BIAS_OFF)
480 dac33_hard_power(codec, 1);
481 dac33_soft_power(codec, 0);
482 break;
483 case SND_SOC_BIAS_OFF:
484 dac33_hard_power(codec, 0);
485 break;
486 }
487 codec->bias_level = level;
488
489 return 0;
490}
491
492static void dac33_work(struct work_struct *work)
493{
494 struct snd_soc_codec *codec;
495 struct tlv320dac33_priv *dac33;
496 u8 reg;
497
498 dac33 = container_of(work, struct tlv320dac33_priv, work);
499 codec = &dac33->codec;
500
501 mutex_lock(&dac33->mutex);
502 switch (dac33->state) {
503 case DAC33_PREFILL:
504 dac33->state = DAC33_PLAYBACK;
505 dac33_write16(codec, DAC33_NSAMPLE_MSB,
506 DAC33_THRREG(dac33->nsample));
507 dac33_write16(codec, DAC33_PREFILL_MSB,
508 DAC33_THRREG(dac33->alarm_threshold));
509 break;
510 case DAC33_PLAYBACK:
511 dac33_write16(codec, DAC33_NSAMPLE_MSB,
512 DAC33_THRREG(dac33->nsample));
513 break;
514 case DAC33_IDLE:
515 break;
516 case DAC33_FLUSH:
517 dac33->state = DAC33_IDLE;
518 /* Mask all interrupts from dac33 */
519 dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0);
520
521 /* flush fifo */
522 reg = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A);
523 reg |= DAC33_FIFOFLUSH;
524 dac33_write(codec, DAC33_FIFO_CTRL_A, reg);
525 break;
526 }
527 mutex_unlock(&dac33->mutex);
528}
529
530static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
531{
532 struct snd_soc_codec *codec = dev;
533 struct tlv320dac33_priv *dac33 = codec->private_data;
534
535 queue_work(dac33->dac33_wq, &dac33->work);
536
537 return IRQ_HANDLED;
538}
539
540static void dac33_shutdown(struct snd_pcm_substream *substream,
541 struct snd_soc_dai *dai)
542{
543 struct snd_soc_pcm_runtime *rtd = substream->private_data;
544 struct snd_soc_device *socdev = rtd->socdev;
545 struct snd_soc_codec *codec = socdev->card->codec;
546 struct tlv320dac33_priv *dac33 = codec->private_data;
547 unsigned int pwr_ctrl;
548
549 /* Stop pending workqueue */
550 if (dac33->nsample_switch)
551 cancel_work_sync(&dac33->work);
552
553 mutex_lock(&dac33->mutex);
554 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
555 pwr_ctrl &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
556 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
557 mutex_unlock(&dac33->mutex);
558}
559
560static void dac33_oscwait(struct snd_soc_codec *codec)
561{
562 int timeout = 20;
563 u8 reg;
564
565 do {
566 msleep(1);
567 dac33_read(codec, DAC33_INT_OSC_STATUS, &reg);
568 } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--);
569 if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL)
570 dev_err(codec->dev,
571 "internal oscillator calibration failed\n");
572}
573
574static int dac33_hw_params(struct snd_pcm_substream *substream,
575 struct snd_pcm_hw_params *params,
576 struct snd_soc_dai *dai)
577{
578 struct snd_soc_pcm_runtime *rtd = substream->private_data;
579 struct snd_soc_device *socdev = rtd->socdev;
580 struct snd_soc_codec *codec = socdev->card->codec;
581
582 /* Check parameters for validity */
583 switch (params_rate(params)) {
584 case 44100:
585 case 48000:
586 break;
587 default:
588 dev_err(codec->dev, "unsupported rate %d\n",
589 params_rate(params));
590 return -EINVAL;
591 }
592
593 switch (params_format(params)) {
594 case SNDRV_PCM_FORMAT_S16_LE:
595 break;
596 default:
597 dev_err(codec->dev, "unsupported format %d\n",
598 params_format(params));
599 return -EINVAL;
600 }
601
602 return 0;
603}
604
605#define CALC_OSCSET(rate, refclk) ( \
606 ((((rate * 10000) / refclk) * 4096) + 5000) / 10000)
607#define CALC_RATIOSET(rate, refclk) ( \
608 ((((refclk * 100000) / rate) * 16384) + 50000) / 100000)
609
610/*
611 * tlv320dac33 is strict on the sequence of the register writes, if the register
612 * writes happens in different order, than dac33 might end up in unknown state.
613 * Use the known, working sequence of register writes to initialize the dac33.
614 */
615static int dac33_prepare_chip(struct snd_pcm_substream *substream)
616{
617 struct snd_soc_pcm_runtime *rtd = substream->private_data;
618 struct snd_soc_device *socdev = rtd->socdev;
619 struct snd_soc_codec *codec = socdev->card->codec;
620 struct tlv320dac33_priv *dac33 = codec->private_data;
621 unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
622 u8 aictrl_a, fifoctrl_a;
623
624 switch (substream->runtime->rate) {
625 case 44100:
626 case 48000:
627 oscset = CALC_OSCSET(substream->runtime->rate, dac33->refclk);
628 ratioset = CALC_RATIOSET(substream->runtime->rate,
629 dac33->refclk);
630 break;
631 default:
632 dev_err(codec->dev, "unsupported rate %d\n",
633 substream->runtime->rate);
634 return -EINVAL;
635 }
636
637
638 aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A);
639 aictrl_a &= ~(DAC33_NCYCL_MASK | DAC33_WLEN_MASK);
640 fifoctrl_a = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A);
641 fifoctrl_a &= ~DAC33_WIDTH;
642 switch (substream->runtime->format) {
643 case SNDRV_PCM_FORMAT_S16_LE:
644 aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16);
645 fifoctrl_a |= DAC33_WIDTH;
646 break;
647 default:
648 dev_err(codec->dev, "unsupported format %d\n",
649 substream->runtime->format);
650 return -EINVAL;
651 }
652
653 mutex_lock(&dac33->mutex);
654 dac33_soft_power(codec, 1);
655
656 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
657 dac33_write(codec, DAC33_INT_OSC_CTRL, reg_tmp);
658
659 /* Write registers 0x08 and 0x09 (MSB, LSB) */
660 dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset);
661
662 /* calib time: 128 is a nice number ;) */
663 dac33_write(codec, DAC33_CALIB_TIME, 128);
664
665 /* adjustment treshold & step */
666 dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) |
667 DAC33_ADJSTEP(1));
668
669 /* div=4 / gain=1 / div */
670 dac33_write(codec, DAC33_INT_OSC_CTRL_C, DAC33_REFDIV(4));
671
672 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
673 pwr_ctrl |= DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB;
674 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
675
676 dac33_oscwait(codec);
677
678 if (dac33->nsample_switch) {
679 /* 50-51 : ASRC Control registers */
680 dac33_write(codec, DAC33_ASRC_CTRL_A, (1 << 4)); /* div=2 */
681 dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */
682
683 /* Write registers 0x34 and 0x35 (MSB, LSB) */
684 dac33_write16(codec, DAC33_SRC_REF_CLK_RATIO_A, ratioset);
685
686 /* Set interrupts to high active */
687 dac33_write(codec, DAC33_INTP_CTRL_A, DAC33_INTPM_AHIGH);
688
689 dac33_write(codec, DAC33_FIFO_IRQ_MODE_B,
690 DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL));
691 dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT);
692 } else {
693 /* 50-51 : ASRC Control registers */
694 dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCBYP);
695 dac33_write(codec, DAC33_ASRC_CTRL_B, 0); /* ??? */
696 }
697
698 if (dac33->nsample_switch)
699 fifoctrl_a &= ~DAC33_FBYPAS;
700 else
701 fifoctrl_a |= DAC33_FBYPAS;
702 dac33_write(codec, DAC33_FIFO_CTRL_A, fifoctrl_a);
703
704 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a);
705 reg_tmp = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
706 if (dac33->nsample_switch)
707 reg_tmp &= ~DAC33_BCLKON;
708 else
709 reg_tmp |= DAC33_BCLKON;
710 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg_tmp);
711
712 if (dac33->nsample_switch) {
713 /* 20: BCLK divide ratio */
714 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 3);
715
716 dac33_write16(codec, DAC33_ATHR_MSB,
717 DAC33_THRREG(dac33->alarm_threshold));
718 } else {
719 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32);
720 }
721
722 mutex_unlock(&dac33->mutex);
723
724 return 0;
725}
726
727static void dac33_calculate_times(struct snd_pcm_substream *substream)
728{
729 struct snd_soc_pcm_runtime *rtd = substream->private_data;
730 struct snd_soc_device *socdev = rtd->socdev;
731 struct snd_soc_codec *codec = socdev->card->codec;
732 struct tlv320dac33_priv *dac33 = codec->private_data;
733 unsigned int nsample_limit;
734
735 /* Number of samples (16bit, stereo) in one period */
736 dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4;
737
738 /* Number of samples (16bit, stereo) in ALSA buffer */
739 dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4;
740 /* Subtract one period from the total */
741 dac33->nsample_max -= dac33->nsample_min;
742
743 /* Number of samples for LATENCY_TIME_MS / 2 */
744 dac33->alarm_threshold = substream->runtime->rate /
745 (1000 / (LATENCY_TIME_MS / 2));
746
747 /* Find and fix up the lowest nsmaple limit */
748 nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS);
749
750 if (dac33->nsample_min < nsample_limit)
751 dac33->nsample_min = nsample_limit;
752
753 if (dac33->nsample < dac33->nsample_min)
754 dac33->nsample = dac33->nsample_min;
755
756 /*
757 * Find and fix up the highest nsmaple limit
758 * In order to not overflow the DAC33 buffer substract the
759 * alarm_threshold value from the size of the DAC33 buffer
760 */
761 nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold;
762
763 if (dac33->nsample_max > nsample_limit)
764 dac33->nsample_max = nsample_limit;
765
766 if (dac33->nsample > dac33->nsample_max)
767 dac33->nsample = dac33->nsample_max;
768}
769
770static int dac33_pcm_prepare(struct snd_pcm_substream *substream,
771 struct snd_soc_dai *dai)
772{
773 dac33_calculate_times(substream);
774 dac33_prepare_chip(substream);
775
776 return 0;
777}
778
779static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
780 struct snd_soc_dai *dai)
781{
782 struct snd_soc_pcm_runtime *rtd = substream->private_data;
783 struct snd_soc_device *socdev = rtd->socdev;
784 struct snd_soc_codec *codec = socdev->card->codec;
785 struct tlv320dac33_priv *dac33 = codec->private_data;
786 int ret = 0;
787
788 switch (cmd) {
789 case SNDRV_PCM_TRIGGER_START:
790 case SNDRV_PCM_TRIGGER_RESUME:
791 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
792 if (dac33->nsample_switch) {
793 dac33->state = DAC33_PREFILL;
794 queue_work(dac33->dac33_wq, &dac33->work);
795 }
796 break;
797 case SNDRV_PCM_TRIGGER_STOP:
798 case SNDRV_PCM_TRIGGER_SUSPEND:
799 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
800 if (dac33->nsample_switch) {
801 dac33->state = DAC33_FLUSH;
802 queue_work(dac33->dac33_wq, &dac33->work);
803 }
804 break;
805 default:
806 ret = -EINVAL;
807 }
808
809 return ret;
810}
811
812static int dac33_set_dai_sysclk(struct snd_soc_dai *codec_dai,
813 int clk_id, unsigned int freq, int dir)
814{
815 struct snd_soc_codec *codec = codec_dai->codec;
816 struct tlv320dac33_priv *dac33 = codec->private_data;
817 u8 ioc_reg, asrcb_reg;
818
819 ioc_reg = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
820 asrcb_reg = dac33_read_reg_cache(codec, DAC33_ASRC_CTRL_B);
821 switch (clk_id) {
822 case TLV320DAC33_MCLK:
823 ioc_reg |= DAC33_REFSEL;
824 asrcb_reg |= DAC33_SRCREFSEL;
825 break;
826 case TLV320DAC33_SLEEPCLK:
827 ioc_reg &= ~DAC33_REFSEL;
828 asrcb_reg &= ~DAC33_SRCREFSEL;
829 break;
830 default:
831 dev_err(codec->dev, "Invalid clock ID (%d)\n", clk_id);
832 break;
833 }
834 dac33->refclk = freq;
835
836 dac33_write_reg_cache(codec, DAC33_INT_OSC_CTRL, ioc_reg);
837 dac33_write_reg_cache(codec, DAC33_ASRC_CTRL_B, asrcb_reg);
838
839 return 0;
840}
841
842static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
843 unsigned int fmt)
844{
845 struct snd_soc_codec *codec = codec_dai->codec;
846 u8 aictrl_a, aictrl_b;
847
848 aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A);
849 aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
850 /* set master/slave audio interface */
851 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
852 case SND_SOC_DAIFMT_CBM_CFM:
853 /* Codec Master */
854 aictrl_a |= (DAC33_MSBCLK | DAC33_MSWCLK);
855 break;
856 case SND_SOC_DAIFMT_CBS_CFS:
857 /* Codec Slave */
858 aictrl_a &= ~(DAC33_MSBCLK | DAC33_MSWCLK);
859 break;
860 default:
861 return -EINVAL;
862 }
863
864 aictrl_a &= ~DAC33_AFMT_MASK;
865 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
866 case SND_SOC_DAIFMT_I2S:
867 aictrl_a |= DAC33_AFMT_I2S;
868 break;
869 case SND_SOC_DAIFMT_DSP_A:
870 aictrl_a |= DAC33_AFMT_DSP;
871 aictrl_b &= ~DAC33_DATA_DELAY_MASK;
872 aictrl_b |= DAC33_DATA_DELAY(1); /* 1 bit delay */
873 break;
874 case SND_SOC_DAIFMT_DSP_B:
875 aictrl_a |= DAC33_AFMT_DSP;
876 aictrl_b &= ~DAC33_DATA_DELAY_MASK; /* No delay */
877 break;
878 case SND_SOC_DAIFMT_RIGHT_J:
879 aictrl_a |= DAC33_AFMT_RIGHT_J;
880 break;
881 case SND_SOC_DAIFMT_LEFT_J:
882 aictrl_a |= DAC33_AFMT_LEFT_J;
883 break;
884 default:
885 dev_err(codec->dev, "Unsupported format (%u)\n",
886 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
887 return -EINVAL;
888 }
889
890 dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a);
891 dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b);
892
893 return 0;
894}
895
896static void dac33_init_chip(struct snd_soc_codec *codec)
897{
898 /* 44-46: DAC Control Registers */
899 /* A : DAC sample rate Fsref/1.5 */
900 dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(1));
901 /* B : DAC src=normal, not muted */
902 dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
903 DAC33_DACSRCL_LEFT);
904 /* C : (defaults) */
905 dac33_write(codec, DAC33_DAC_CTRL_C, 0x00);
906
907 /* 64-65 : L&R DAC power control
908 Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/
909 dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
910 dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
911
912 /* 73 : volume soft stepping control,
913 clock source = internal osc (?) */
914 dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
915
916 /* 66 : LOP/LOM Modes */
917 dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff);
918
919 /* 68 : LOM inverted from LOP */
920 dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2));
921
922 dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
923}
924
925static int dac33_soc_probe(struct platform_device *pdev)
926{
927 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
928 struct snd_soc_codec *codec;
929 struct tlv320dac33_priv *dac33;
930 int ret = 0;
931
932 BUG_ON(!tlv320dac33_codec);
933
934 codec = tlv320dac33_codec;
935 socdev->card->codec = codec;
936 dac33 = codec->private_data;
937
938 /* Power up the codec */
939 dac33_hard_power(codec, 1);
940 /* Set default configuration */
941 dac33_init_chip(codec);
942
943 /* register pcms */
944 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
945 if (ret < 0) {
946 dev_err(codec->dev, "failed to create pcms\n");
947 goto pcm_err;
948 }
949
950 snd_soc_add_controls(codec, dac33_snd_controls,
951 ARRAY_SIZE(dac33_snd_controls));
952 /* Only add the nSample controls, if we have valid IRQ number */
953 if (dac33->irq >= 0)
954 snd_soc_add_controls(codec, dac33_nsample_snd_controls,
955 ARRAY_SIZE(dac33_nsample_snd_controls));
956
957 dac33_add_widgets(codec);
958
959 /* power on device */
960 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
961
962 return 0;
963
964pcm_err:
965 dac33_hard_power(codec, 0);
966 return ret;
967}
968
969static int dac33_soc_remove(struct platform_device *pdev)
970{
971 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
972 struct snd_soc_codec *codec = socdev->card->codec;
973
974 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
975
976 snd_soc_free_pcms(socdev);
977 snd_soc_dapm_free(socdev);
978
979 return 0;
980}
981
982static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state)
983{
984 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
985 struct snd_soc_codec *codec = socdev->card->codec;
986
987 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
988
989 return 0;
990}
991
992static int dac33_soc_resume(struct platform_device *pdev)
993{
994 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
995 struct snd_soc_codec *codec = socdev->card->codec;
996
997 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
998 dac33_set_bias_level(codec, codec->suspend_bias_level);
999
1000 return 0;
1001}
1002
1003struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = {
1004 .probe = dac33_soc_probe,
1005 .remove = dac33_soc_remove,
1006 .suspend = dac33_soc_suspend,
1007 .resume = dac33_soc_resume,
1008};
1009EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
1010
1011#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
1012 SNDRV_PCM_RATE_48000)
1013#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
1014
1015static struct snd_soc_dai_ops dac33_dai_ops = {
1016 .shutdown = dac33_shutdown,
1017 .hw_params = dac33_hw_params,
1018 .prepare = dac33_pcm_prepare,
1019 .trigger = dac33_pcm_trigger,
1020 .set_sysclk = dac33_set_dai_sysclk,
1021 .set_fmt = dac33_set_dai_fmt,
1022};
1023
1024struct snd_soc_dai dac33_dai = {
1025 .name = "tlv320dac33",
1026 .playback = {
1027 .stream_name = "Playback",
1028 .channels_min = 2,
1029 .channels_max = 2,
1030 .rates = DAC33_RATES,
1031 .formats = DAC33_FORMATS,},
1032 .ops = &dac33_dai_ops,
1033};
1034EXPORT_SYMBOL_GPL(dac33_dai);
1035
1036static int dac33_i2c_probe(struct i2c_client *client,
1037 const struct i2c_device_id *id)
1038{
1039 struct tlv320dac33_platform_data *pdata;
1040 struct tlv320dac33_priv *dac33;
1041 struct snd_soc_codec *codec;
1042 int ret = 0;
1043
1044 if (client->dev.platform_data == NULL) {
1045 dev_err(&client->dev, "Platform data not set\n");
1046 return -ENODEV;
1047 }
1048 pdata = client->dev.platform_data;
1049
1050 dac33 = kzalloc(sizeof(struct tlv320dac33_priv), GFP_KERNEL);
1051 if (dac33 == NULL)
1052 return -ENOMEM;
1053
1054 codec = &dac33->codec;
1055 codec->private_data = dac33;
1056 codec->control_data = client;
1057
1058 mutex_init(&codec->mutex);
1059 mutex_init(&dac33->mutex);
1060 INIT_LIST_HEAD(&codec->dapm_widgets);
1061 INIT_LIST_HEAD(&codec->dapm_paths);
1062
1063 codec->name = "tlv320dac33";
1064 codec->owner = THIS_MODULE;
1065 codec->read = dac33_read_reg_cache;
1066 codec->write = dac33_write_locked;
1067 codec->hw_write = (hw_write_t) i2c_master_send;
1068 codec->bias_level = SND_SOC_BIAS_OFF;
1069 codec->set_bias_level = dac33_set_bias_level;
1070 codec->dai = &dac33_dai;
1071 codec->num_dai = 1;
1072 codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
1073 codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
1074 GFP_KERNEL);
1075 if (codec->reg_cache == NULL) {
1076 ret = -ENOMEM;
1077 goto error_reg;
1078 }
1079
1080 i2c_set_clientdata(client, dac33);
1081
1082 dac33->power_gpio = pdata->power_gpio;
1083 dac33->irq = client->irq;
1084 dac33->nsample = NSAMPLE_MAX;
1085 /* Disable FIFO use by default */
1086 dac33->nsample_switch = 0;
1087
1088 tlv320dac33_codec = codec;
1089
1090 codec->dev = &client->dev;
1091 dac33_dai.dev = codec->dev;
1092
1093 /* Check if the reset GPIO number is valid and request it */
1094 if (dac33->power_gpio >= 0) {
1095 ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
1096 if (ret < 0) {
1097 dev_err(codec->dev,
1098 "Failed to request reset GPIO (%d)\n",
1099 dac33->power_gpio);
1100 snd_soc_unregister_dai(&dac33_dai);
1101 snd_soc_unregister_codec(codec);
1102 goto error_gpio;
1103 }
1104 gpio_direction_output(dac33->power_gpio, 0);
1105 } else {
1106 dac33->chip_power = 1;
1107 }
1108
1109 /* Check if the IRQ number is valid and request it */
1110 if (dac33->irq >= 0) {
1111 ret = request_irq(dac33->irq, dac33_interrupt_handler,
1112 IRQF_TRIGGER_RISING | IRQF_DISABLED,
1113 codec->name, codec);
1114 if (ret < 0) {
1115 dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
1116 dac33->irq, ret);
1117 dac33->irq = -1;
1118 }
1119 if (dac33->irq != -1) {
1120 /* Setup work queue */
1121 dac33->dac33_wq =
1122 create_singlethread_workqueue("tlv320dac33");
1123 if (dac33->dac33_wq == NULL) {
1124 free_irq(dac33->irq, &dac33->codec);
1125 ret = -ENOMEM;
1126 goto error_wq;
1127 }
1128
1129 INIT_WORK(&dac33->work, dac33_work);
1130 }
1131 }
1132
1133 ret = snd_soc_register_codec(codec);
1134 if (ret != 0) {
1135 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1136 goto error_codec;
1137 }
1138
1139 ret = snd_soc_register_dai(&dac33_dai);
1140 if (ret != 0) {
1141 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1142 snd_soc_unregister_codec(codec);
1143 goto error_codec;
1144 }
1145
1146 /* Shut down the codec for now */
1147 dac33_hard_power(codec, 0);
1148
1149 return ret;
1150
1151error_codec:
1152 if (dac33->irq >= 0) {
1153 free_irq(dac33->irq, &dac33->codec);
1154 destroy_workqueue(dac33->dac33_wq);
1155 }
1156error_wq:
1157 if (dac33->power_gpio >= 0)
1158 gpio_free(dac33->power_gpio);
1159error_gpio:
1160 kfree(codec->reg_cache);
1161error_reg:
1162 tlv320dac33_codec = NULL;
1163 kfree(dac33);
1164
1165 return ret;
1166}
1167
1168static int dac33_i2c_remove(struct i2c_client *client)
1169{
1170 struct tlv320dac33_priv *dac33;
1171
1172 dac33 = i2c_get_clientdata(client);
1173 dac33_hard_power(&dac33->codec, 0);
1174
1175 if (dac33->power_gpio >= 0)
1176 gpio_free(dac33->power_gpio);
1177 if (dac33->irq >= 0)
1178 free_irq(dac33->irq, &dac33->codec);
1179
1180 destroy_workqueue(dac33->dac33_wq);
1181 snd_soc_unregister_dai(&dac33_dai);
1182 snd_soc_unregister_codec(&dac33->codec);
1183 kfree(dac33->codec.reg_cache);
1184 kfree(dac33);
1185 tlv320dac33_codec = NULL;
1186
1187 return 0;
1188}
1189
1190static const struct i2c_device_id tlv320dac33_i2c_id[] = {
1191 {
1192 .name = "tlv320dac33",
1193 .driver_data = 0,
1194 },
1195 { },
1196};
1197
1198static struct i2c_driver tlv320dac33_i2c_driver = {
1199 .driver = {
1200 .name = "tlv320dac33",
1201 .owner = THIS_MODULE,
1202 },
1203 .probe = dac33_i2c_probe,
1204 .remove = __devexit_p(dac33_i2c_remove),
1205 .id_table = tlv320dac33_i2c_id,
1206};
1207
1208static int __init dac33_module_init(void)
1209{
1210 int r;
1211 r = i2c_add_driver(&tlv320dac33_i2c_driver);
1212 if (r < 0) {
1213 printk(KERN_ERR "DAC33: driver registration failed\n");
1214 return r;
1215 }
1216 return 0;
1217}
1218module_init(dac33_module_init);
1219
1220static void __exit dac33_module_exit(void)
1221{
1222 i2c_del_driver(&tlv320dac33_i2c_driver);
1223}
1224module_exit(dac33_module_exit);
1225
1226
1227MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver");
1228MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>");
1229MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h
new file mode 100644
index 000000000000..eb8ae07f0bd2
--- /dev/null
+++ b/sound/soc/codecs/tlv320dac33.h
@@ -0,0 +1,267 @@
1/*
2 * ALSA SoC Texas Instruments TLV320DAC33 codec driver
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __TLV320DAC33_H
25#define __TLV320DAC33_H
26
27#define DAC33_PAGE_SELECT 0x00
28#define DAC33_PWR_CTRL 0x01
29#define DAC33_PLL_CTRL_A 0x02
30#define DAC33_PLL_CTRL_B 0x03
31#define DAC33_PLL_CTRL_C 0x04
32#define DAC33_PLL_CTRL_D 0x05
33#define DAC33_PLL_CTRL_E 0x06
34#define DAC33_INT_OSC_CTRL 0x07
35#define DAC33_INT_OSC_FREQ_RAT_A 0x08
36#define DAC33_INT_OSC_FREQ_RAT_B 0x09
37#define DAC33_INT_OSC_DAC_RATIO_SET 0x0A
38#define DAC33_CALIB_TIME 0x0B
39#define DAC33_INT_OSC_CTRL_B 0x0C
40#define DAC33_INT_OSC_CTRL_C 0x0D
41#define DAC33_INT_OSC_STATUS 0x0E
42#define DAC33_INT_OSC_DAC_RATIO_READ 0x0F
43#define DAC33_INT_OSC_FREQ_RAT_READ_A 0x10
44#define DAC33_INT_OSC_FREQ_RAT_READ_B 0x11
45#define DAC33_SER_AUDIOIF_CTRL_A 0x12
46#define DAC33_SER_AUDIOIF_CTRL_B 0x13
47#define DAC33_SER_AUDIOIF_CTRL_C 0x14
48#define DAC33_FIFO_CTRL_A 0x15
49#define DAC33_UTHR_MSB 0x16
50#define DAC33_UTHR_LSB 0x17
51#define DAC33_ATHR_MSB 0x18
52#define DAC33_ATHR_LSB 0x19
53#define DAC33_LTHR_MSB 0x1A
54#define DAC33_LTHR_LSB 0x1B
55#define DAC33_PREFILL_MSB 0x1C
56#define DAC33_PREFILL_LSB 0x1D
57#define DAC33_NSAMPLE_MSB 0x1E
58#define DAC33_NSAMPLE_LSB 0x1F
59#define DAC33_FIFO_WPTR_MSB 0x20
60#define DAC33_FIFO_WPTR_LSB 0x21
61#define DAC33_FIFO_RPTR_MSB 0x22
62#define DAC33_FIFO_RPTR_LSB 0x23
63#define DAC33_FIFO_DEPTH_MSB 0x24
64#define DAC33_FIFO_DEPTH_LSB 0x25
65#define DAC33_SAMPLES_REMAINING_MSB 0x26
66#define DAC33_SAMPLES_REMAINING_LSB 0x27
67#define DAC33_FIFO_IRQ_FLAG 0x28
68#define DAC33_FIFO_IRQ_MASK 0x29
69#define DAC33_FIFO_IRQ_MODE_A 0x2A
70#define DAC33_FIFO_IRQ_MODE_B 0x2B
71#define DAC33_DAC_CTRL_A 0x2C
72#define DAC33_DAC_CTRL_B 0x2D
73#define DAC33_DAC_CTRL_C 0x2E
74#define DAC33_LDAC_DIG_VOL_CTRL 0x2F
75#define DAC33_RDAC_DIG_VOL_CTRL 0x30
76#define DAC33_DAC_STATUS_FLAGS 0x31
77#define DAC33_ASRC_CTRL_A 0x32
78#define DAC33_ASRC_CTRL_B 0x33
79#define DAC33_SRC_REF_CLK_RATIO_A 0x34
80#define DAC33_SRC_REF_CLK_RATIO_B 0x35
81#define DAC33_SRC_EST_REF_CLK_RATIO_A 0x36
82#define DAC33_SRC_EST_REF_CLK_RATIO_B 0x37
83#define DAC33_INTP_CTRL_A 0x38
84#define DAC33_INTP_CTRL_B 0x39
85/* Registers 0x3A - 0x3F Reserved */
86#define DAC33_LDAC_PWR_CTRL 0x40
87#define DAC33_RDAC_PWR_CTRL 0x41
88#define DAC33_OUT_AMP_CM_CTRL 0x42
89#define DAC33_OUT_AMP_PWR_CTRL 0x43
90#define DAC33_OUT_AMP_CTRL 0x44
91#define DAC33_LINEL_TO_LLO_VOL 0x45
92/* Registers 0x45 - 0x47 Reserved */
93#define DAC33_LINER_TO_RLO_VOL 0x48
94#define DAC33_ANA_VOL_SOFT_STEP_CTRL 0x49
95#define DAC33_OSC_TRIM 0x4A
96/* Registers 0x4B - 0x7C Reserved */
97#define DAC33_DEVICE_ID_MSB 0x7D
98#define DAC33_DEVICE_ID_LSB 0x7E
99#define DAC33_DEVICE_REV_ID 0x7F
100
101#define DAC33_CACHEREGNUM 128
102
103/* Bit definitions */
104
105/* DAC33_PWR_CTRL (0x01) */
106#define DAC33_DACRPDNB (0x01 << 0)
107#define DAC33_DACLPDNB (0x01 << 1)
108#define DAC33_OSCPDNB (0x01 << 2)
109#define DAC33_PLLPDNB (0x01 << 3)
110#define DAC33_PDNALLB (0x01 << 4)
111#define DAC33_SOFT_RESET (0x01 << 7)
112
113/* DAC33_INT_OSC_CTRL (0x07) */
114#define DAC33_REFSEL (0x01 << 1)
115
116/* DAC33_INT_OSC_CTRL_B (0x0C) */
117#define DAC33_ADJSTEP(x) (x << 0)
118#define DAC33_ADJTHRSHLD(x) (x << 4)
119
120/* DAC33_INT_OSC_CTRL_C (0x0D) */
121#define DAC33_REFDIV(x) (x << 4)
122
123/* DAC33_INT_OSC_STATUS (0x0E) */
124#define DAC33_OSCSTATUS_IDLE_CALIB (0x00)
125#define DAC33_OSCSTATUS_NORMAL (0x01)
126#define DAC33_OSCSTATUS_ADJUSTMENT (0x03)
127#define DAC33_OSCSTATUS_NOT_USED (0x02)
128
129/* DAC33_SER_AUDIOIF_CTRL_A (0x12) */
130#define DAC33_MSWCLK (0x01 << 0)
131#define DAC33_MSBCLK (0x01 << 1)
132#define DAC33_AFMT_MASK (0x03 << 2)
133#define DAC33_AFMT_I2S (0x00 << 2)
134#define DAC33_AFMT_DSP (0x01 << 2)
135#define DAC33_AFMT_RIGHT_J (0x02 << 2)
136#define DAC33_AFMT_LEFT_J (0x03 << 2)
137#define DAC33_WLEN_MASK (0x03 << 4)
138#define DAC33_WLEN_16 (0x00 << 4)
139#define DAC33_WLEN_20 (0x01 << 4)
140#define DAC33_WLEN_24 (0x02 << 4)
141#define DAC33_WLEN_32 (0x03 << 4)
142#define DAC33_NCYCL_MASK (0x03 << 6)
143#define DAC33_NCYCL_16 (0x00 << 6)
144#define DAC33_NCYCL_20 (0x01 << 6)
145#define DAC33_NCYCL_24 (0x02 << 6)
146#define DAC33_NCYCL_32 (0x03 << 6)
147
148/* DAC33_SER_AUDIOIF_CTRL_B (0x13) */
149#define DAC33_DATA_DELAY_MASK (0x03 << 2)
150#define DAC33_DATA_DELAY(x) (x << 2)
151#define DAC33_BCLKON (0x01 << 5)
152
153/* DAC33_FIFO_CTRL_A (0x15) */
154#define DAC33_WIDTH (0x01 << 0)
155#define DAC33_FBYPAS (0x01 << 1)
156#define DAC33_FAUTO (0x01 << 2)
157#define DAC33_FIFOFLUSH (0x01 << 3)
158
159/*
160 * UTHR, ATHR, LTHR, PREFILL, NSAMPLE (0x16 - 0x1F)
161 * 13-bit values
162*/
163#define DAC33_THRREG(x) (((x) & 0x1FFF) << 3)
164
165/* DAC33_FIFO_IRQ_MASK (0x29) */
166#define DAC33_MNS (0x01 << 0)
167#define DAC33_MPS (0x01 << 1)
168#define DAC33_MAT (0x01 << 2)
169#define DAC33_MLT (0x01 << 3)
170#define DAC33_MUT (0x01 << 4)
171#define DAC33_MUF (0x01 << 5)
172#define DAC33_MOF (0x01 << 6)
173
174#define DAC33_FIFO_IRQ_MODE_MASK (0x03)
175#define DAC33_FIFO_IRQ_MODE_RISING (0x00)
176#define DAC33_FIFO_IRQ_MODE_FALLING (0x01)
177#define DAC33_FIFO_IRQ_MODE_LEVEL (0x02)
178#define DAC33_FIFO_IRQ_MODE_EDGE (0x03)
179
180/* DAC33_FIFO_IRQ_MODE_A (0x2A) */
181#define DAC33_UTM(x) (x << 0)
182#define DAC33_UFM(x) (x << 2)
183#define DAC33_OFM(x) (x << 4)
184
185/* DAC33_FIFO_IRQ_MODE_B (0x2B) */
186#define DAC33_NSM(x) (x << 0)
187#define DAC33_PSM(x) (x << 2)
188#define DAC33_ATM(x) (x << 4)
189#define DAC33_LTM(x) (x << 6)
190
191/* DAC33_DAC_CTRL_A (0x2C) */
192#define DAC33_DACRATE(x) (x << 0)
193#define DAC33_DACDUAL (0x01 << 4)
194#define DAC33_DACLKSEL_MASK (0x03 << 5)
195#define DAC33_DACLKSEL_INTSOC (0x00 << 5)
196#define DAC33_DACLKSEL_PLL (0x01 << 5)
197#define DAC33_DACLKSEL_MCLK (0x02 << 5)
198#define DAC33_DACLKSEL_BCLK (0x03 << 5)
199
200/* DAC33_DAC_CTRL_B (0x2D) */
201#define DAC33_DACSRCR_MASK (0x03 << 0)
202#define DAC33_DACSRCR_MUTE (0x00 << 0)
203#define DAC33_DACSRCR_RIGHT (0x01 << 0)
204#define DAC33_DACSRCR_LEFT (0x02 << 0)
205#define DAC33_DACSRCR_MONOMIX (0x03 << 0)
206#define DAC33_DACSRCL_MASK (0x03 << 2)
207#define DAC33_DACSRCL_MUTE (0x00 << 2)
208#define DAC33_DACSRCL_LEFT (0x01 << 2)
209#define DAC33_DACSRCL_RIGHT (0x02 << 2)
210#define DAC33_DACSRCL_MONOMIX (0x03 << 2)
211#define DAC33_DVOLSTEP_MASK (0x03 << 4)
212#define DAC33_DVOLSTEP_SS_PERFS (0x00 << 4)
213#define DAC33_DVOLSTEP_SS_PER2FS (0x01 << 4)
214#define DAC33_DVOLSTEP_SS_DISABLED (0x02 << 4)
215#define DAC33_DVOLCTRL_MASK (0x03 << 6)
216#define DAC33_DVOLCTRL_LR_INDEPENDENT1 (0x00 << 6)
217#define DAC33_DVOLCTRL_LR_RIGHT_CONTROL (0x01 << 6)
218#define DAC33_DVOLCTRL_LR_LEFT_CONTROL (0x02 << 6)
219#define DAC33_DVOLCTRL_LR_INDEPENDENT2 (0x03 << 6)
220
221/* DAC33_DAC_CTRL_C (0x2E) */
222#define DAC33_DEEMENR (0x01 << 0)
223#define DAC33_EFFENR (0x01 << 1)
224#define DAC33_DEEMENL (0x01 << 2)
225#define DAC33_EFFENL (0x01 << 3)
226#define DAC33_EN3D (0x01 << 4)
227#define DAC33_RESYNMUTE (0x01 << 5)
228#define DAC33_RESYNEN (0x01 << 6)
229
230/* DAC33_ASRC_CTRL_A (0x32) */
231#define DAC33_SRCBYP (0x01 << 0)
232#define DAC33_SRCLKSEL_MASK (0x03 << 1)
233#define DAC33_SRCLKSEL_INTSOC (0x00 << 1)
234#define DAC33_SRCLKSEL_PLL (0x01 << 1)
235#define DAC33_SRCLKSEL_MCLK (0x02 << 1)
236#define DAC33_SRCLKSEL_BCLK (0x03 << 1)
237#define DAC33_SRCLKDIV(x) (x << 3)
238
239/* DAC33_ASRC_CTRL_B (0x33) */
240#define DAC33_SRCSETUP(x) (x << 0)
241#define DAC33_SRCREFSEL (0x01 << 4)
242#define DAC33_SRCREFDIV(x) (x << 5)
243
244/* DAC33_INTP_CTRL_A (0x38) */
245#define DAC33_INTPSEL (0x01 << 0)
246#define DAC33_INTPM_MASK (0x03 << 1)
247#define DAC33_INTPM_ALOW_OPENDRAIN (0x00 << 1)
248#define DAC33_INTPM_ALOW (0x01 << 1)
249#define DAC33_INTPM_AHIGH (0x02 << 1)
250
251/* DAC33_LDAC_PWR_CTRL (0x40) */
252/* DAC33_RDAC_PWR_CTRL (0x41) */
253#define DAC33_DACLRNUM (0x01 << 2)
254#define DAC33_LROUT_GAIN(x) (x << 0)
255
256/* DAC33_ANA_VOL_SOFT_STEP_CTRL (0x49) */
257#define DAC33_VOLCLKSEL (0x01 << 0)
258#define DAC33_VOLCLKEN (0x01 << 1)
259#define DAC33_VOLBYPASS (0x01 << 2)
260
261#define TLV320DAC33_MCLK 0
262#define TLV320DAC33_SLEEPCLK 1
263
264extern struct snd_soc_dai dac33_dai;
265extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33;
266
267#endif /* __TLV320DAC33_H */
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
new file mode 100644
index 000000000000..6b650c1aa3d1
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -0,0 +1,463 @@
1/*
2 * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
3 *
4 * Copyright (C) Nokia Corporation
5 *
6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/device.h>
26#include <linux/i2c.h>
27#include <linux/gpio.h>
28#include <sound/tpa6130a2-plat.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31#include <sound/tlv.h>
32
33#include "tpa6130a2.h"
34
35static struct i2c_client *tpa6130a2_client;
36
37/* This struct is used to save the context */
38struct tpa6130a2_data {
39 struct mutex mutex;
40 unsigned char regs[TPA6130A2_CACHEREGNUM];
41 int power_gpio;
42 unsigned char power_state;
43};
44
45static int tpa6130a2_i2c_read(int reg)
46{
47 struct tpa6130a2_data *data;
48 int val;
49
50 BUG_ON(tpa6130a2_client == NULL);
51 data = i2c_get_clientdata(tpa6130a2_client);
52
53 /* If powered off, return the cached value */
54 if (data->power_state) {
55 val = i2c_smbus_read_byte_data(tpa6130a2_client, reg);
56 if (val < 0)
57 dev_err(&tpa6130a2_client->dev, "Read failed\n");
58 else
59 data->regs[reg] = val;
60 } else {
61 val = data->regs[reg];
62 }
63
64 return val;
65}
66
67static int tpa6130a2_i2c_write(int reg, u8 value)
68{
69 struct tpa6130a2_data *data;
70 int val = 0;
71
72 BUG_ON(tpa6130a2_client == NULL);
73 data = i2c_get_clientdata(tpa6130a2_client);
74
75 if (data->power_state) {
76 val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
77 if (val < 0)
78 dev_err(&tpa6130a2_client->dev, "Write failed\n");
79 }
80
81 /* Either powered on or off, we save the context */
82 data->regs[reg] = value;
83
84 return val;
85}
86
87static u8 tpa6130a2_read(int reg)
88{
89 struct tpa6130a2_data *data;
90
91 BUG_ON(tpa6130a2_client == NULL);
92 data = i2c_get_clientdata(tpa6130a2_client);
93
94 return data->regs[reg];
95}
96
97static void tpa6130a2_initialize(void)
98{
99 struct tpa6130a2_data *data;
100 int i;
101
102 BUG_ON(tpa6130a2_client == NULL);
103 data = i2c_get_clientdata(tpa6130a2_client);
104
105 for (i = 1; i < TPA6130A2_REG_VERSION; i++)
106 tpa6130a2_i2c_write(i, data->regs[i]);
107}
108
109static void tpa6130a2_power(int power)
110{
111 struct tpa6130a2_data *data;
112 u8 val;
113
114 BUG_ON(tpa6130a2_client == NULL);
115 data = i2c_get_clientdata(tpa6130a2_client);
116
117 mutex_lock(&data->mutex);
118 if (power) {
119 /* Power on */
120 if (data->power_gpio >= 0) {
121 gpio_set_value(data->power_gpio, 1);
122 data->power_state = 1;
123 tpa6130a2_initialize();
124 }
125 /* Clear SWS */
126 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
127 val &= ~TPA6130A2_SWS;
128 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
129 } else {
130 /* set SWS */
131 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
132 val |= TPA6130A2_SWS;
133 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
134 /* Power off */
135 if (data->power_gpio >= 0) {
136 gpio_set_value(data->power_gpio, 0);
137 data->power_state = 0;
138 }
139 }
140 mutex_unlock(&data->mutex);
141}
142
143static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
144 struct snd_ctl_elem_value *ucontrol)
145{
146 struct soc_mixer_control *mc =
147 (struct soc_mixer_control *)kcontrol->private_value;
148 struct tpa6130a2_data *data;
149 unsigned int reg = mc->reg;
150 unsigned int shift = mc->shift;
151 unsigned int mask = mc->max;
152 unsigned int invert = mc->invert;
153
154 BUG_ON(tpa6130a2_client == NULL);
155 data = i2c_get_clientdata(tpa6130a2_client);
156
157 mutex_lock(&data->mutex);
158
159 ucontrol->value.integer.value[0] =
160 (tpa6130a2_read(reg) >> shift) & mask;
161
162 if (invert)
163 ucontrol->value.integer.value[0] =
164 mask - ucontrol->value.integer.value[0];
165
166 mutex_unlock(&data->mutex);
167 return 0;
168}
169
170static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
172{
173 struct soc_mixer_control *mc =
174 (struct soc_mixer_control *)kcontrol->private_value;
175 struct tpa6130a2_data *data;
176 unsigned int reg = mc->reg;
177 unsigned int shift = mc->shift;
178 unsigned int mask = mc->max;
179 unsigned int invert = mc->invert;
180 unsigned int val = (ucontrol->value.integer.value[0] & mask);
181 unsigned int val_reg;
182
183 BUG_ON(tpa6130a2_client == NULL);
184 data = i2c_get_clientdata(tpa6130a2_client);
185
186 if (invert)
187 val = mask - val;
188
189 mutex_lock(&data->mutex);
190
191 val_reg = tpa6130a2_read(reg);
192 if (((val_reg >> shift) & mask) == val) {
193 mutex_unlock(&data->mutex);
194 return 0;
195 }
196
197 val_reg &= ~(mask << shift);
198 val_reg |= val << shift;
199 tpa6130a2_i2c_write(reg, val_reg);
200
201 mutex_unlock(&data->mutex);
202
203 return 1;
204}
205
206/*
207 * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
208 * down in gain.
209 */
210static const unsigned int tpa6130_tlv[] = {
211 TLV_DB_RANGE_HEAD(10),
212 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
213 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
214 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
215 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
216 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
217 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
218 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
219 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
220 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
221 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0),
222};
223
224static const struct snd_kcontrol_new tpa6130a2_controls[] = {
225 SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
226 TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
227 tpa6130a2_get_reg, tpa6130a2_set_reg,
228 tpa6130_tlv),
229};
230
231/*
232 * Enable or disable channel (left or right)
233 * The bit number for mute and amplifier are the same per channel:
234 * bit 6: Right channel
235 * bit 7: Left channel
236 * in both registers.
237 */
238static void tpa6130a2_channel_enable(u8 channel, int enable)
239{
240 struct tpa6130a2_data *data;
241 u8 val;
242
243 BUG_ON(tpa6130a2_client == NULL);
244 data = i2c_get_clientdata(tpa6130a2_client);
245
246 if (enable) {
247 /* Enable channel */
248 /* Enable amplifier */
249 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
250 val |= channel;
251 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
252
253 /* Unmute channel */
254 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
255 val &= ~channel;
256 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
257 } else {
258 /* Disable channel */
259 /* Mute channel */
260 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
261 val |= channel;
262 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
263
264 /* Disable amplifier */
265 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
266 val &= ~channel;
267 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
268 }
269}
270
271static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w,
272 struct snd_kcontrol *kcontrol, int event)
273{
274 switch (event) {
275 case SND_SOC_DAPM_POST_PMU:
276 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1);
277 break;
278 case SND_SOC_DAPM_POST_PMD:
279 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0);
280 break;
281 }
282 return 0;
283}
284
285static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
286 struct snd_kcontrol *kcontrol, int event)
287{
288 switch (event) {
289 case SND_SOC_DAPM_POST_PMU:
290 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1);
291 break;
292 case SND_SOC_DAPM_POST_PMD:
293 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0);
294 break;
295 }
296 return 0;
297}
298
299static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event)
301{
302 switch (event) {
303 case SND_SOC_DAPM_POST_PMU:
304 tpa6130a2_power(1);
305 break;
306 case SND_SOC_DAPM_POST_PMD:
307 tpa6130a2_power(0);
308 break;
309 }
310 return 0;
311}
312
313static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
314 SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM,
315 0, 0, NULL, 0, tpa6130a2_left_event,
316 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
317 SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM,
318 0, 0, NULL, 0, tpa6130a2_right_event,
319 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
320 SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM,
321 0, 0, tpa6130a2_supply_event,
322 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
323 /* Outputs */
324 SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL),
325 SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL),
326};
327
328static const struct snd_soc_dapm_route audio_map[] = {
329 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"},
330 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"},
331
332 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"},
333 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"},
334};
335
336int tpa6130a2_add_controls(struct snd_soc_codec *codec)
337{
338 snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
339 ARRAY_SIZE(tpa6130a2_dapm_widgets));
340
341 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
342
343 return snd_soc_add_controls(codec, tpa6130a2_controls,
344 ARRAY_SIZE(tpa6130a2_controls));
345
346}
347EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
348
349static int tpa6130a2_probe(struct i2c_client *client,
350 const struct i2c_device_id *id)
351{
352 struct device *dev;
353 struct tpa6130a2_data *data;
354 struct tpa6130a2_platform_data *pdata;
355 int ret;
356
357 dev = &client->dev;
358
359 if (client->dev.platform_data == NULL) {
360 dev_err(dev, "Platform data not set\n");
361 dump_stack();
362 return -ENODEV;
363 }
364
365 data = kzalloc(sizeof(*data), GFP_KERNEL);
366 if (data == NULL) {
367 dev_err(dev, "Can not allocate memory\n");
368 return -ENOMEM;
369 }
370
371 tpa6130a2_client = client;
372
373 i2c_set_clientdata(tpa6130a2_client, data);
374
375 pdata = client->dev.platform_data;
376 data->power_gpio = pdata->power_gpio;
377
378 mutex_init(&data->mutex);
379
380 /* Set default register values */
381 data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS;
382 data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R |
383 TPA6130A2_MUTE_L;
384
385 if (data->power_gpio >= 0) {
386 ret = gpio_request(data->power_gpio, "tpa6130a2 enable");
387 if (ret < 0) {
388 dev_err(dev, "Failed to request power GPIO (%d)\n",
389 data->power_gpio);
390 goto fail;
391 }
392 gpio_direction_output(data->power_gpio, 0);
393 } else {
394 data->power_state = 1;
395 tpa6130a2_initialize();
396 }
397
398 tpa6130a2_power(1);
399
400 /* Read version */
401 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
402 TPA6130A2_VERSION_MASK;
403 if ((ret != 1) && (ret != 2))
404 dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
405
406 /* Disable the chip */
407 tpa6130a2_power(0);
408
409 return 0;
410fail:
411 kfree(data);
412 i2c_set_clientdata(tpa6130a2_client, NULL);
413 tpa6130a2_client = NULL;
414
415 return ret;
416}
417
418static int tpa6130a2_remove(struct i2c_client *client)
419{
420 struct tpa6130a2_data *data = i2c_get_clientdata(client);
421
422 tpa6130a2_power(0);
423
424 if (data->power_gpio >= 0)
425 gpio_free(data->power_gpio);
426 kfree(data);
427 tpa6130a2_client = NULL;
428
429 return 0;
430}
431
432static const struct i2c_device_id tpa6130a2_id[] = {
433 { "tpa6130a2", 0 },
434 { }
435};
436MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
437
438static struct i2c_driver tpa6130a2_i2c_driver = {
439 .driver = {
440 .name = "tpa6130a2",
441 .owner = THIS_MODULE,
442 },
443 .probe = tpa6130a2_probe,
444 .remove = __devexit_p(tpa6130a2_remove),
445 .id_table = tpa6130a2_id,
446};
447
448static int __init tpa6130a2_init(void)
449{
450 return i2c_add_driver(&tpa6130a2_i2c_driver);
451}
452
453static void __exit tpa6130a2_exit(void)
454{
455 i2c_del_driver(&tpa6130a2_i2c_driver);
456}
457
458MODULE_AUTHOR("Peter Ujfalusi");
459MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
460MODULE_LICENSE("GPL");
461
462module_init(tpa6130a2_init);
463module_exit(tpa6130a2_exit);
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h
new file mode 100644
index 000000000000..57e867fd86d1
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.h
@@ -0,0 +1,61 @@
1/*
2 * ALSA SoC TPA6130A2 amplifier driver
3 *
4 * Copyright (C) Nokia Corporation
5 *
6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __TPA6130A2_H__
25#define __TPA6130A2_H__
26
27/* Register addresses */
28#define TPA6130A2_REG_CONTROL 0x01
29#define TPA6130A2_REG_VOL_MUTE 0x02
30#define TPA6130A2_REG_OUT_IMPEDANCE 0x03
31#define TPA6130A2_REG_VERSION 0x04
32
33#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1)
34
35/* Register bits */
36/* TPA6130A2_REG_CONTROL (0x01) */
37#define TPA6130A2_SWS (0x01 << 0)
38#define TPA6130A2_TERMAL (0x01 << 1)
39#define TPA6130A2_MODE(x) (x << 4)
40#define TPA6130A2_MODE_STEREO (0x00)
41#define TPA6130A2_MODE_DUAL_MONO (0x01)
42#define TPA6130A2_MODE_BRIDGE (0x02)
43#define TPA6130A2_MODE_MASK (0x03)
44#define TPA6130A2_HP_EN_R (0x01 << 6)
45#define TPA6130A2_HP_EN_L (0x01 << 7)
46
47/* TPA6130A2_REG_VOL_MUTE (0x02) */
48#define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0)
49#define TPA6130A2_MUTE_R (0x01 << 6)
50#define TPA6130A2_MUTE_L (0x01 << 7)
51
52/* TPA6130A2_REG_OUT_IMPEDANCE (0x03) */
53#define TPA6130A2_HIZ_R (0x01 << 0)
54#define TPA6130A2_HIZ_L (0x01 << 1)
55
56/* TPA6130A2_REG_VERSION (0x04) */
57#define TPA6130A2_VERSION_MASK (0x0f)
58
59extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
60
61#endif /* __TPA6130A2_H__ */
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 4df7c6c61c76..5f1681f6ca76 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -120,9 +120,10 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
120 120
121/* codec private data */ 121/* codec private data */
122struct twl4030_priv { 122struct twl4030_priv {
123 unsigned int bypass_state; 123 struct snd_soc_codec codec;
124
124 unsigned int codec_powered; 125 unsigned int codec_powered;
125 unsigned int codec_muted; 126 unsigned int apll_enabled;
126 127
127 struct snd_pcm_substream *master_substream; 128 struct snd_pcm_substream *master_substream;
128 struct snd_pcm_substream *slave_substream; 129 struct snd_pcm_substream *slave_substream;
@@ -183,19 +184,20 @@ static int twl4030_write(struct snd_soc_codec *codec,
183static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 184static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
184{ 185{
185 struct twl4030_priv *twl4030 = codec->private_data; 186 struct twl4030_priv *twl4030 = codec->private_data;
186 u8 mode; 187 int mode;
187 188
188 if (enable == twl4030->codec_powered) 189 if (enable == twl4030->codec_powered)
189 return; 190 return;
190 191
191 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
192 if (enable) 192 if (enable)
193 mode |= TWL4030_CODECPDZ; 193 mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
194 else 194 else
195 mode &= ~TWL4030_CODECPDZ; 195 mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
196 196
197 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); 197 if (mode >= 0) {
198 twl4030->codec_powered = enable; 198 twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode);
199 twl4030->codec_powered = enable;
200 }
199 201
200 /* REVISIT: this delay is present in TI sample drivers */ 202 /* REVISIT: this delay is present in TI sample drivers */
201 /* but there seems to be no TRM requirement for it */ 203 /* but there seems to be no TRM requirement for it */
@@ -212,31 +214,30 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
212 214
213 /* set all audio section registers to reasonable defaults */ 215 /* set all audio section registers to reasonable defaults */
214 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) 216 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
215 twl4030_write(codec, i, cache[i]); 217 if (i != TWL4030_REG_APLL_CTL)
218 twl4030_write(codec, i, cache[i]);
216 219
217} 220}
218 221
219static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) 222static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
220{ 223{
221 struct twl4030_priv *twl4030 = codec->private_data; 224 struct twl4030_priv *twl4030 = codec->private_data;
222 u8 reg_val; 225 int status;
223 226
224 if (mute == twl4030->codec_muted) 227 if (enable == twl4030->apll_enabled)
225 return; 228 return;
226 229
227 if (mute) { 230 if (enable)
228 /* Disable PLL */
229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
230 reg_val &= ~TWL4030_APLL_EN;
231 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
232 } else {
233 /* Enable PLL */ 231 /* Enable PLL */
234 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 232 status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
235 reg_val |= TWL4030_APLL_EN; 233 else
236 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); 234 /* Disable PLL */
237 } 235 status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
236
237 if (status >= 0)
238 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status);
238 239
239 twl4030->codec_muted = mute; 240 twl4030->apll_enabled = enable;
240} 241}
241 242
242static void twl4030_power_up(struct snd_soc_codec *codec) 243static void twl4030_power_up(struct snd_soc_codec *codec)
@@ -613,6 +614,27 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
613 return 0; 614 return 0;
614} 615}
615 616
617static int vibramux_event(struct snd_soc_dapm_widget *w,
618 struct snd_kcontrol *kcontrol, int event)
619{
620 twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff);
621 return 0;
622}
623
624static int apll_event(struct snd_soc_dapm_widget *w,
625 struct snd_kcontrol *kcontrol, int event)
626{
627 switch (event) {
628 case SND_SOC_DAPM_PRE_PMU:
629 twl4030_apll_enable(w->codec, 1);
630 break;
631 case SND_SOC_DAPM_POST_PMD:
632 twl4030_apll_enable(w->codec, 0);
633 break;
634 }
635 return 0;
636}
637
616static void headset_ramp(struct snd_soc_codec *codec, int ramp) 638static void headset_ramp(struct snd_soc_codec *codec, int ramp)
617{ 639{
618 struct snd_soc_device *socdev = codec->socdev; 640 struct snd_soc_device *socdev = codec->socdev;
@@ -724,67 +746,6 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
724 return 0; 746 return 0;
725} 747}
726 748
727static int bypass_event(struct snd_soc_dapm_widget *w,
728 struct snd_kcontrol *kcontrol, int event)
729{
730 struct soc_mixer_control *m =
731 (struct soc_mixer_control *)w->kcontrols->private_value;
732 struct twl4030_priv *twl4030 = w->codec->private_data;
733 unsigned char reg, misc;
734
735 reg = twl4030_read_reg_cache(w->codec, m->reg);
736
737 /*
738 * bypass_state[0:3] - analog HiFi bypass
739 * bypass_state[4] - analog voice bypass
740 * bypass_state[5] - digital voice bypass
741 * bypass_state[6:7] - digital HiFi bypass
742 */
743 if (m->reg == TWL4030_REG_VSTPGA) {
744 /* Voice digital bypass */
745 if (reg)
746 twl4030->bypass_state |= (1 << 5);
747 else
748 twl4030->bypass_state &= ~(1 << 5);
749 } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
750 /* Analog bypass */
751 if (reg & (1 << m->shift))
752 twl4030->bypass_state |=
753 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
754 else
755 twl4030->bypass_state &=
756 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
757 } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
758 /* Analog voice bypass */
759 if (reg & (1 << m->shift))
760 twl4030->bypass_state |= (1 << 4);
761 else
762 twl4030->bypass_state &= ~(1 << 4);
763 } else {
764 /* Digital bypass */
765 if (reg & (0x7 << m->shift))
766 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
767 else
768 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
769 }
770
771 /* Enable master analog loopback mode if any analog switch is enabled*/
772 misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
773 if (twl4030->bypass_state & 0x1F)
774 misc |= TWL4030_FMLOOP_EN;
775 else
776 misc &= ~TWL4030_FMLOOP_EN;
777 twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
778
779 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
780 if (twl4030->bypass_state)
781 twl4030_codec_mute(w->codec, 0);
782 else
783 twl4030_codec_mute(w->codec, 1);
784 }
785 return 0;
786}
787
788/* 749/*
789 * Some of the gain controls in TWL (mostly those which are associated with 750 * Some of the gain controls in TWL (mostly those which are associated with
790 * the outputs) are implemented in an interesting way: 751 * the outputs) are implemented in an interesting way:
@@ -1192,32 +1153,28 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1192 SND_SOC_NOPM, 0, 0), 1153 SND_SOC_NOPM, 0, 0),
1193 1154
1194 /* Analog bypasses */ 1155 /* Analog bypasses */
1195 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1156 SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1196 &twl4030_dapm_abypassr1_control, bypass_event, 1157 &twl4030_dapm_abypassr1_control),
1197 SND_SOC_DAPM_POST_REG), 1158 SND_SOC_DAPM_SWITCH("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1198 SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1159 &twl4030_dapm_abypassl1_control),
1199 &twl4030_dapm_abypassl1_control, 1160 SND_SOC_DAPM_SWITCH("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1200 bypass_event, SND_SOC_DAPM_POST_REG), 1161 &twl4030_dapm_abypassr2_control),
1201 SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1162 SND_SOC_DAPM_SWITCH("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1202 &twl4030_dapm_abypassr2_control, 1163 &twl4030_dapm_abypassl2_control),
1203 bypass_event, SND_SOC_DAPM_POST_REG), 1164 SND_SOC_DAPM_SWITCH("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1204 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1165 &twl4030_dapm_abypassv_control),
1205 &twl4030_dapm_abypassl2_control, 1166
1206 bypass_event, SND_SOC_DAPM_POST_REG), 1167 /* Master analog loopback switch */
1207 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, 1168 SND_SOC_DAPM_SUPPLY("FM Loop Enable", TWL4030_REG_MISC_SET_1, 5, 0,
1208 &twl4030_dapm_abypassv_control, 1169 NULL, 0),
1209 bypass_event, SND_SOC_DAPM_POST_REG),
1210 1170
1211 /* Digital bypasses */ 1171 /* Digital bypasses */
1212 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1172 SND_SOC_DAPM_SWITCH("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
1213 &twl4030_dapm_dbypassl_control, bypass_event, 1173 &twl4030_dapm_dbypassl_control),
1214 SND_SOC_DAPM_POST_REG), 1174 SND_SOC_DAPM_SWITCH("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
1215 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1175 &twl4030_dapm_dbypassr_control),
1216 &twl4030_dapm_dbypassr_control, bypass_event, 1176 SND_SOC_DAPM_SWITCH("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1217 SND_SOC_DAPM_POST_REG), 1177 &twl4030_dapm_dbypassv_control),
1218 SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1219 &twl4030_dapm_dbypassv_control, bypass_event,
1220 SND_SOC_DAPM_POST_REG),
1221 1178
1222 /* Digital mixers, power control for the physical DACs */ 1179 /* Digital mixers, power control for the physical DACs */
1223 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", 1180 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
@@ -1243,6 +1200,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1243 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", 1200 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1244 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), 1201 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1245 1202
1203 SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event,
1204 SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD),
1205
1246 /* Output MIXER controls */ 1206 /* Output MIXER controls */
1247 /* Earpiece */ 1207 /* Earpiece */
1248 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, 1208 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
@@ -1308,8 +1268,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1308 0, 0, NULL, 0, handsfreerpga_event, 1268 0, 0, NULL, 0, handsfreerpga_event,
1309 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1269 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1310 /* Vibra */ 1270 /* Vibra */
1311 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, 1271 SND_SOC_DAPM_MUX_E("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1312 &twl4030_dapm_vibra_control), 1272 &twl4030_dapm_vibra_control, vibramux_event,
1273 SND_SOC_DAPM_PRE_PMU),
1313 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, 1274 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1314 &twl4030_dapm_vibrapath_control), 1275 &twl4030_dapm_vibrapath_control),
1315 1276
@@ -1369,6 +1330,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1369 {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, 1330 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1370 {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, 1331 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1371 1332
1333 /* Supply for the digital part (APLL) */
1334 {"Digital R1 Playback Mixer", NULL, "APLL Enable"},
1335 {"Digital L1 Playback Mixer", NULL, "APLL Enable"},
1336 {"Digital R2 Playback Mixer", NULL, "APLL Enable"},
1337 {"Digital L2 Playback Mixer", NULL, "APLL Enable"},
1338 {"Digital Voice Playback Mixer", NULL, "APLL Enable"},
1339
1372 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, 1340 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1373 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, 1341 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1374 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, 1342 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
@@ -1482,6 +1450,11 @@ static const struct snd_soc_dapm_route intercon[] = {
1482 {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, 1450 {"ADC Virtual Left2", NULL, "TX2 Capture Route"},
1483 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1451 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
1484 1452
1453 {"ADC Virtual Left1", NULL, "APLL Enable"},
1454 {"ADC Virtual Right1", NULL, "APLL Enable"},
1455 {"ADC Virtual Left2", NULL, "APLL Enable"},
1456 {"ADC Virtual Right2", NULL, "APLL Enable"},
1457
1485 /* Analog bypass routes */ 1458 /* Analog bypass routes */
1486 {"Right1 Analog Loopback", "Switch", "Analog Right"}, 1459 {"Right1 Analog Loopback", "Switch", "Analog Right"},
1487 {"Left1 Analog Loopback", "Switch", "Analog Left"}, 1460 {"Left1 Analog Loopback", "Switch", "Analog Left"},
@@ -1489,6 +1462,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1489 {"Left2 Analog Loopback", "Switch", "Analog Left"}, 1462 {"Left2 Analog Loopback", "Switch", "Analog Left"},
1490 {"Voice Analog Loopback", "Switch", "Analog Left"}, 1463 {"Voice Analog Loopback", "Switch", "Analog Left"},
1491 1464
1465 /* Supply for the Analog loopbacks */
1466 {"Right1 Analog Loopback", NULL, "FM Loop Enable"},
1467 {"Left1 Analog Loopback", NULL, "FM Loop Enable"},
1468 {"Right2 Analog Loopback", NULL, "FM Loop Enable"},
1469 {"Left2 Analog Loopback", NULL, "FM Loop Enable"},
1470 {"Voice Analog Loopback", NULL, "FM Loop Enable"},
1471
1492 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1472 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1493 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1473 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1494 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1474 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
@@ -1513,32 +1493,20 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec)
1513 1493
1514 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 1494 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
1515 1495
1516 snd_soc_dapm_new_widgets(codec);
1517 return 0; 1496 return 0;
1518} 1497}
1519 1498
1520static int twl4030_set_bias_level(struct snd_soc_codec *codec, 1499static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1521 enum snd_soc_bias_level level) 1500 enum snd_soc_bias_level level)
1522{ 1501{
1523 struct twl4030_priv *twl4030 = codec->private_data;
1524
1525 switch (level) { 1502 switch (level) {
1526 case SND_SOC_BIAS_ON: 1503 case SND_SOC_BIAS_ON:
1527 twl4030_codec_mute(codec, 0);
1528 break; 1504 break;
1529 case SND_SOC_BIAS_PREPARE: 1505 case SND_SOC_BIAS_PREPARE:
1530 twl4030_power_up(codec);
1531 if (twl4030->bypass_state)
1532 twl4030_codec_mute(codec, 0);
1533 else
1534 twl4030_codec_mute(codec, 1);
1535 break; 1506 break;
1536 case SND_SOC_BIAS_STANDBY: 1507 case SND_SOC_BIAS_STANDBY:
1537 twl4030_power_up(codec); 1508 if (codec->bias_level == SND_SOC_BIAS_OFF)
1538 if (twl4030->bypass_state) 1509 twl4030_power_up(codec);
1539 twl4030_codec_mute(codec, 0);
1540 else
1541 twl4030_codec_mute(codec, 1);
1542 break; 1510 break;
1543 case SND_SOC_BIAS_OFF: 1511 case SND_SOC_BIAS_OFF:
1544 twl4030_power_down(codec); 1512 twl4030_power_down(codec);
@@ -1785,29 +1753,23 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1785{ 1753{
1786 struct snd_soc_codec *codec = codec_dai->codec; 1754 struct snd_soc_codec *codec = codec_dai->codec;
1787 struct twl4030_priv *twl4030 = codec->private_data; 1755 struct twl4030_priv *twl4030 = codec->private_data;
1788 u8 infreq;
1789 1756
1790 switch (freq) { 1757 switch (freq) {
1791 case 19200000: 1758 case 19200000:
1792 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1793 twl4030->sysclk = 19200;
1794 break;
1795 case 26000000: 1759 case 26000000:
1796 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1797 twl4030->sysclk = 26000;
1798 break;
1799 case 38400000: 1760 case 38400000:
1800 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1801 twl4030->sysclk = 38400;
1802 break; 1761 break;
1803 default: 1762 default:
1804 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", 1763 dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
1805 freq);
1806 return -EINVAL; 1764 return -EINVAL;
1807 } 1765 }
1808 1766
1809 infreq |= TWL4030_APLL_EN; 1767 if ((freq / 1000) != twl4030->sysclk) {
1810 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq); 1768 dev_err(codec->dev,
1769 "Mismatch in APLL mclk: %u (configured: %u)\n",
1770 freq, twl4030->sysclk * 1000);
1771 return -EINVAL;
1772 }
1811 1773
1812 return 0; 1774 return 0;
1813} 1775}
@@ -1905,18 +1867,16 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1905 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1867 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1906 struct snd_soc_device *socdev = rtd->socdev; 1868 struct snd_soc_device *socdev = rtd->socdev;
1907 struct snd_soc_codec *codec = socdev->card->codec; 1869 struct snd_soc_codec *codec = socdev->card->codec;
1908 u8 infreq; 1870 struct twl4030_priv *twl4030 = codec->private_data;
1909 u8 mode; 1871 u8 mode;
1910 1872
1911 /* If the system master clock is not 26MHz, the voice PCM interface is 1873 /* If the system master clock is not 26MHz, the voice PCM interface is
1912 * not avilable. 1874 * not avilable.
1913 */ 1875 */
1914 infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL) 1876 if (twl4030->sysclk != 26000) {
1915 & TWL4030_APLL_INFREQ; 1877 dev_err(codec->dev, "The board is configured for %u Hz, while"
1916 1878 "the Voice interface needs 26MHz APLL mclk\n",
1917 if (infreq != TWL4030_APLL_INFREQ_26000KHZ) { 1879 twl4030->sysclk * 1000);
1918 printk(KERN_ERR "TWL4030 voice startup: "
1919 "MCLK is not 26MHz, call set_sysclk() on init\n");
1920 return -EINVAL; 1880 return -EINVAL;
1921 } 1881 }
1922 1882
@@ -1989,21 +1949,19 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1989 int clk_id, unsigned int freq, int dir) 1949 int clk_id, unsigned int freq, int dir)
1990{ 1950{
1991 struct snd_soc_codec *codec = codec_dai->codec; 1951 struct snd_soc_codec *codec = codec_dai->codec;
1992 u8 infreq; 1952 struct twl4030_priv *twl4030 = codec->private_data;
1993 1953
1994 switch (freq) { 1954 if (freq != 26000000) {
1995 case 26000000: 1955 dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
1996 infreq = TWL4030_APLL_INFREQ_26000KHZ; 1956 "interface needs 26MHz APLL mclk\n", freq);
1997 break; 1957 return -EINVAL;
1998 default: 1958 }
1999 printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n", 1959 if ((freq / 1000) != twl4030->sysclk) {
2000 freq); 1960 dev_err(codec->dev,
1961 "Mismatch in APLL mclk: %u (configured: %u)\n",
1962 freq, twl4030->sysclk * 1000);
2001 return -EINVAL; 1963 return -EINVAL;
2002 } 1964 }
2003
2004 infreq |= TWL4030_APLL_EN;
2005 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
2006
2007 return 0; 1965 return 0;
2008} 1966}
2009 1967
@@ -2121,7 +2079,7 @@ struct snd_soc_dai twl4030_dai[] = {
2121}; 2079};
2122EXPORT_SYMBOL_GPL(twl4030_dai); 2080EXPORT_SYMBOL_GPL(twl4030_dai);
2123 2081
2124static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) 2082static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state)
2125{ 2083{
2126 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2084 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2127 struct snd_soc_codec *codec = socdev->card->codec; 2085 struct snd_soc_codec *codec = socdev->card->codec;
@@ -2131,7 +2089,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
2131 return 0; 2089 return 0;
2132} 2090}
2133 2091
2134static int twl4030_resume(struct platform_device *pdev) 2092static int twl4030_soc_resume(struct platform_device *pdev)
2135{ 2093{
2136 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2094 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2137 struct snd_soc_codec *codec = socdev->card->codec; 2095 struct snd_soc_codec *codec = socdev->card->codec;
@@ -2141,147 +2099,181 @@ static int twl4030_resume(struct platform_device *pdev)
2141 return 0; 2099 return 0;
2142} 2100}
2143 2101
2144/* 2102static struct snd_soc_codec *twl4030_codec;
2145 * initialize the driver
2146 * register the mixer and dsp interfaces with the kernel
2147 */
2148 2103
2149static int twl4030_init(struct snd_soc_device *socdev) 2104static int twl4030_soc_probe(struct platform_device *pdev)
2150{ 2105{
2151 struct snd_soc_codec *codec = socdev->card->codec; 2106 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2152 struct twl4030_setup_data *setup = socdev->codec_data; 2107 struct twl4030_setup_data *setup = socdev->codec_data;
2153 struct twl4030_priv *twl4030 = codec->private_data; 2108 struct snd_soc_codec *codec;
2154 int ret = 0; 2109 struct twl4030_priv *twl4030;
2110 int ret;
2155 2111
2156 printk(KERN_INFO "TWL4030 Audio Codec init \n"); 2112 BUG_ON(!twl4030_codec);
2157 2113
2158 codec->name = "twl4030"; 2114 codec = twl4030_codec;
2159 codec->owner = THIS_MODULE; 2115 twl4030 = codec->private_data;
2160 codec->read = twl4030_read_reg_cache; 2116 socdev->card->codec = codec;
2161 codec->write = twl4030_write;
2162 codec->set_bias_level = twl4030_set_bias_level;
2163 codec->dai = twl4030_dai;
2164 codec->num_dai = ARRAY_SIZE(twl4030_dai),
2165 codec->reg_cache_size = sizeof(twl4030_reg);
2166 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
2167 GFP_KERNEL);
2168 if (codec->reg_cache == NULL)
2169 return -ENOMEM;
2170 2117
2171 /* Configuration for headset ramp delay from setup data */ 2118 /* Configuration for headset ramp delay from setup data */
2172 if (setup) { 2119 if (setup) {
2173 unsigned char hs_pop; 2120 unsigned char hs_pop;
2174 2121
2175 if (setup->sysclk) 2122 if (setup->sysclk != twl4030->sysclk)
2176 twl4030->sysclk = setup->sysclk; 2123 dev_warn(&pdev->dev,
2177 else 2124 "Mismatch in APLL mclk: %u (configured: %u)\n",
2178 twl4030->sysclk = 26000; 2125 setup->sysclk, twl4030->sysclk);
2179 2126
2180 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); 2127 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2181 hs_pop &= ~TWL4030_RAMP_DELAY; 2128 hs_pop &= ~TWL4030_RAMP_DELAY;
2182 hs_pop |= (setup->ramp_delay_value << 2); 2129 hs_pop |= (setup->ramp_delay_value << 2);
2183 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 2130 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2184 } else {
2185 twl4030->sysclk = 26000;
2186 } 2131 }
2187 2132
2188 /* register pcms */ 2133 /* register pcms */
2189 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2134 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
2190 if (ret < 0) { 2135 if (ret < 0) {
2191 printk(KERN_ERR "twl4030: failed to create pcms\n"); 2136 dev_err(&pdev->dev, "failed to create pcms\n");
2192 goto pcm_err; 2137 return ret;
2193 } 2138 }
2194 2139
2195 twl4030_init_chip(codec);
2196
2197 /* power on device */
2198 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2199
2200 snd_soc_add_controls(codec, twl4030_snd_controls, 2140 snd_soc_add_controls(codec, twl4030_snd_controls,
2201 ARRAY_SIZE(twl4030_snd_controls)); 2141 ARRAY_SIZE(twl4030_snd_controls));
2202 twl4030_add_widgets(codec); 2142 twl4030_add_widgets(codec);
2203 2143
2204 ret = snd_soc_init_card(socdev); 2144 return 0;
2205 if (ret < 0) { 2145}
2206 printk(KERN_ERR "twl4030: failed to register card\n");
2207 goto card_err;
2208 }
2209 2146
2210 return ret; 2147static int twl4030_soc_remove(struct platform_device *pdev)
2148{
2149 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2150 struct snd_soc_codec *codec = socdev->card->codec;
2211 2151
2212card_err: 2152 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2213 snd_soc_free_pcms(socdev); 2153 snd_soc_free_pcms(socdev);
2214 snd_soc_dapm_free(socdev); 2154 snd_soc_dapm_free(socdev);
2215pcm_err: 2155 kfree(codec->private_data);
2216 kfree(codec->reg_cache); 2156 kfree(codec);
2217 return ret;
2218}
2219 2157
2220static struct snd_soc_device *twl4030_socdev; 2158 return 0;
2159}
2221 2160
2222static int twl4030_probe(struct platform_device *pdev) 2161static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2223{ 2162{
2224 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2163 struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
2225 struct snd_soc_codec *codec; 2164 struct snd_soc_codec *codec;
2226 struct twl4030_priv *twl4030; 2165 struct twl4030_priv *twl4030;
2166 int ret;
2227 2167
2228 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 2168 if (!pdata) {
2229 if (codec == NULL) 2169 dev_err(&pdev->dev, "platform_data is missing\n");
2230 return -ENOMEM; 2170 return -EINVAL;
2171 }
2231 2172
2232 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); 2173 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
2233 if (twl4030 == NULL) { 2174 if (twl4030 == NULL) {
2234 kfree(codec); 2175 dev_err(&pdev->dev, "Can not allocate memroy\n");
2235 return -ENOMEM; 2176 return -ENOMEM;
2236 } 2177 }
2237 2178
2179 codec = &twl4030->codec;
2238 codec->private_data = twl4030; 2180 codec->private_data = twl4030;
2239 socdev->card->codec = codec; 2181 codec->dev = &pdev->dev;
2182 twl4030_dai[0].dev = &pdev->dev;
2183 twl4030_dai[1].dev = &pdev->dev;
2184
2240 mutex_init(&codec->mutex); 2185 mutex_init(&codec->mutex);
2241 INIT_LIST_HEAD(&codec->dapm_widgets); 2186 INIT_LIST_HEAD(&codec->dapm_widgets);
2242 INIT_LIST_HEAD(&codec->dapm_paths); 2187 INIT_LIST_HEAD(&codec->dapm_paths);
2243 2188
2244 twl4030_socdev = socdev; 2189 codec->name = "twl4030";
2245 twl4030_init(socdev); 2190 codec->owner = THIS_MODULE;
2191 codec->read = twl4030_read_reg_cache;
2192 codec->write = twl4030_write;
2193 codec->set_bias_level = twl4030_set_bias_level;
2194 codec->dai = twl4030_dai;
2195 codec->num_dai = ARRAY_SIZE(twl4030_dai),
2196 codec->reg_cache_size = sizeof(twl4030_reg);
2197 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
2198 GFP_KERNEL);
2199 if (codec->reg_cache == NULL) {
2200 ret = -ENOMEM;
2201 goto error_cache;
2202 }
2203
2204 platform_set_drvdata(pdev, twl4030);
2205 twl4030_codec = codec;
2206
2207 /* Set the defaults, and power up the codec */
2208 twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
2209 twl4030_init_chip(codec);
2210 codec->bias_level = SND_SOC_BIAS_OFF;
2211 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2212
2213 ret = snd_soc_register_codec(codec);
2214 if (ret != 0) {
2215 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2216 goto error_codec;
2217 }
2218
2219 ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
2220 if (ret != 0) {
2221 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
2222 snd_soc_unregister_codec(codec);
2223 goto error_codec;
2224 }
2246 2225
2247 return 0; 2226 return 0;
2227
2228error_codec:
2229 twl4030_power_down(codec);
2230 kfree(codec->reg_cache);
2231error_cache:
2232 kfree(twl4030);
2233 return ret;
2248} 2234}
2249 2235
2250static int twl4030_remove(struct platform_device *pdev) 2236static int __devexit twl4030_codec_remove(struct platform_device *pdev)
2251{ 2237{
2252 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2238 struct twl4030_priv *twl4030 = platform_get_drvdata(pdev);
2253 struct snd_soc_codec *codec = socdev->card->codec;
2254 2239
2255 printk(KERN_INFO "TWL4030 Audio Codec remove\n"); 2240 kfree(twl4030);
2256 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2257 snd_soc_free_pcms(socdev);
2258 snd_soc_dapm_free(socdev);
2259 kfree(codec->private_data);
2260 kfree(codec);
2261 2241
2242 twl4030_codec = NULL;
2262 return 0; 2243 return 0;
2263} 2244}
2264 2245
2265struct snd_soc_codec_device soc_codec_dev_twl4030 = { 2246MODULE_ALIAS("platform:twl4030_codec_audio");
2266 .probe = twl4030_probe, 2247
2267 .remove = twl4030_remove, 2248static struct platform_driver twl4030_codec_driver = {
2268 .suspend = twl4030_suspend, 2249 .probe = twl4030_codec_probe,
2269 .resume = twl4030_resume, 2250 .remove = __devexit_p(twl4030_codec_remove),
2251 .driver = {
2252 .name = "twl4030_codec_audio",
2253 .owner = THIS_MODULE,
2254 },
2270}; 2255};
2271EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
2272 2256
2273static int __init twl4030_modinit(void) 2257static int __init twl4030_modinit(void)
2274{ 2258{
2275 return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); 2259 return platform_driver_register(&twl4030_codec_driver);
2276} 2260}
2277module_init(twl4030_modinit); 2261module_init(twl4030_modinit);
2278 2262
2279static void __exit twl4030_exit(void) 2263static void __exit twl4030_exit(void)
2280{ 2264{
2281 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); 2265 platform_driver_unregister(&twl4030_codec_driver);
2282} 2266}
2283module_exit(twl4030_exit); 2267module_exit(twl4030_exit);
2284 2268
2269struct snd_soc_codec_device soc_codec_dev_twl4030 = {
2270 .probe = twl4030_soc_probe,
2271 .remove = twl4030_soc_remove,
2272 .suspend = twl4030_soc_suspend,
2273 .resume = twl4030_soc_resume,
2274};
2275EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
2276
2285MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); 2277MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
2286MODULE_AUTHOR("Steve Sakoman"); 2278MODULE_AUTHOR("Steve Sakoman");
2287MODULE_LICENSE("GPL"); 2279MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 2b4bfa23f985..dd6396ec9c79 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -22,245 +22,13 @@
22#ifndef __TWL4030_AUDIO_H__ 22#ifndef __TWL4030_AUDIO_H__
23#define __TWL4030_AUDIO_H__ 23#define __TWL4030_AUDIO_H__
24 24
25#define TWL4030_REG_CODEC_MODE 0x1 25/* Register descriptions are here */
26#define TWL4030_REG_OPTION 0x2 26#include <linux/mfd/twl4030-codec.h>
27#define TWL4030_REG_UNKNOWN 0x3
28#define TWL4030_REG_MICBIAS_CTL 0x4
29#define TWL4030_REG_ANAMICL 0x5
30#define TWL4030_REG_ANAMICR 0x6
31#define TWL4030_REG_AVADC_CTL 0x7
32#define TWL4030_REG_ADCMICSEL 0x8
33#define TWL4030_REG_DIGMIXING 0x9
34#define TWL4030_REG_ATXL1PGA 0xA
35#define TWL4030_REG_ATXR1PGA 0xB
36#define TWL4030_REG_AVTXL2PGA 0xC
37#define TWL4030_REG_AVTXR2PGA 0xD
38#define TWL4030_REG_AUDIO_IF 0xE
39#define TWL4030_REG_VOICE_IF 0xF
40#define TWL4030_REG_ARXR1PGA 0x10
41#define TWL4030_REG_ARXL1PGA 0x11
42#define TWL4030_REG_ARXR2PGA 0x12
43#define TWL4030_REG_ARXL2PGA 0x13
44#define TWL4030_REG_VRXPGA 0x14
45#define TWL4030_REG_VSTPGA 0x15
46#define TWL4030_REG_VRX2ARXPGA 0x16
47#define TWL4030_REG_AVDAC_CTL 0x17
48#define TWL4030_REG_ARX2VTXPGA 0x18
49#define TWL4030_REG_ARXL1_APGA_CTL 0x19
50#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
51#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
52#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
53#define TWL4030_REG_ATX2ARXPGA 0x1D
54#define TWL4030_REG_BT_IF 0x1E
55#define TWL4030_REG_BTPGA 0x1F
56#define TWL4030_REG_BTSTPGA 0x20
57#define TWL4030_REG_EAR_CTL 0x21
58#define TWL4030_REG_HS_SEL 0x22
59#define TWL4030_REG_HS_GAIN_SET 0x23
60#define TWL4030_REG_HS_POPN_SET 0x24
61#define TWL4030_REG_PREDL_CTL 0x25
62#define TWL4030_REG_PREDR_CTL 0x26
63#define TWL4030_REG_PRECKL_CTL 0x27
64#define TWL4030_REG_PRECKR_CTL 0x28
65#define TWL4030_REG_HFL_CTL 0x29
66#define TWL4030_REG_HFR_CTL 0x2A
67#define TWL4030_REG_ALC_CTL 0x2B
68#define TWL4030_REG_ALC_SET1 0x2C
69#define TWL4030_REG_ALC_SET2 0x2D
70#define TWL4030_REG_BOOST_CTL 0x2E
71#define TWL4030_REG_SOFTVOL_CTL 0x2F
72#define TWL4030_REG_DTMF_FREQSEL 0x30
73#define TWL4030_REG_DTMF_TONEXT1H 0x31
74#define TWL4030_REG_DTMF_TONEXT1L 0x32
75#define TWL4030_REG_DTMF_TONEXT2H 0x33
76#define TWL4030_REG_DTMF_TONEXT2L 0x34
77#define TWL4030_REG_DTMF_TONOFF 0x35
78#define TWL4030_REG_DTMF_WANONOFF 0x36
79#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
80#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
81#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
82#define TWL4030_REG_APLL_CTL 0x3A
83#define TWL4030_REG_DTMF_CTL 0x3B
84#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
85#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
86#define TWL4030_REG_MISC_SET_1 0x3E
87#define TWL4030_REG_PCMBTMUX 0x3F
88#define TWL4030_REG_RX_PATH_SEL 0x43
89#define TWL4030_REG_VDL_APGA_CTL 0x44
90#define TWL4030_REG_VIBRA_CTL 0x45
91#define TWL4030_REG_VIBRA_SET 0x46
92#define TWL4030_REG_VIBRA_PWM_SET 0x47
93#define TWL4030_REG_ANAMIC_GAIN 0x48
94#define TWL4030_REG_MISC_SET_2 0x49
95#define TWL4030_REG_SW_SHADOW 0x4A
96 27
28/* Sgadow register used by the audio driver */
29#define TWL4030_REG_SW_SHADOW 0x4A
97#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) 30#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
98 31
99/* Bitfield Definitions */
100
101/* TWL4030_CODEC_MODE (0x01) Fields */
102
103#define TWL4030_APLL_RATE 0xF0
104#define TWL4030_APLL_RATE_8000 0x00
105#define TWL4030_APLL_RATE_11025 0x10
106#define TWL4030_APLL_RATE_12000 0x20
107#define TWL4030_APLL_RATE_16000 0x40
108#define TWL4030_APLL_RATE_22050 0x50
109#define TWL4030_APLL_RATE_24000 0x60
110#define TWL4030_APLL_RATE_32000 0x80
111#define TWL4030_APLL_RATE_44100 0x90
112#define TWL4030_APLL_RATE_48000 0xA0
113#define TWL4030_APLL_RATE_96000 0xE0
114#define TWL4030_SEL_16K 0x08
115#define TWL4030_CODECPDZ 0x02
116#define TWL4030_OPT_MODE 0x01
117#define TWL4030_OPTION_1 (1 << 0)
118#define TWL4030_OPTION_2 (0 << 0)
119
120/* TWL4030_OPTION (0x02) Fields */
121
122#define TWL4030_ATXL1_EN (1 << 0)
123#define TWL4030_ATXR1_EN (1 << 1)
124#define TWL4030_ATXL2_VTXL_EN (1 << 2)
125#define TWL4030_ATXR2_VTXR_EN (1 << 3)
126#define TWL4030_ARXL1_VRX_EN (1 << 4)
127#define TWL4030_ARXR1_EN (1 << 5)
128#define TWL4030_ARXL2_EN (1 << 6)
129#define TWL4030_ARXR2_EN (1 << 7)
130
131/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
132
133#define TWL4030_MICBIAS2_CTL 0x40
134#define TWL4030_MICBIAS1_CTL 0x20
135#define TWL4030_HSMICBIAS_EN 0x04
136#define TWL4030_MICBIAS2_EN 0x02
137#define TWL4030_MICBIAS1_EN 0x01
138
139/* ANAMICL (0x05) Fields */
140
141#define TWL4030_CNCL_OFFSET_START 0x80
142#define TWL4030_OFFSET_CNCL_SEL 0x60
143#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
144#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
145#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
146#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
147#define TWL4030_MICAMPL_EN 0x10
148#define TWL4030_CKMIC_EN 0x08
149#define TWL4030_AUXL_EN 0x04
150#define TWL4030_HSMIC_EN 0x02
151#define TWL4030_MAINMIC_EN 0x01
152
153/* ANAMICR (0x06) Fields */
154
155#define TWL4030_MICAMPR_EN 0x10
156#define TWL4030_AUXR_EN 0x04
157#define TWL4030_SUBMIC_EN 0x01
158
159/* AVADC_CTL (0x07) Fields */
160
161#define TWL4030_ADCL_EN 0x08
162#define TWL4030_AVADC_CLK_PRIORITY 0x04
163#define TWL4030_ADCR_EN 0x02
164
165/* TWL4030_REG_ADCMICSEL (0x08) Fields */
166
167#define TWL4030_DIGMIC1_EN 0x08
168#define TWL4030_TX2IN_SEL 0x04
169#define TWL4030_DIGMIC0_EN 0x02
170#define TWL4030_TX1IN_SEL 0x01
171
172/* AUDIO_IF (0x0E) Fields */
173
174#define TWL4030_AIF_SLAVE_EN 0x80
175#define TWL4030_DATA_WIDTH 0x60
176#define TWL4030_DATA_WIDTH_16S_16W 0x00
177#define TWL4030_DATA_WIDTH_32S_16W 0x40
178#define TWL4030_DATA_WIDTH_32S_24W 0x60
179#define TWL4030_AIF_FORMAT 0x18
180#define TWL4030_AIF_FORMAT_CODEC 0x00
181#define TWL4030_AIF_FORMAT_LEFT 0x08
182#define TWL4030_AIF_FORMAT_RIGHT 0x10
183#define TWL4030_AIF_FORMAT_TDM 0x18
184#define TWL4030_AIF_TRI_EN 0x04
185#define TWL4030_CLK256FS_EN 0x02
186#define TWL4030_AIF_EN 0x01
187
188/* VOICE_IF (0x0F) Fields */
189
190#define TWL4030_VIF_SLAVE_EN 0x80
191#define TWL4030_VIF_DIN_EN 0x40
192#define TWL4030_VIF_DOUT_EN 0x20
193#define TWL4030_VIF_SWAP 0x10
194#define TWL4030_VIF_FORMAT 0x08
195#define TWL4030_VIF_TRI_EN 0x04
196#define TWL4030_VIF_SUB_EN 0x02
197#define TWL4030_VIF_EN 0x01
198
199/* EAR_CTL (0x21) */
200#define TWL4030_EAR_GAIN 0x30
201
202/* HS_GAIN_SET (0x23) Fields */
203
204#define TWL4030_HSR_GAIN 0x0C
205#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
206#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
207#define TWL4030_HSR_GAIN_0DB 0x08
208#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
209#define TWL4030_HSL_GAIN 0x03
210#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
211#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
212#define TWL4030_HSL_GAIN_0DB 0x02
213#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
214
215/* HS_POPN_SET (0x24) Fields */
216
217#define TWL4030_VMID_EN 0x40
218#define TWL4030_EXTMUTE 0x20
219#define TWL4030_RAMP_DELAY 0x1C
220#define TWL4030_RAMP_DELAY_20MS 0x00
221#define TWL4030_RAMP_DELAY_40MS 0x04
222#define TWL4030_RAMP_DELAY_81MS 0x08
223#define TWL4030_RAMP_DELAY_161MS 0x0C
224#define TWL4030_RAMP_DELAY_323MS 0x10
225#define TWL4030_RAMP_DELAY_645MS 0x14
226#define TWL4030_RAMP_DELAY_1291MS 0x18
227#define TWL4030_RAMP_DELAY_2581MS 0x1C
228#define TWL4030_RAMP_EN 0x02
229
230/* PREDL_CTL (0x25) */
231#define TWL4030_PREDL_GAIN 0x30
232
233/* PREDR_CTL (0x26) */
234#define TWL4030_PREDR_GAIN 0x30
235
236/* PRECKL_CTL (0x27) */
237#define TWL4030_PRECKL_GAIN 0x30
238
239/* PRECKR_CTL (0x28) */
240#define TWL4030_PRECKR_GAIN 0x30
241
242/* HFL_CTL (0x29, 0x2A) Fields */
243#define TWL4030_HF_CTL_HB_EN 0x04
244#define TWL4030_HF_CTL_LOOP_EN 0x08
245#define TWL4030_HF_CTL_RAMP_EN 0x10
246#define TWL4030_HF_CTL_REF_EN 0x20
247
248/* APLL_CTL (0x3A) Fields */
249
250#define TWL4030_APLL_EN 0x10
251#define TWL4030_APLL_INFREQ 0x0F
252#define TWL4030_APLL_INFREQ_19200KHZ 0x05
253#define TWL4030_APLL_INFREQ_26000KHZ 0x06
254#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
255
256/* REG_MISC_SET_1 (0x3E) Fields */
257
258#define TWL4030_CLK64_EN 0x80
259#define TWL4030_SCRAMBLE_EN 0x40
260#define TWL4030_FMLOOP_EN 0x20
261#define TWL4030_SMOOTH_ANAVOL_EN 0x02
262#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
263
264/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ 32/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
265#define TWL4030_HFL_EN 0x01 33#define TWL4030_HFL_EN 0x01
266#define TWL4030_HFR_EN 0x02 34#define TWL4030_HFR_EN 0x02
@@ -279,3 +47,5 @@ struct twl4030_setup_data {
279}; 47};
280 48
281#endif /* End of __TWL4030_AUDIO_H__ */ 49#endif /* End of __TWL4030_AUDIO_H__ */
50
51
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index c33b92edbded..aa40d985138f 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -562,17 +562,8 @@ static int uda134x_soc_probe(struct platform_device *pdev)
562 goto pcm_err; 562 goto pcm_err;
563 } 563 }
564 564
565 ret = snd_soc_init_card(socdev);
566 if (ret < 0) {
567 printk(KERN_ERR "UDA134X: failed to register card\n");
568 goto card_err;
569 }
570
571 return 0; 565 return 0;
572 566
573card_err:
574 snd_soc_free_pcms(socdev);
575 snd_soc_dapm_free(socdev);
576pcm_err: 567pcm_err:
577 kfree(codec->reg_cache); 568 kfree(codec->reg_cache);
578reg_err: 569reg_err:
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 92ec03442154..a2763c2e7348 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -378,7 +378,6 @@ static int uda1380_add_widgets(struct snd_soc_codec *codec)
378 378
379 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 379 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
380 380
381 snd_soc_dapm_new_widgets(codec);
382 return 0; 381 return 0;
383} 382}
384 383
@@ -713,17 +712,9 @@ static int uda1380_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, uda1380_snd_controls, 712 snd_soc_add_controls(codec, uda1380_snd_controls,
714 ARRAY_SIZE(uda1380_snd_controls)); 713 ARRAY_SIZE(uda1380_snd_controls));
715 uda1380_add_widgets(codec); 714 uda1380_add_widgets(codec);
716 ret = snd_soc_init_card(socdev);
717 if (ret < 0) {
718 dev_err(codec->dev, "failed to register card: %d\n", ret);
719 goto card_err;
720 }
721 715
722 return ret; 716 return ret;
723 717
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 718pcm_err:
728 return ret; 719 return ret;
729} 720}
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 593d5b9c9f03..f82125d9e85a 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -800,7 +800,7 @@ static int wm8350_add_widgets(struct snd_soc_codec *codec)
800 return ret; 800 return ret;
801 } 801 }
802 802
803 return snd_soc_dapm_new_widgets(codec); 803 return 0;
804} 804}
805 805
806static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, 806static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -1101,7 +1101,7 @@ static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
1101} 1101}
1102 1102
1103static int wm8350_set_fll(struct snd_soc_dai *codec_dai, 1103static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1104 int pll_id, unsigned int freq_in, 1104 int pll_id, int source, unsigned int freq_in,
1105 unsigned int freq_out) 1105 unsigned int freq_out)
1106{ 1106{
1107 struct snd_soc_codec *codec = codec_dai->codec; 1107 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1501,18 +1501,7 @@ static int wm8350_probe(struct platform_device *pdev)
1501 1501
1502 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1502 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1503 1503
1504 ret = snd_soc_init_card(socdev);
1505 if (ret < 0) {
1506 dev_err(&pdev->dev, "failed to register card\n");
1507 goto card_err;
1508 }
1509
1510 return 0; 1504 return 0;
1511
1512card_err:
1513 snd_soc_free_pcms(socdev);
1514 snd_soc_dapm_free(socdev);
1515 return ret;
1516} 1505}
1517 1506
1518static int wm8350_remove(struct platform_device *pdev) 1507static int wm8350_remove(struct platform_device *pdev)
@@ -1680,21 +1669,6 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1680 return 0; 1669 return 0;
1681} 1670}
1682 1671
1683#ifdef CONFIG_PM
1684static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
1685{
1686 return snd_soc_suspend_device(&pdev->dev);
1687}
1688
1689static int wm8350_codec_resume(struct platform_device *pdev)
1690{
1691 return snd_soc_resume_device(&pdev->dev);
1692}
1693#else
1694#define wm8350_codec_suspend NULL
1695#define wm8350_codec_resume NULL
1696#endif
1697
1698static struct platform_driver wm8350_codec_driver = { 1672static struct platform_driver wm8350_codec_driver = {
1699 .driver = { 1673 .driver = {
1700 .name = "wm8350-codec", 1674 .name = "wm8350-codec",
@@ -1702,8 +1676,6 @@ static struct platform_driver wm8350_codec_driver = {
1702 }, 1676 },
1703 .probe = wm8350_codec_probe, 1677 .probe = wm8350_codec_probe,
1704 .remove = __devexit_p(wm8350_codec_remove), 1678 .remove = __devexit_p(wm8350_codec_remove),
1705 .suspend = wm8350_codec_suspend,
1706 .resume = wm8350_codec_resume,
1707}; 1679};
1708 1680
1709static __init int wm8350_init(void) 1681static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index b9ef4d915221..b432f4d4a324 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -915,7 +915,6 @@ static int wm8400_add_widgets(struct snd_soc_codec *codec)
915 915
916 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 916 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
917 917
918 snd_soc_dapm_new_widgets(codec);
919 return 0; 918 return 0;
920} 919}
921 920
@@ -1011,7 +1010,8 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
1011} 1010}
1012 1011
1013static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 1012static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1014 unsigned int freq_in, unsigned int freq_out) 1013 int source, unsigned int freq_in,
1014 unsigned int freq_out)
1015{ 1015{
1016 struct snd_soc_codec *codec = codec_dai->codec; 1016 struct snd_soc_codec *codec = codec_dai->codec;
1017 struct wm8400_priv *wm8400 = codec->private_data; 1017 struct wm8400_priv *wm8400 = codec->private_data;
@@ -1399,17 +1399,6 @@ static int wm8400_probe(struct platform_device *pdev)
1399 wm8400_add_controls(codec); 1399 wm8400_add_controls(codec);
1400 wm8400_add_widgets(codec); 1400 wm8400_add_widgets(codec);
1401 1401
1402 ret = snd_soc_init_card(socdev);
1403 if (ret < 0) {
1404 dev_err(&pdev->dev, "failed to register card\n");
1405 goto card_err;
1406 }
1407
1408 return ret;
1409
1410card_err:
1411 snd_soc_free_pcms(socdev);
1412 snd_soc_dapm_free(socdev);
1413pcm_err: 1402pcm_err:
1414 return ret; 1403 return ret;
1415} 1404}
@@ -1558,21 +1547,6 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
1558 return 0; 1547 return 0;
1559} 1548}
1560 1549
1561#ifdef CONFIG_PM
1562static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
1563{
1564 return snd_soc_suspend_device(&pdev->dev);
1565}
1566
1567static int wm8400_pdev_resume(struct platform_device *pdev)
1568{
1569 return snd_soc_resume_device(&pdev->dev);
1570}
1571#else
1572#define wm8400_pdev_suspend NULL
1573#define wm8400_pdev_resume NULL
1574#endif
1575
1576static struct platform_driver wm8400_codec_driver = { 1550static struct platform_driver wm8400_codec_driver = {
1577 .driver = { 1551 .driver = {
1578 .name = "wm8400-codec", 1552 .name = "wm8400-codec",
@@ -1580,8 +1554,6 @@ static struct platform_driver wm8400_codec_driver = {
1580 }, 1554 },
1581 .probe = wm8400_codec_probe, 1555 .probe = wm8400_codec_probe,
1582 .remove = __exit_p(wm8400_codec_remove), 1556 .remove = __exit_p(wm8400_codec_remove),
1583 .suspend = wm8400_pdev_suspend,
1584 .resume = wm8400_pdev_resume,
1585}; 1557};
1586 1558
1587static int __init wm8400_codec_init(void) 1559static int __init wm8400_codec_init(void)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 060d5d06ba95..265e68c75df8 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -219,7 +219,6 @@ static int wm8510_add_widgets(struct snd_soc_codec *codec)
219 219
220 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 220 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
221 221
222 snd_soc_dapm_new_widgets(codec);
223 return 0; 222 return 0;
224} 223}
225 224
@@ -271,8 +270,8 @@ static void pll_factors(unsigned int target, unsigned int source)
271 pll_div.k = K; 270 pll_div.k = K;
272} 271}
273 272
274static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, 273static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
275 int pll_id, unsigned int freq_in, unsigned int freq_out) 274 int source, unsigned int freq_in, unsigned int freq_out)
276{ 275{
277 struct snd_soc_codec *codec = codec_dai->codec; 276 struct snd_soc_codec *codec = codec_dai->codec;
278 u16 reg; 277 u16 reg;
@@ -604,16 +603,9 @@ static int wm8510_init(struct snd_soc_device *socdev,
604 snd_soc_add_controls(codec, wm8510_snd_controls, 603 snd_soc_add_controls(codec, wm8510_snd_controls,
605 ARRAY_SIZE(wm8510_snd_controls)); 604 ARRAY_SIZE(wm8510_snd_controls));
606 wm8510_add_widgets(codec); 605 wm8510_add_widgets(codec);
607 ret = snd_soc_init_card(socdev); 606
608 if (ret < 0) {
609 printk(KERN_ERR "wm8510: failed to register card\n");
610 goto card_err;
611 }
612 return ret; 607 return ret;
613 608
614card_err:
615 snd_soc_free_pcms(socdev);
616 snd_soc_dapm_free(socdev);
617err: 609err:
618 kfree(codec->reg_cache); 610 kfree(codec->reg_cache);
619 return ret; 611 return ret;
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 25870a4652fb..d3a61d7ea0c5 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -117,7 +117,6 @@ static int wm8523_add_widgets(struct snd_soc_codec *codec)
117 117
118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
119 119
120 snd_soc_dapm_new_widgets(codec);
121 return 0; 120 return 0;
122} 121}
123 122
@@ -448,17 +447,9 @@ static int wm8523_probe(struct platform_device *pdev)
448 snd_soc_add_controls(codec, wm8523_snd_controls, 447 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls)); 448 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec); 449 wm8523_add_widgets(codec);
451 ret = snd_soc_init_card(socdev);
452 if (ret < 0) {
453 dev_err(codec->dev, "failed to register card: %d\n", ret);
454 goto card_err;
455 }
456 450
457 return ret; 451 return ret;
458 452
459card_err:
460 snd_soc_free_pcms(socdev);
461 snd_soc_dapm_free(socdev);
462pcm_err: 453pcm_err:
463 return ret; 454 return ret;
464} 455}
@@ -638,21 +629,6 @@ static __devexit int wm8523_i2c_remove(struct i2c_client *client)
638 return 0; 629 return 0;
639} 630}
640 631
641#ifdef CONFIG_PM
642static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
643{
644 return snd_soc_suspend_device(&i2c->dev);
645}
646
647static int wm8523_i2c_resume(struct i2c_client *i2c)
648{
649 return snd_soc_resume_device(&i2c->dev);
650}
651#else
652#define wm8523_i2c_suspend NULL
653#define wm8523_i2c_resume NULL
654#endif
655
656static const struct i2c_device_id wm8523_i2c_id[] = { 632static const struct i2c_device_id wm8523_i2c_id[] = {
657 { "wm8523", 0 }, 633 { "wm8523", 0 },
658 { } 634 { }
@@ -666,8 +642,6 @@ static struct i2c_driver wm8523_i2c_driver = {
666 }, 642 },
667 .probe = wm8523_i2c_probe, 643 .probe = wm8523_i2c_probe,
668 .remove = __devexit_p(wm8523_i2c_remove), 644 .remove = __devexit_p(wm8523_i2c_remove),
669 .suspend = wm8523_i2c_suspend,
670 .resume = wm8523_i2c_resume,
671 .id_table = wm8523_i2c_id, 645 .id_table = wm8523_i2c_id,
672}; 646};
673#endif 647#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 6bded8c78150..d077df6f5e75 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -315,7 +315,6 @@ static int wm8580_add_widgets(struct snd_soc_codec *codec)
315 315
316 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 316 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
317 317
318 snd_soc_dapm_new_widgets(codec);
319 return 0; 318 return 0;
320} 319}
321 320
@@ -407,8 +406,8 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
407 return 0; 406 return 0;
408} 407}
409 408
410static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, 409static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
411 int pll_id, unsigned int freq_in, unsigned int freq_out) 410 int source, unsigned int freq_in, unsigned int freq_out)
412{ 411{
413 int offset; 412 int offset;
414 struct snd_soc_codec *codec = codec_dai->codec; 413 struct snd_soc_codec *codec = codec_dai->codec;
@@ -800,17 +799,9 @@ static int wm8580_probe(struct platform_device *pdev)
800 snd_soc_add_controls(codec, wm8580_snd_controls, 799 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls)); 800 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec); 801 wm8580_add_widgets(codec);
803 ret = snd_soc_init_card(socdev);
804 if (ret < 0) {
805 dev_err(codec->dev, "failed to register card: %d\n", ret);
806 goto card_err;
807 }
808 802
809 return ret; 803 return ret;
810 804
811card_err:
812 snd_soc_free_pcms(socdev);
813 snd_soc_dapm_free(socdev);
814pcm_err: 805pcm_err:
815 return ret; 806 return ret;
816} 807}
@@ -961,21 +952,6 @@ static int wm8580_i2c_remove(struct i2c_client *client)
961 return 0; 952 return 0;
962} 953}
963 954
964#ifdef CONFIG_PM
965static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
966{
967 return snd_soc_suspend_device(&client->dev);
968}
969
970static int wm8580_i2c_resume(struct i2c_client *client)
971{
972 return snd_soc_resume_device(&client->dev);
973}
974#else
975#define wm8580_i2c_suspend NULL
976#define wm8580_i2c_resume NULL
977#endif
978
979static const struct i2c_device_id wm8580_i2c_id[] = { 955static const struct i2c_device_id wm8580_i2c_id[] = {
980 { "wm8580", 0 }, 956 { "wm8580", 0 },
981 { } 957 { }
@@ -989,8 +965,6 @@ static struct i2c_driver wm8580_i2c_driver = {
989 }, 965 },
990 .probe = wm8580_i2c_probe, 966 .probe = wm8580_i2c_probe,
991 .remove = wm8580_i2c_remove, 967 .remove = wm8580_i2c_remove,
992 .suspend = wm8580_i2c_suspend,
993 .resume = wm8580_i2c_resume,
994 .id_table = wm8580_i2c_id, 968 .id_table = wm8580_i2c_id,
995}; 969};
996#endif 970#endif
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
new file mode 100644
index 000000000000..24a35603bcf7
--- /dev/null
+++ b/sound/soc/codecs/wm8711.c
@@ -0,0 +1,633 @@
1/*
2 * wm8711.c -- WM8711 ALSA SoC Audio driver
3 *
4 * Copyright 2006 Wolfson Microelectronics
5 *
6 * Author: Mike Arthur <linux@wolfsonmicro.com>
7 *
8 * Based on wm8731.c by Richard Purdie
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/tlv.h>
29#include <sound/initval.h>
30
31#include "wm8711.h"
32
33static struct snd_soc_codec *wm8711_codec;
34
35/* codec private data */
36struct wm8711_priv {
37 struct snd_soc_codec codec;
38 u16 reg_cache[WM8711_CACHEREGNUM];
39 unsigned int sysclk;
40};
41
42/*
43 * wm8711 register cache
44 * We can't read the WM8711 register space when we are
45 * using 2 wire for device control, so we cache them instead.
46 * There is no point in caching the reset register
47 */
48static const u16 wm8711_reg[WM8711_CACHEREGNUM] = {
49 0x0079, 0x0079, 0x000a, 0x0008,
50 0x009f, 0x000a, 0x0000, 0x0000
51};
52
53#define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0)
54
55static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
56
57static const struct snd_kcontrol_new wm8711_snd_controls[] = {
58
59SOC_DOUBLE_R_TLV("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V,
60 0, 127, 0, out_tlv),
61SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V,
62 7, 1, 0),
63
64};
65
66/* Output Mixer */
67static const struct snd_kcontrol_new wm8711_output_mixer_controls[] = {
68SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0),
69SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0),
70};
71
72static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = {
73SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1,
74 &wm8711_output_mixer_controls[0],
75 ARRAY_SIZE(wm8711_output_mixer_controls)),
76SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1),
77SND_SOC_DAPM_OUTPUT("LOUT"),
78SND_SOC_DAPM_OUTPUT("LHPOUT"),
79SND_SOC_DAPM_OUTPUT("ROUT"),
80SND_SOC_DAPM_OUTPUT("RHPOUT"),
81};
82
83static const struct snd_soc_dapm_route intercon[] = {
84 /* output mixer */
85 {"Output Mixer", "Line Bypass Switch", "Line Input"},
86 {"Output Mixer", "HiFi Playback Switch", "DAC"},
87
88 /* outputs */
89 {"RHPOUT", NULL, "Output Mixer"},
90 {"ROUT", NULL, "Output Mixer"},
91 {"LHPOUT", NULL, "Output Mixer"},
92 {"LOUT", NULL, "Output Mixer"},
93};
94
95static int wm8711_add_widgets(struct snd_soc_codec *codec)
96{
97 snd_soc_dapm_new_controls(codec, wm8711_dapm_widgets,
98 ARRAY_SIZE(wm8711_dapm_widgets));
99
100 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
101
102 return 0;
103}
104
105struct _coeff_div {
106 u32 mclk;
107 u32 rate;
108 u16 fs;
109 u8 sr:4;
110 u8 bosr:1;
111 u8 usb:1;
112};
113
114/* codec mclk clock divider coefficients */
115static const struct _coeff_div coeff_div[] = {
116 /* 48k */
117 {12288000, 48000, 256, 0x0, 0x0, 0x0},
118 {18432000, 48000, 384, 0x0, 0x1, 0x0},
119 {12000000, 48000, 250, 0x0, 0x0, 0x1},
120
121 /* 32k */
122 {12288000, 32000, 384, 0x6, 0x0, 0x0},
123 {18432000, 32000, 576, 0x6, 0x1, 0x0},
124 {12000000, 32000, 375, 0x6, 0x0, 0x1},
125
126 /* 8k */
127 {12288000, 8000, 1536, 0x3, 0x0, 0x0},
128 {18432000, 8000, 2304, 0x3, 0x1, 0x0},
129 {11289600, 8000, 1408, 0xb, 0x0, 0x0},
130 {16934400, 8000, 2112, 0xb, 0x1, 0x0},
131 {12000000, 8000, 1500, 0x3, 0x0, 0x1},
132
133 /* 96k */
134 {12288000, 96000, 128, 0x7, 0x0, 0x0},
135 {18432000, 96000, 192, 0x7, 0x1, 0x0},
136 {12000000, 96000, 125, 0x7, 0x0, 0x1},
137
138 /* 44.1k */
139 {11289600, 44100, 256, 0x8, 0x0, 0x0},
140 {16934400, 44100, 384, 0x8, 0x1, 0x0},
141 {12000000, 44100, 272, 0x8, 0x1, 0x1},
142
143 /* 88.2k */
144 {11289600, 88200, 128, 0xf, 0x0, 0x0},
145 {16934400, 88200, 192, 0xf, 0x1, 0x0},
146 {12000000, 88200, 136, 0xf, 0x1, 0x1},
147};
148
149static inline int get_coeff(int mclk, int rate)
150{
151 int i;
152
153 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
154 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
155 return i;
156 }
157 return 0;
158}
159
160static int wm8711_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params,
162 struct snd_soc_dai *dai)
163{
164 struct snd_soc_codec *codec = dai->codec;
165 struct wm8711_priv *wm8711 = codec->private_data;
166 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
167 int i = get_coeff(wm8711->sysclk, params_rate(params));
168 u16 srate = (coeff_div[i].sr << 2) |
169 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
170
171 snd_soc_write(codec, WM8711_SRATE, srate);
172
173 /* bit size */
174 switch (params_format(params)) {
175 case SNDRV_PCM_FORMAT_S16_LE:
176 break;
177 case SNDRV_PCM_FORMAT_S20_3LE:
178 iface |= 0x0004;
179 break;
180 case SNDRV_PCM_FORMAT_S24_LE:
181 iface |= 0x0008;
182 break;
183 }
184
185 snd_soc_write(codec, WM8711_IFACE, iface);
186 return 0;
187}
188
189static int wm8711_pcm_prepare(struct snd_pcm_substream *substream,
190 struct snd_soc_dai *dai)
191{
192 struct snd_soc_codec *codec = dai->codec;
193
194 /* set active */
195 snd_soc_write(codec, WM8711_ACTIVE, 0x0001);
196
197 return 0;
198}
199
200static void wm8711_shutdown(struct snd_pcm_substream *substream,
201 struct snd_soc_dai *dai)
202{
203 struct snd_soc_codec *codec = dai->codec;
204
205 /* deactivate */
206 if (!codec->active) {
207 udelay(50);
208 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
209 }
210}
211
212static int wm8711_mute(struct snd_soc_dai *dai, int mute)
213{
214 struct snd_soc_codec *codec = dai->codec;
215 u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7;
216
217 if (mute)
218 snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8);
219 else
220 snd_soc_write(codec, WM8711_APDIGI, mute_reg);
221
222 return 0;
223}
224
225static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai,
226 int clk_id, unsigned int freq, int dir)
227{
228 struct snd_soc_codec *codec = codec_dai->codec;
229 struct wm8711_priv *wm8711 = codec->private_data;
230
231 switch (freq) {
232 case 11289600:
233 case 12000000:
234 case 12288000:
235 case 16934400:
236 case 18432000:
237 wm8711->sysclk = freq;
238 return 0;
239 }
240 return -EINVAL;
241}
242
243static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
244 unsigned int fmt)
245{
246 struct snd_soc_codec *codec = codec_dai->codec;
247 u16 iface = 0;
248
249 /* set master/slave audio interface */
250 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
251 case SND_SOC_DAIFMT_CBM_CFM:
252 iface |= 0x0040;
253 break;
254 case SND_SOC_DAIFMT_CBS_CFS:
255 break;
256 default:
257 return -EINVAL;
258 }
259
260 /* interface format */
261 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
262 case SND_SOC_DAIFMT_I2S:
263 iface |= 0x0002;
264 break;
265 case SND_SOC_DAIFMT_RIGHT_J:
266 break;
267 case SND_SOC_DAIFMT_LEFT_J:
268 iface |= 0x0001;
269 break;
270 case SND_SOC_DAIFMT_DSP_A:
271 iface |= 0x0003;
272 break;
273 case SND_SOC_DAIFMT_DSP_B:
274 iface |= 0x0013;
275 break;
276 default:
277 return -EINVAL;
278 }
279
280 /* clock inversion */
281 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
282 case SND_SOC_DAIFMT_NB_NF:
283 break;
284 case SND_SOC_DAIFMT_IB_IF:
285 iface |= 0x0090;
286 break;
287 case SND_SOC_DAIFMT_IB_NF:
288 iface |= 0x0080;
289 break;
290 case SND_SOC_DAIFMT_NB_IF:
291 iface |= 0x0010;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 /* set iface */
298 snd_soc_write(codec, WM8711_IFACE, iface);
299 return 0;
300}
301
302
303static int wm8711_set_bias_level(struct snd_soc_codec *codec,
304 enum snd_soc_bias_level level)
305{
306 u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f;
307
308 switch (level) {
309 case SND_SOC_BIAS_ON:
310 snd_soc_write(codec, WM8711_PWR, reg);
311 break;
312 case SND_SOC_BIAS_PREPARE:
313 break;
314 case SND_SOC_BIAS_STANDBY:
315 snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
316 break;
317 case SND_SOC_BIAS_OFF:
318 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
319 snd_soc_write(codec, WM8711_PWR, 0xffff);
320 break;
321 }
322 codec->bias_level = level;
323 return 0;
324}
325
326#define WM8711_RATES SNDRV_PCM_RATE_8000_96000
327
328#define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
329 SNDRV_PCM_FMTBIT_S24_LE)
330
331static struct snd_soc_dai_ops wm8711_ops = {
332 .prepare = wm8711_pcm_prepare,
333 .hw_params = wm8711_hw_params,
334 .shutdown = wm8711_shutdown,
335 .digital_mute = wm8711_mute,
336 .set_sysclk = wm8711_set_dai_sysclk,
337 .set_fmt = wm8711_set_dai_fmt,
338};
339
340struct snd_soc_dai wm8711_dai = {
341 .name = "WM8711",
342 .playback = {
343 .stream_name = "Playback",
344 .channels_min = 1,
345 .channels_max = 2,
346 .rates = WM8711_RATES,
347 .formats = WM8711_FORMATS,
348 },
349 .ops = &wm8711_ops,
350};
351EXPORT_SYMBOL_GPL(wm8711_dai);
352
353static int wm8711_suspend(struct platform_device *pdev, pm_message_t state)
354{
355 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
356 struct snd_soc_codec *codec = socdev->card->codec;
357
358 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
359 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
360 return 0;
361}
362
363static int wm8711_resume(struct platform_device *pdev)
364{
365 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
366 struct snd_soc_codec *codec = socdev->card->codec;
367 int i;
368 u8 data[2];
369 u16 *cache = codec->reg_cache;
370
371 /* Sync reg_cache with the hardware */
372 for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
373 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
374 data[1] = cache[i] & 0x00ff;
375 codec->hw_write(codec->control_data, data, 2);
376 }
377 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
378 wm8711_set_bias_level(codec, codec->suspend_bias_level);
379 return 0;
380}
381
382static int wm8711_probe(struct platform_device *pdev)
383{
384 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
385 struct snd_soc_codec *codec;
386 int ret = 0;
387
388 if (wm8711_codec == NULL) {
389 dev_err(&pdev->dev, "Codec device not registered\n");
390 return -ENODEV;
391 }
392
393 socdev->card->codec = wm8711_codec;
394 codec = wm8711_codec;
395
396 /* register pcms */
397 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
398 if (ret < 0) {
399 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
400 goto pcm_err;
401 }
402
403 snd_soc_add_controls(codec, wm8711_snd_controls,
404 ARRAY_SIZE(wm8711_snd_controls));
405 wm8711_add_widgets(codec);
406
407 return ret;
408
409pcm_err:
410 return ret;
411}
412
413/* power down chip */
414static int wm8711_remove(struct platform_device *pdev)
415{
416 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
417
418 snd_soc_free_pcms(socdev);
419 snd_soc_dapm_free(socdev);
420
421 return 0;
422}
423
424struct snd_soc_codec_device soc_codec_dev_wm8711 = {
425 .probe = wm8711_probe,
426 .remove = wm8711_remove,
427 .suspend = wm8711_suspend,
428 .resume = wm8711_resume,
429};
430EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
431
432static int wm8711_register(struct wm8711_priv *wm8711,
433 enum snd_soc_control_type control)
434{
435 int ret;
436 struct snd_soc_codec *codec = &wm8711->codec;
437 u16 reg;
438
439 if (wm8711_codec) {
440 dev_err(codec->dev, "Another WM8711 is registered\n");
441 return -EINVAL;
442 }
443
444 mutex_init(&codec->mutex);
445 INIT_LIST_HEAD(&codec->dapm_widgets);
446 INIT_LIST_HEAD(&codec->dapm_paths);
447
448 codec->private_data = wm8711;
449 codec->name = "WM8711";
450 codec->owner = THIS_MODULE;
451 codec->bias_level = SND_SOC_BIAS_OFF;
452 codec->set_bias_level = wm8711_set_bias_level;
453 codec->dai = &wm8711_dai;
454 codec->num_dai = 1;
455 codec->reg_cache_size = WM8711_CACHEREGNUM;
456 codec->reg_cache = &wm8711->reg_cache;
457
458 memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
459
460 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
461 if (ret < 0) {
462 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
463 goto err;
464 }
465
466 ret = wm8711_reset(codec);
467 if (ret < 0) {
468 dev_err(codec->dev, "Failed to issue reset\n");
469 goto err;
470 }
471
472 wm8711_dai.dev = codec->dev;
473
474 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
475
476 /* Latch the update bits */
477 reg = snd_soc_read(codec, WM8711_LOUT1V);
478 snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
479 reg = snd_soc_read(codec, WM8711_ROUT1V);
480 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
481
482 wm8711_codec = codec;
483
484 ret = snd_soc_register_codec(codec);
485 if (ret != 0) {
486 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
487 goto err;
488 }
489
490 ret = snd_soc_register_dai(&wm8711_dai);
491 if (ret != 0) {
492 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
493 goto err_codec;
494 }
495
496 return 0;
497
498err_codec:
499 snd_soc_unregister_codec(codec);
500err:
501 kfree(wm8711);
502 return ret;
503}
504
505static void wm8711_unregister(struct wm8711_priv *wm8711)
506{
507 wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF);
508 snd_soc_unregister_dai(&wm8711_dai);
509 snd_soc_unregister_codec(&wm8711->codec);
510 kfree(wm8711);
511 wm8711_codec = NULL;
512}
513
514#if defined(CONFIG_SPI_MASTER)
515static int __devinit wm8711_spi_probe(struct spi_device *spi)
516{
517 struct snd_soc_codec *codec;
518 struct wm8711_priv *wm8711;
519
520 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
521 if (wm8711 == NULL)
522 return -ENOMEM;
523
524 codec = &wm8711->codec;
525 codec->control_data = spi;
526 codec->dev = &spi->dev;
527
528 dev_set_drvdata(&spi->dev, wm8711);
529
530 return wm8711_register(wm8711, SND_SOC_SPI);
531}
532
533static int __devexit wm8711_spi_remove(struct spi_device *spi)
534{
535 struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev);
536
537 wm8711_unregister(wm8711);
538
539 return 0;
540}
541
542static struct spi_driver wm8711_spi_driver = {
543 .driver = {
544 .name = "wm8711",
545 .bus = &spi_bus_type,
546 .owner = THIS_MODULE,
547 },
548 .probe = wm8711_spi_probe,
549 .remove = __devexit_p(wm8711_spi_remove),
550};
551#endif /* CONFIG_SPI_MASTER */
552
553#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
554static __devinit int wm8711_i2c_probe(struct i2c_client *i2c,
555 const struct i2c_device_id *id)
556{
557 struct wm8711_priv *wm8711;
558 struct snd_soc_codec *codec;
559
560 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
561 if (wm8711 == NULL)
562 return -ENOMEM;
563
564 codec = &wm8711->codec;
565 codec->hw_write = (hw_write_t)i2c_master_send;
566
567 i2c_set_clientdata(i2c, wm8711);
568 codec->control_data = i2c;
569
570 codec->dev = &i2c->dev;
571
572 return wm8711_register(wm8711, SND_SOC_I2C);
573}
574
575static __devexit int wm8711_i2c_remove(struct i2c_client *client)
576{
577 struct wm8711_priv *wm8711 = i2c_get_clientdata(client);
578 wm8711_unregister(wm8711);
579 return 0;
580}
581
582static const struct i2c_device_id wm8711_i2c_id[] = {
583 { "wm8711", 0 },
584 { }
585};
586MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
587
588static struct i2c_driver wm8711_i2c_driver = {
589 .driver = {
590 .name = "WM8711 I2C Codec",
591 .owner = THIS_MODULE,
592 },
593 .probe = wm8711_i2c_probe,
594 .remove = __devexit_p(wm8711_i2c_remove),
595 .id_table = wm8711_i2c_id,
596};
597#endif
598
599static int __init wm8711_modinit(void)
600{
601 int ret;
602#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
603 ret = i2c_add_driver(&wm8711_i2c_driver);
604 if (ret != 0) {
605 printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n",
606 ret);
607 }
608#endif
609#if defined(CONFIG_SPI_MASTER)
610 ret = spi_register_driver(&wm8711_spi_driver);
611 if (ret != 0) {
612 printk(KERN_ERR "Failed to register WM8711 SPI driver: %d\n",
613 ret);
614 }
615#endif
616 return 0;
617}
618module_init(wm8711_modinit);
619
620static void __exit wm8711_exit(void)
621{
622#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
623 i2c_del_driver(&wm8711_i2c_driver);
624#endif
625#if defined(CONFIG_SPI_MASTER)
626 spi_unregister_driver(&wm8711_spi_driver);
627#endif
628}
629module_exit(wm8711_exit);
630
631MODULE_DESCRIPTION("ASoC WM8711 driver");
632MODULE_AUTHOR("Mike Arthur");
633MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h
new file mode 100644
index 000000000000..381e84a43816
--- /dev/null
+++ b/sound/soc/codecs/wm8711.h
@@ -0,0 +1,42 @@
1/*
2 * wm8711.h -- WM8711 Soc Audio driver
3 *
4 * Copyright 2006 Wolfson Microelectronics
5 *
6 * Author: Mike Arthur <linux@wolfsonmicro.com>
7 *
8 * Based on wm8731.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _WM8711_H
16#define _WM8711_H
17
18/* WM8711 register space */
19
20#define WM8711_LOUT1V 0x02
21#define WM8711_ROUT1V 0x03
22#define WM8711_APANA 0x04
23#define WM8711_APDIGI 0x05
24#define WM8711_PWR 0x06
25#define WM8711_IFACE 0x07
26#define WM8711_SRATE 0x08
27#define WM8711_ACTIVE 0x09
28#define WM8711_RESET 0x0f
29
30#define WM8711_CACHEREGNUM 8
31
32#define WM8711_SYSCLK 0
33#define WM8711_DAI 0
34
35struct wm8711_setup_data {
36 unsigned short i2c_address;
37};
38
39extern struct snd_soc_dai wm8711_dai;
40extern struct snd_soc_codec_device soc_codec_dev_wm8711;
41
42#endif
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
new file mode 100644
index 000000000000..d8ffbd641d71
--- /dev/null
+++ b/sound/soc/codecs/wm8727.c
@@ -0,0 +1,135 @@
1/*
2 * wm8727.c
3 *
4 * Created on: 15-Oct-2009
5 * Author: neil.jones@imgtec.com
6 *
7 * Copyright (C) 2009 Imagination Technologies Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/ac97_codec.h>
22#include <sound/initval.h>
23#include <sound/soc.h>
24
25#include "wm8727.h"
26/*
27 * Note this is a simple chip with no configuration interface, sample rate is
28 * determined automatically by examining the Master clock and Bit clock ratios
29 */
30#define WM8727_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
31 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\
32 SNDRV_PCM_RATE_192000)
33
34
35struct snd_soc_dai wm8727_dai = {
36 .name = "WM8727",
37 .playback = {
38 .stream_name = "Playback",
39 .channels_min = 2,
40 .channels_max = 2,
41 .rates = WM8727_RATES,
42 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
43 },
44};
45EXPORT_SYMBOL_GPL(wm8727_dai);
46
47static int wm8727_soc_probe(struct platform_device *pdev)
48{
49 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
50 struct snd_soc_codec *codec;
51 int ret = 0;
52
53 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
54 if (codec == NULL)
55 return -ENOMEM;
56 mutex_init(&codec->mutex);
57 codec->name = "WM8727";
58 codec->owner = THIS_MODULE;
59 codec->dai = &wm8727_dai;
60 codec->num_dai = 1;
61 socdev->card->codec = codec;
62 INIT_LIST_HEAD(&codec->dapm_widgets);
63 INIT_LIST_HEAD(&codec->dapm_paths);
64
65 /* register pcms */
66 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
67 if (ret < 0) {
68 printk(KERN_ERR "wm8727: failed to create pcms\n");
69 goto pcm_err;
70 }
71
72 return ret;
73
74pcm_err:
75 kfree(socdev->card->codec);
76 socdev->card->codec = NULL;
77 return ret;
78}
79
80static int wm8727_soc_remove(struct platform_device *pdev)
81{
82 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
83 struct snd_soc_codec *codec = socdev->card->codec;
84
85 if (codec == NULL)
86 return 0;
87 snd_soc_free_pcms(socdev);
88 kfree(codec);
89 return 0;
90}
91
92struct snd_soc_codec_device soc_codec_dev_wm8727 = {
93 .probe = wm8727_soc_probe,
94 .remove = wm8727_soc_remove,
95};
96EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727);
97
98
99static __devinit int wm8727_platform_probe(struct platform_device *pdev)
100{
101 wm8727_dai.dev = &pdev->dev;
102 return snd_soc_register_dai(&wm8727_dai);
103}
104
105static int __devexit wm8727_platform_remove(struct platform_device *pdev)
106{
107 snd_soc_unregister_dai(&wm8727_dai);
108 return 0;
109}
110
111static struct platform_driver wm8727_codec_driver = {
112 .driver = {
113 .name = "wm8727-codec",
114 .owner = THIS_MODULE,
115 },
116
117 .probe = wm8727_platform_probe,
118 .remove = __devexit_p(wm8727_platform_remove),
119};
120
121static int __init wm8727_init(void)
122{
123 return platform_driver_register(&wm8727_codec_driver);
124}
125module_init(wm8727_init);
126
127static void __exit wm8727_exit(void)
128{
129 platform_driver_unregister(&wm8727_codec_driver);
130}
131module_exit(wm8727_exit);
132
133MODULE_DESCRIPTION("ASoC wm8727 driver");
134MODULE_AUTHOR("Neil Jones");
135MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h
new file mode 100644
index 000000000000..ee19aa71bcdc
--- /dev/null
+++ b/sound/soc/codecs/wm8727.h
@@ -0,0 +1,21 @@
1/*
2 * wm8727.h
3 *
4 * Created on: 15-Oct-2009
5 * Author: neil.jones@imgtec.com
6 *
7 * Copyright (C) 2009 Imagination Technologies Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#ifndef WM8727_H_
16#define WM8727_H_
17
18extern struct snd_soc_dai wm8727_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8727;
20
21#endif /* WM8727_H_ */
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 16e969a762c3..3fb653ba363a 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -74,8 +74,6 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
74 74
75 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 75 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
76 76
77 snd_soc_dapm_new_widgets(codec);
78
79 return 0; 77 return 0;
80} 78}
81 79
@@ -287,17 +285,9 @@ static int wm8728_init(struct snd_soc_device *socdev,
287 snd_soc_add_controls(codec, wm8728_snd_controls, 285 snd_soc_add_controls(codec, wm8728_snd_controls,
288 ARRAY_SIZE(wm8728_snd_controls)); 286 ARRAY_SIZE(wm8728_snd_controls));
289 wm8728_add_widgets(codec); 287 wm8728_add_widgets(codec);
290 ret = snd_soc_init_card(socdev);
291 if (ret < 0) {
292 printk(KERN_ERR "wm8728: failed to register card\n");
293 goto card_err;
294 }
295 288
296 return ret; 289 return ret;
297 290
298card_err:
299 snd_soc_free_pcms(socdev);
300 snd_soc_dapm_free(socdev);
301err: 291err:
302 kfree(codec->reg_cache); 292 kfree(codec->reg_cache);
303 return ret; 293 return ret;
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d3fd4f28d96e..3a497810f939 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/regulator/consumer.h>
22#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -33,9 +34,18 @@
33static struct snd_soc_codec *wm8731_codec; 34static struct snd_soc_codec *wm8731_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8731; 35struct snd_soc_codec_device soc_codec_dev_wm8731;
35 36
37#define WM8731_NUM_SUPPLIES 4
38static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
39 "AVDD",
40 "HPVDD",
41 "DCVDD",
42 "DBVDD",
43};
44
36/* codec private data */ 45/* codec private data */
37struct wm8731_priv { 46struct wm8731_priv {
38 struct snd_soc_codec codec; 47 struct snd_soc_codec codec;
48 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
39 u16 reg_cache[WM8731_CACHEREGNUM]; 49 u16 reg_cache[WM8731_CACHEREGNUM];
40 unsigned int sysclk; 50 unsigned int sysclk;
41}; 51};
@@ -149,7 +159,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
149 159
150 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 160 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
151 161
152 snd_soc_dapm_new_widgets(codec);
153 return 0; 162 return 0;
154} 163}
155 164
@@ -422,9 +431,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
422{ 431{
423 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 432 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
424 struct snd_soc_codec *codec = socdev->card->codec; 433 struct snd_soc_codec *codec = socdev->card->codec;
434 struct wm8731_priv *wm8731 = codec->private_data;
425 435
426 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 436 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 437 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
438 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
439 wm8731->supplies);
428 return 0; 440 return 0;
429} 441}
430 442
@@ -432,10 +444,16 @@ static int wm8731_resume(struct platform_device *pdev)
432{ 444{
433 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 445 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
434 struct snd_soc_codec *codec = socdev->card->codec; 446 struct snd_soc_codec *codec = socdev->card->codec;
435 int i; 447 struct wm8731_priv *wm8731 = codec->private_data;
448 int i, ret;
436 u8 data[2]; 449 u8 data[2];
437 u16 *cache = codec->reg_cache; 450 u16 *cache = codec->reg_cache;
438 451
452 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
453 wm8731->supplies);
454 if (ret != 0)
455 return ret;
456
439 /* Sync reg_cache with the hardware */ 457 /* Sync reg_cache with the hardware */
440 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { 458 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
441 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 459 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
@@ -444,6 +462,7 @@ static int wm8731_resume(struct platform_device *pdev)
444 } 462 }
445 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 463 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
446 wm8731_set_bias_level(codec, codec->suspend_bias_level); 464 wm8731_set_bias_level(codec, codec->suspend_bias_level);
465
447 return 0; 466 return 0;
448} 467}
449#else 468#else
@@ -475,17 +494,9 @@ static int wm8731_probe(struct platform_device *pdev)
475 snd_soc_add_controls(codec, wm8731_snd_controls, 494 snd_soc_add_controls(codec, wm8731_snd_controls,
476 ARRAY_SIZE(wm8731_snd_controls)); 495 ARRAY_SIZE(wm8731_snd_controls));
477 wm8731_add_widgets(codec); 496 wm8731_add_widgets(codec);
478 ret = snd_soc_init_card(socdev);
479 if (ret < 0) {
480 dev_err(codec->dev, "failed to register card: %d\n", ret);
481 goto card_err;
482 }
483 497
484 return ret; 498 return ret;
485 499
486card_err:
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489pcm_err: 500pcm_err:
490 return ret; 501 return ret;
491} 502}
@@ -512,7 +523,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
512static int wm8731_register(struct wm8731_priv *wm8731, 523static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control) 524 enum snd_soc_control_type control)
514{ 525{
515 int ret; 526 int ret, i;
516 struct snd_soc_codec *codec = &wm8731->codec; 527 struct snd_soc_codec *codec = &wm8731->codec;
517 528
518 if (wm8731_codec) { 529 if (wm8731_codec) {
@@ -543,10 +554,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
543 goto err; 554 goto err;
544 } 555 }
545 556
557 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
558 wm8731->supplies[i].supply = wm8731_supply_names[i];
559
560 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
561 wm8731->supplies);
562 if (ret != 0) {
563 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
564 goto err;
565 }
566
567 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
568 wm8731->supplies);
569 if (ret != 0) {
570 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
571 goto err_regulator_get;
572 }
573
546 ret = wm8731_reset(codec); 574 ret = wm8731_reset(codec);
547 if (ret < 0) { 575 if (ret < 0) {
548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 576 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
549 goto err; 577 goto err_regulator_enable;
550 } 578 }
551 579
552 wm8731_dai.dev = codec->dev; 580 wm8731_dai.dev = codec->dev;
@@ -567,7 +595,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
567 ret = snd_soc_register_codec(codec); 595 ret = snd_soc_register_codec(codec);
568 if (ret != 0) { 596 if (ret != 0) {
569 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 597 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
570 goto err; 598 goto err_regulator_enable;
571 } 599 }
572 600
573 ret = snd_soc_register_dai(&wm8731_dai); 601 ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +609,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
581 609
582err_codec: 610err_codec:
583 snd_soc_unregister_codec(codec); 611 snd_soc_unregister_codec(codec);
612err_regulator_enable:
613 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
614err_regulator_get:
615 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
584err: 616err:
585 kfree(wm8731); 617 kfree(wm8731);
586 return ret; 618 return ret;
@@ -591,6 +623,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
591 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 623 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
592 snd_soc_unregister_dai(&wm8731_dai); 624 snd_soc_unregister_dai(&wm8731_dai);
593 snd_soc_unregister_codec(&wm8731->codec); 625 snd_soc_unregister_codec(&wm8731->codec);
626 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
627 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
594 kfree(wm8731); 628 kfree(wm8731);
595 wm8731_codec = NULL; 629 wm8731_codec = NULL;
596} 630}
@@ -623,21 +657,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
623 return 0; 657 return 0;
624} 658}
625 659
626#ifdef CONFIG_PM
627static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
628{
629 return snd_soc_suspend_device(&spi->dev);
630}
631
632static int wm8731_spi_resume(struct spi_device *spi)
633{
634 return snd_soc_resume_device(&spi->dev);
635}
636#else
637#define wm8731_spi_suspend NULL
638#define wm8731_spi_resume NULL
639#endif
640
641static struct spi_driver wm8731_spi_driver = { 660static struct spi_driver wm8731_spi_driver = {
642 .driver = { 661 .driver = {
643 .name = "wm8731", 662 .name = "wm8731",
@@ -645,8 +664,6 @@ static struct spi_driver wm8731_spi_driver = {
645 .owner = THIS_MODULE, 664 .owner = THIS_MODULE,
646 }, 665 },
647 .probe = wm8731_spi_probe, 666 .probe = wm8731_spi_probe,
648 .suspend = wm8731_spi_suspend,
649 .resume = wm8731_spi_resume,
650 .remove = __devexit_p(wm8731_spi_remove), 667 .remove = __devexit_p(wm8731_spi_remove),
651}; 668};
652#endif /* CONFIG_SPI_MASTER */ 669#endif /* CONFIG_SPI_MASTER */
@@ -679,21 +696,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
679 return 0; 696 return 0;
680} 697}
681 698
682#ifdef CONFIG_PM
683static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
684{
685 return snd_soc_suspend_device(&i2c->dev);
686}
687
688static int wm8731_i2c_resume(struct i2c_client *i2c)
689{
690 return snd_soc_resume_device(&i2c->dev);
691}
692#else
693#define wm8731_i2c_suspend NULL
694#define wm8731_i2c_resume NULL
695#endif
696
697static const struct i2c_device_id wm8731_i2c_id[] = { 699static const struct i2c_device_id wm8731_i2c_id[] = {
698 { "wm8731", 0 }, 700 { "wm8731", 0 },
699 { } 701 { }
@@ -707,8 +709,6 @@ static struct i2c_driver wm8731_i2c_driver = {
707 }, 709 },
708 .probe = wm8731_i2c_probe, 710 .probe = wm8731_i2c_probe,
709 .remove = __devexit_p(wm8731_i2c_remove), 711 .remove = __devexit_p(wm8731_i2c_remove),
710 .suspend = wm8731_i2c_suspend,
711 .resume = wm8731_i2c_resume,
712 .id_table = wm8731_i2c_id, 712 .id_table = wm8731_i2c_id,
713}; 713};
714#endif 714#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 4ba1e7e93fb4..475c67ac7818 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -403,7 +403,6 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
403 403
404 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 404 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
405 405
406 snd_soc_dapm_new_widgets(codec);
407 return 0; 406 return 0;
408} 407}
409 408
@@ -772,16 +771,8 @@ static int wm8750_init(struct snd_soc_device *socdev,
772 snd_soc_add_controls(codec, wm8750_snd_controls, 771 snd_soc_add_controls(codec, wm8750_snd_controls,
773 ARRAY_SIZE(wm8750_snd_controls)); 772 ARRAY_SIZE(wm8750_snd_controls));
774 wm8750_add_widgets(codec); 773 wm8750_add_widgets(codec);
775 ret = snd_soc_init_card(socdev);
776 if (ret < 0) {
777 printk(KERN_ERR "wm8750: failed to register card\n");
778 goto card_err;
779 }
780 return ret; 774 return ret;
781 775
782card_err:
783 snd_soc_free_pcms(socdev);
784 snd_soc_dapm_free(socdev);
785err: 776err:
786 kfree(codec->reg_cache); 777 kfree(codec->reg_cache);
787 return ret; 778 return ret;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 5ad677ce80da..d6850dacda29 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -673,7 +673,6 @@ static int wm8753_add_widgets(struct snd_soc_codec *codec)
673 673
674 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 674 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
675 675
676 snd_soc_dapm_new_widgets(codec);
677 return 0; 676 return 0;
678} 677}
679 678
@@ -724,8 +723,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
724 pll_div->k = K; 723 pll_div->k = K;
725} 724}
726 725
727static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, 726static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
728 int pll_id, unsigned int freq_in, unsigned int freq_out) 727 int source, unsigned int freq_in, unsigned int freq_out)
729{ 728{
730 u16 reg, enable; 729 u16 reg, enable;
731 int offset; 730 int offset;
@@ -1583,18 +1582,9 @@ static int wm8753_probe(struct platform_device *pdev)
1583 snd_soc_add_controls(codec, wm8753_snd_controls, 1582 snd_soc_add_controls(codec, wm8753_snd_controls,
1584 ARRAY_SIZE(wm8753_snd_controls)); 1583 ARRAY_SIZE(wm8753_snd_controls));
1585 wm8753_add_widgets(codec); 1584 wm8753_add_widgets(codec);
1586 ret = snd_soc_init_card(socdev);
1587 if (ret < 0) {
1588 printk(KERN_ERR "wm8753: failed to register card\n");
1589 goto card_err;
1590 }
1591 1585
1592 return 0; 1586 return 0;
1593 1587
1594card_err:
1595 snd_soc_free_pcms(socdev);
1596 snd_soc_dapm_free(socdev);
1597
1598pcm_err: 1588pcm_err:
1599 return ret; 1589 return ret;
1600} 1590}
@@ -1767,21 +1757,6 @@ static int wm8753_i2c_remove(struct i2c_client *client)
1767 return 0; 1757 return 0;
1768} 1758}
1769 1759
1770#ifdef CONFIG_PM
1771static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1772{
1773 return snd_soc_suspend_device(&client->dev);
1774}
1775
1776static int wm8753_i2c_resume(struct i2c_client *client)
1777{
1778 return snd_soc_resume_device(&client->dev);
1779}
1780#else
1781#define wm8753_i2c_suspend NULL
1782#define wm8753_i2c_resume NULL
1783#endif
1784
1785static const struct i2c_device_id wm8753_i2c_id[] = { 1760static const struct i2c_device_id wm8753_i2c_id[] = {
1786 { "wm8753", 0 }, 1761 { "wm8753", 0 },
1787 { } 1762 { }
@@ -1795,8 +1770,6 @@ static struct i2c_driver wm8753_i2c_driver = {
1795 }, 1770 },
1796 .probe = wm8753_i2c_probe, 1771 .probe = wm8753_i2c_probe,
1797 .remove = wm8753_i2c_remove, 1772 .remove = wm8753_i2c_remove,
1798 .suspend = wm8753_i2c_suspend,
1799 .resume = wm8753_i2c_resume,
1800 .id_table = wm8753_i2c_id, 1773 .id_table = wm8753_i2c_id,
1801}; 1774};
1802#endif 1775#endif
@@ -1852,22 +1825,6 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
1852 return 0; 1825 return 0;
1853} 1826}
1854 1827
1855#ifdef CONFIG_PM
1856static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
1857{
1858 return snd_soc_suspend_device(&spi->dev);
1859}
1860
1861static int wm8753_spi_resume(struct spi_device *spi)
1862{
1863 return snd_soc_resume_device(&spi->dev);
1864}
1865
1866#else
1867#define wm8753_spi_suspend NULL
1868#define wm8753_spi_resume NULL
1869#endif
1870
1871static struct spi_driver wm8753_spi_driver = { 1828static struct spi_driver wm8753_spi_driver = {
1872 .driver = { 1829 .driver = {
1873 .name = "wm8753", 1830 .name = "wm8753",
@@ -1876,8 +1833,6 @@ static struct spi_driver wm8753_spi_driver = {
1876 }, 1833 },
1877 .probe = wm8753_spi_probe, 1834 .probe = wm8753_spi_probe,
1878 .remove = __devexit_p(wm8753_spi_remove), 1835 .remove = __devexit_p(wm8753_spi_remove),
1879 .suspend = wm8753_spi_suspend,
1880 .resume = wm8753_spi_resume,
1881}; 1836};
1882#endif 1837#endif
1883 1838
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index a9829aa26e53..ab2c0da18091 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -447,17 +447,8 @@ static int wm8776_probe(struct platform_device *pdev)
447 ARRAY_SIZE(wm8776_dapm_widgets)); 447 ARRAY_SIZE(wm8776_dapm_widgets));
448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); 448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
449 449
450 ret = snd_soc_init_card(socdev);
451 if (ret < 0) {
452 dev_err(codec->dev, "failed to register card: %d\n", ret);
453 goto card_err;
454 }
455
456 return ret; 450 return ret;
457 451
458card_err:
459 snd_soc_free_pcms(socdev);
460 snd_soc_dapm_free(socdev);
461pcm_err: 452pcm_err:
462 return ret; 453 return ret;
463} 454}
@@ -616,21 +607,6 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi)
616 return 0; 607 return 0;
617} 608}
618 609
619#ifdef CONFIG_PM
620static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
621{
622 return snd_soc_suspend_device(&spi->dev);
623}
624
625static int wm8776_spi_resume(struct spi_device *spi)
626{
627 return snd_soc_resume_device(&spi->dev);
628}
629#else
630#define wm8776_spi_suspend NULL
631#define wm8776_spi_resume NULL
632#endif
633
634static struct spi_driver wm8776_spi_driver = { 610static struct spi_driver wm8776_spi_driver = {
635 .driver = { 611 .driver = {
636 .name = "wm8776", 612 .name = "wm8776",
@@ -638,8 +614,6 @@ static struct spi_driver wm8776_spi_driver = {
638 .owner = THIS_MODULE, 614 .owner = THIS_MODULE,
639 }, 615 },
640 .probe = wm8776_spi_probe, 616 .probe = wm8776_spi_probe,
641 .suspend = wm8776_spi_suspend,
642 .resume = wm8776_spi_resume,
643 .remove = __devexit_p(wm8776_spi_remove), 617 .remove = __devexit_p(wm8776_spi_remove),
644}; 618};
645#endif /* CONFIG_SPI_MASTER */ 619#endif /* CONFIG_SPI_MASTER */
@@ -673,21 +647,6 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client)
673 return 0; 647 return 0;
674} 648}
675 649
676#ifdef CONFIG_PM
677static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
678{
679 return snd_soc_suspend_device(&i2c->dev);
680}
681
682static int wm8776_i2c_resume(struct i2c_client *i2c)
683{
684 return snd_soc_resume_device(&i2c->dev);
685}
686#else
687#define wm8776_i2c_suspend NULL
688#define wm8776_i2c_resume NULL
689#endif
690
691static const struct i2c_device_id wm8776_i2c_id[] = { 650static const struct i2c_device_id wm8776_i2c_id[] = {
692 { "wm8776", 0 }, 651 { "wm8776", 0 },
693 { } 652 { }
@@ -701,8 +660,6 @@ static struct i2c_driver wm8776_i2c_driver = {
701 }, 660 },
702 .probe = wm8776_i2c_probe, 661 .probe = wm8776_i2c_probe,
703 .remove = __devexit_p(wm8776_i2c_remove), 662 .remove = __devexit_p(wm8776_i2c_remove),
704 .suspend = wm8776_i2c_suspend,
705 .resume = wm8776_i2c_resume,
706 .id_table = wm8776_i2c_id, 663 .id_table = wm8776_i2c_id,
707}; 664};
708#endif 665#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 5e9c855c0036..c9438dd62df3 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -618,8 +618,6 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
618 618
619 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 619 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
620 620
621 snd_soc_dapm_new_widgets(codec);
622
623 return 0; 621 return 0;
624} 622}
625 623
@@ -814,8 +812,8 @@ reenable:
814 return 0; 812 return 0;
815} 813}
816 814
817static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, 815static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
818 int pll_id, unsigned int freq_in, unsigned int freq_out) 816 int source, unsigned int freq_in, unsigned int freq_out)
819{ 817{
820 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); 818 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
821} 819}
@@ -1312,21 +1310,6 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1312 return 0; 1310 return 0;
1313} 1311}
1314 1312
1315#ifdef CONFIG_PM
1316static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1317{
1318 return snd_soc_suspend_device(&client->dev);
1319}
1320
1321static int wm8900_i2c_resume(struct i2c_client *client)
1322{
1323 return snd_soc_resume_device(&client->dev);
1324}
1325#else
1326#define wm8900_i2c_suspend NULL
1327#define wm8900_i2c_resume NULL
1328#endif
1329
1330static const struct i2c_device_id wm8900_i2c_id[] = { 1313static const struct i2c_device_id wm8900_i2c_id[] = {
1331 { "wm8900", 0 }, 1314 { "wm8900", 0 },
1332 { } 1315 { }
@@ -1340,8 +1323,6 @@ static struct i2c_driver wm8900_i2c_driver = {
1340 }, 1323 },
1341 .probe = wm8900_i2c_probe, 1324 .probe = wm8900_i2c_probe,
1342 .remove = __devexit_p(wm8900_i2c_remove), 1325 .remove = __devexit_p(wm8900_i2c_remove),
1343 .suspend = wm8900_i2c_suspend,
1344 .resume = wm8900_i2c_resume,
1345 .id_table = wm8900_i2c_id, 1326 .id_table = wm8900_i2c_id,
1346}; 1327};
1347 1328
@@ -1370,17 +1351,6 @@ static int wm8900_probe(struct platform_device *pdev)
1370 ARRAY_SIZE(wm8900_snd_controls)); 1351 ARRAY_SIZE(wm8900_snd_controls));
1371 wm8900_add_widgets(codec); 1352 wm8900_add_widgets(codec);
1372 1353
1373 ret = snd_soc_init_card(socdev);
1374 if (ret < 0) {
1375 dev_err(&pdev->dev, "Failed to register card\n");
1376 goto card_err;
1377 }
1378
1379 return ret;
1380
1381card_err:
1382 snd_soc_free_pcms(socdev);
1383 snd_soc_dapm_free(socdev);
1384pcm_err: 1354pcm_err:
1385 return ret; 1355 return ret;
1386} 1356}
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index fe1307b500cf..b8cae1758642 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -919,8 +919,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
919 919
920 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 920 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
921 921
922 snd_soc_dapm_new_widgets(codec);
923
924 return 0; 922 return 0;
925} 923}
926 924
@@ -1655,21 +1653,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1655 return 0; 1653 return 0;
1656} 1654}
1657 1655
1658#ifdef CONFIG_PM
1659static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1660{
1661 return snd_soc_suspend_device(&client->dev);
1662}
1663
1664static int wm8903_i2c_resume(struct i2c_client *client)
1665{
1666 return snd_soc_resume_device(&client->dev);
1667}
1668#else
1669#define wm8903_i2c_suspend NULL
1670#define wm8903_i2c_resume NULL
1671#endif
1672
1673/* i2c codec control layer */ 1656/* i2c codec control layer */
1674static const struct i2c_device_id wm8903_i2c_id[] = { 1657static const struct i2c_device_id wm8903_i2c_id[] = {
1675 { "wm8903", 0 }, 1658 { "wm8903", 0 },
@@ -1684,8 +1667,6 @@ static struct i2c_driver wm8903_i2c_driver = {
1684 }, 1667 },
1685 .probe = wm8903_i2c_probe, 1668 .probe = wm8903_i2c_probe,
1686 .remove = __devexit_p(wm8903_i2c_remove), 1669 .remove = __devexit_p(wm8903_i2c_remove),
1687 .suspend = wm8903_i2c_suspend,
1688 .resume = wm8903_i2c_resume,
1689 .id_table = wm8903_i2c_id, 1670 .id_table = wm8903_i2c_id,
1690}; 1671};
1691 1672
@@ -1712,17 +1693,8 @@ static int wm8903_probe(struct platform_device *pdev)
1712 ARRAY_SIZE(wm8903_snd_controls)); 1693 ARRAY_SIZE(wm8903_snd_controls));
1713 wm8903_add_widgets(socdev->card->codec); 1694 wm8903_add_widgets(socdev->card->codec);
1714 1695
1715 ret = snd_soc_init_card(socdev);
1716 if (ret < 0) {
1717 dev_err(&pdev->dev, "wm8903: failed to register card\n");
1718 goto card_err;
1719 }
1720
1721 return ret; 1696 return ret;
1722 1697
1723card_err:
1724 snd_soc_free_pcms(socdev);
1725 snd_soc_dapm_free(socdev);
1726err: 1698err:
1727 return ret; 1699 return ret;
1728} 1700}
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 1ef2454c5205..3d850b97037a 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -298,7 +298,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec)
298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
299 if (ret) 299 if (ret)
300 goto error_ret; 300 goto error_ret;
301 ret = snd_soc_dapm_new_widgets(codec);
302 301
303error_ret: 302error_ret:
304 return ret; 303 return ret;
@@ -536,8 +535,8 @@ static void pll_factors(unsigned int target, unsigned int source)
536} 535}
537 536
538/* Untested at the moment */ 537/* Untested at the moment */
539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, 538static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
540 int pll_id, unsigned int freq_in, unsigned int freq_out) 539 int source, unsigned int freq_in, unsigned int freq_out)
541{ 540{
542 struct snd_soc_codec *codec = codec_dai->codec; 541 struct snd_soc_codec *codec = codec_dai->codec;
543 u16 reg; 542 u16 reg;
@@ -731,12 +730,6 @@ static int wm8940_probe(struct platform_device *pdev)
731 if (ret) 730 if (ret)
732 goto error_free_pcms; 731 goto error_free_pcms;
733 732
734 ret = snd_soc_init_card(socdev);
735 if (ret < 0) {
736 dev_err(codec->dev, "failed to register card: %d\n", ret);
737 goto error_free_pcms;
738 }
739
740 return ret; 733 return ret;
741 734
742error_free_pcms: 735error_free_pcms:
@@ -877,21 +870,6 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client)
877 return 0; 870 return 0;
878} 871}
879 872
880#ifdef CONFIG_PM
881static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
882{
883 return snd_soc_suspend_device(&client->dev);
884}
885
886static int wm8940_i2c_resume(struct i2c_client *client)
887{
888 return snd_soc_resume_device(&client->dev);
889}
890#else
891#define wm8940_i2c_suspend NULL
892#define wm8940_i2c_resume NULL
893#endif
894
895static const struct i2c_device_id wm8940_i2c_id[] = { 873static const struct i2c_device_id wm8940_i2c_id[] = {
896 { "wm8940", 0 }, 874 { "wm8940", 0 },
897 { } 875 { }
@@ -905,8 +883,6 @@ static struct i2c_driver wm8940_i2c_driver = {
905 }, 883 },
906 .probe = wm8940_i2c_probe, 884 .probe = wm8940_i2c_probe,
907 .remove = __devexit_p(wm8940_i2c_remove), 885 .remove = __devexit_p(wm8940_i2c_remove),
908 .suspend = wm8940_i2c_suspend,
909 .resume = wm8940_i2c_resume,
910 .id_table = wm8940_i2c_id, 886 .id_table = wm8940_i2c_id,
911}; 887};
912 888
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f59703be61c8..d07bcc1e1c60 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -307,7 +307,6 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
307 307
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309 309
310 snd_soc_dapm_new_widgets(codec);
311 return 0; 310 return 0;
312} 311}
313 312
@@ -540,8 +539,8 @@ static int pll_factors(unsigned int source, unsigned int target,
540 return 0; 539 return 0;
541} 540}
542 541
543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, 542static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
544 int pll_id, unsigned int freq_in, unsigned int freq_out) 543 int source, unsigned int freq_in, unsigned int freq_out)
545{ 544{
546 struct snd_soc_codec *codec = codec_dai->codec; 545 struct snd_soc_codec *codec = codec_dai->codec;
547 u16 reg; 546 u16 reg;
@@ -713,17 +712,9 @@ static int wm8960_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, wm8960_snd_controls, 712 snd_soc_add_controls(codec, wm8960_snd_controls,
714 ARRAY_SIZE(wm8960_snd_controls)); 713 ARRAY_SIZE(wm8960_snd_controls));
715 wm8960_add_widgets(codec); 714 wm8960_add_widgets(codec);
716 ret = snd_soc_init_card(socdev);
717 if (ret < 0) {
718 dev_err(codec->dev, "failed to register card: %d\n", ret);
719 goto card_err;
720 }
721 715
722 return ret; 716 return ret;
723 717
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 718pcm_err:
728 return ret; 719 return ret;
729} 720}
@@ -883,21 +874,6 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client)
883 return 0; 874 return 0;
884} 875}
885 876
886#ifdef CONFIG_PM
887static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
888{
889 return snd_soc_suspend_device(&client->dev);
890}
891
892static int wm8960_i2c_resume(struct i2c_client *client)
893{
894 return snd_soc_resume_device(&client->dev);
895}
896#else
897#define wm8960_i2c_suspend NULL
898#define wm8960_i2c_resume NULL
899#endif
900
901static const struct i2c_device_id wm8960_i2c_id[] = { 877static const struct i2c_device_id wm8960_i2c_id[] = {
902 { "wm8960", 0 }, 878 { "wm8960", 0 },
903 { } 879 { }
@@ -911,8 +887,6 @@ static struct i2c_driver wm8960_i2c_driver = {
911 }, 887 },
912 .probe = wm8960_i2c_probe, 888 .probe = wm8960_i2c_probe,
913 .remove = __devexit_p(wm8960_i2c_remove), 889 .remove = __devexit_p(wm8960_i2c_remove),
914 .suspend = wm8960_i2c_suspend,
915 .resume = wm8960_i2c_resume,
916 .id_table = wm8960_i2c_id, 890 .id_table = wm8960_i2c_id,
917}; 891};
918 892
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 503032085899..a8007d58813f 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -986,19 +986,9 @@ static int wm8961_probe(struct platform_device *pdev)
986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, 986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
987 ARRAY_SIZE(wm8961_dapm_widgets)); 987 ARRAY_SIZE(wm8961_dapm_widgets));
988 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 988 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
989 snd_soc_dapm_new_widgets(codec);
990
991 ret = snd_soc_init_card(socdev);
992 if (ret < 0) {
993 dev_err(codec->dev, "failed to register card: %d\n", ret);
994 goto card_err;
995 }
996 989
997 return ret; 990 return ret;
998 991
999card_err:
1000 snd_soc_free_pcms(socdev);
1001 snd_soc_dapm_free(socdev);
1002pcm_err: 992pcm_err:
1003 return ret; 993 return ret;
1004} 994}
@@ -1206,21 +1196,6 @@ static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1206 return 0; 1196 return 0;
1207} 1197}
1208 1198
1209#ifdef CONFIG_PM
1210static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
1211{
1212 return snd_soc_suspend_device(&client->dev);
1213}
1214
1215static int wm8961_i2c_resume(struct i2c_client *client)
1216{
1217 return snd_soc_resume_device(&client->dev);
1218}
1219#else
1220#define wm8961_i2c_suspend NULL
1221#define wm8961_i2c_resume NULL
1222#endif
1223
1224static const struct i2c_device_id wm8961_i2c_id[] = { 1199static const struct i2c_device_id wm8961_i2c_id[] = {
1225 { "wm8961", 0 }, 1200 { "wm8961", 0 },
1226 { } 1201 { }
@@ -1234,8 +1209,6 @@ static struct i2c_driver wm8961_i2c_driver = {
1234 }, 1209 },
1235 .probe = wm8961_i2c_probe, 1210 .probe = wm8961_i2c_probe,
1236 .remove = __devexit_p(wm8961_i2c_remove), 1211 .remove = __devexit_p(wm8961_i2c_remove),
1237 .suspend = wm8961_i2c_suspend,
1238 .resume = wm8961_i2c_resume,
1239 .id_table = wm8961_i2c_id, 1212 .id_table = wm8961_i2c_id,
1240}; 1213};
1241 1214
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index d66efb0546ea..d9540d55fc89 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -338,8 +338,6 @@ static int wm8971_add_widgets(struct snd_soc_codec *codec)
338 338
339 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 339 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
340 340
341 snd_soc_dapm_new_widgets(codec);
342
343 return 0; 341 return 0;
344} 342}
345 343
@@ -703,16 +701,9 @@ static int wm8971_init(struct snd_soc_device *socdev,
703 snd_soc_add_controls(codec, wm8971_snd_controls, 701 snd_soc_add_controls(codec, wm8971_snd_controls,
704 ARRAY_SIZE(wm8971_snd_controls)); 702 ARRAY_SIZE(wm8971_snd_controls));
705 wm8971_add_widgets(codec); 703 wm8971_add_widgets(codec);
706 ret = snd_soc_init_card(socdev); 704
707 if (ret < 0) {
708 printk(KERN_ERR "wm8971: failed to register card\n");
709 goto card_err;
710 }
711 return ret; 705 return ret;
712 706
713card_err:
714 snd_soc_free_pcms(socdev);
715 snd_soc_dapm_free(socdev);
716err: 707err:
717 kfree(codec->reg_cache); 708 kfree(codec->reg_cache);
718 return ret; 709 return ret;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 98d663afc97d..81c57b5c591c 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -276,41 +276,42 @@ static int wm8974_add_widgets(struct snd_soc_codec *codec)
276 276
277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
278 278
279 snd_soc_dapm_new_widgets(codec);
280 return 0; 279 return 0;
281} 280}
282 281
283struct pll_ { 282struct pll_ {
284 unsigned int pre_div:4; /* prescale - 1 */ 283 unsigned int pre_div:1;
285 unsigned int n:4; 284 unsigned int n:4;
286 unsigned int k; 285 unsigned int k;
287}; 286};
288 287
289static struct pll_ pll_div;
290
291/* The size in bits of the pll divide multiplied by 10 288/* The size in bits of the pll divide multiplied by 10
292 * to allow rounding later */ 289 * to allow rounding later */
293#define FIXED_PLL_SIZE ((1 << 24) * 10) 290#define FIXED_PLL_SIZE ((1 << 24) * 10)
294 291
295static void pll_factors(unsigned int target, unsigned int source) 292static void pll_factors(struct pll_ *pll_div,
293 unsigned int target, unsigned int source)
296{ 294{
297 unsigned long long Kpart; 295 unsigned long long Kpart;
298 unsigned int K, Ndiv, Nmod; 296 unsigned int K, Ndiv, Nmod;
299 297
298 /* There is a fixed divide by 4 in the output path */
299 target *= 4;
300
300 Ndiv = target / source; 301 Ndiv = target / source;
301 if (Ndiv < 6) { 302 if (Ndiv < 6) {
302 source >>= 1; 303 source /= 2;
303 pll_div.pre_div = 1; 304 pll_div->pre_div = 1;
304 Ndiv = target / source; 305 Ndiv = target / source;
305 } else 306 } else
306 pll_div.pre_div = 0; 307 pll_div->pre_div = 0;
307 308
308 if ((Ndiv < 6) || (Ndiv > 12)) 309 if ((Ndiv < 6) || (Ndiv > 12))
309 printk(KERN_WARNING 310 printk(KERN_WARNING
310 "WM8974 N value %u outwith recommended range!\n", 311 "WM8974 N value %u outwith recommended range!\n",
311 Ndiv); 312 Ndiv);
312 313
313 pll_div.n = Ndiv; 314 pll_div->n = Ndiv;
314 Nmod = target % source; 315 Nmod = target % source;
315 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 316 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
316 317
@@ -325,13 +326,14 @@ static void pll_factors(unsigned int target, unsigned int source)
325 /* Move down to proper range now rounding is done */ 326 /* Move down to proper range now rounding is done */
326 K /= 10; 327 K /= 10;
327 328
328 pll_div.k = K; 329 pll_div->k = K;
329} 330}
330 331
331static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, 332static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
332 int pll_id, unsigned int freq_in, unsigned int freq_out) 333 int source, unsigned int freq_in, unsigned int freq_out)
333{ 334{
334 struct snd_soc_codec *codec = codec_dai->codec; 335 struct snd_soc_codec *codec = codec_dai->codec;
336 struct pll_ pll_div;
335 u16 reg; 337 u16 reg;
336 338
337 if (freq_in == 0 || freq_out == 0) { 339 if (freq_in == 0 || freq_out == 0) {
@@ -345,7 +347,7 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai,
345 return 0; 347 return 0;
346 } 348 }
347 349
348 pll_factors(freq_out*4, freq_in); 350 pll_factors(&pll_div, freq_out, freq_in);
349 351
350 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); 352 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n);
351 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); 353 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);
@@ -638,17 +640,9 @@ static int wm8974_probe(struct platform_device *pdev)
638 snd_soc_add_controls(codec, wm8974_snd_controls, 640 snd_soc_add_controls(codec, wm8974_snd_controls,
639 ARRAY_SIZE(wm8974_snd_controls)); 641 ARRAY_SIZE(wm8974_snd_controls));
640 wm8974_add_widgets(codec); 642 wm8974_add_widgets(codec);
641 ret = snd_soc_init_card(socdev);
642 if (ret < 0) {
643 dev_err(codec->dev, "failed to register card: %d\n", ret);
644 goto card_err;
645 }
646 643
647 return ret; 644 return ret;
648 645
649card_err:
650 snd_soc_free_pcms(socdev);
651 snd_soc_dapm_free(socdev);
652pcm_err: 646pcm_err:
653 return ret; 647 return ret;
654} 648}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 3f530f8a972a..2862e4dced27 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -790,19 +790,9 @@ static int wm8988_probe(struct platform_device *pdev)
790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, 790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
791 ARRAY_SIZE(wm8988_dapm_widgets)); 791 ARRAY_SIZE(wm8988_dapm_widgets));
792 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 792 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
793 snd_soc_dapm_new_widgets(codec);
794
795 ret = snd_soc_init_card(socdev);
796 if (ret < 0) {
797 dev_err(codec->dev, "failed to register card: %d\n", ret);
798 goto card_err;
799 }
800 793
801 return ret; 794 return ret;
802 795
803card_err:
804 snd_soc_free_pcms(socdev);
805 snd_soc_dapm_free(socdev);
806pcm_err: 796pcm_err:
807 return ret; 797 return ret;
808} 798}
@@ -944,21 +934,6 @@ static int wm8988_i2c_remove(struct i2c_client *client)
944 return 0; 934 return 0;
945} 935}
946 936
947#ifdef CONFIG_PM
948static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
949{
950 return snd_soc_suspend_device(&client->dev);
951}
952
953static int wm8988_i2c_resume(struct i2c_client *client)
954{
955 return snd_soc_resume_device(&client->dev);
956}
957#else
958#define wm8988_i2c_suspend NULL
959#define wm8988_i2c_resume NULL
960#endif
961
962static const struct i2c_device_id wm8988_i2c_id[] = { 937static const struct i2c_device_id wm8988_i2c_id[] = {
963 { "wm8988", 0 }, 938 { "wm8988", 0 },
964 { } 939 { }
@@ -972,8 +947,6 @@ static struct i2c_driver wm8988_i2c_driver = {
972 }, 947 },
973 .probe = wm8988_i2c_probe, 948 .probe = wm8988_i2c_probe,
974 .remove = wm8988_i2c_remove, 949 .remove = wm8988_i2c_remove,
975 .suspend = wm8988_i2c_suspend,
976 .resume = wm8988_i2c_resume,
977 .id_table = wm8988_i2c_id, 950 .id_table = wm8988_i2c_id,
978}; 951};
979#endif 952#endif
@@ -1006,21 +979,6 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
1006 return 0; 979 return 0;
1007} 980}
1008 981
1009#ifdef CONFIG_PM
1010static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1011{
1012 return snd_soc_suspend_device(&spi->dev);
1013}
1014
1015static int wm8988_spi_resume(struct spi_device *spi)
1016{
1017 return snd_soc_resume_device(&spi->dev);
1018}
1019#else
1020#define wm8988_spi_suspend NULL
1021#define wm8988_spi_resume NULL
1022#endif
1023
1024static struct spi_driver wm8988_spi_driver = { 982static struct spi_driver wm8988_spi_driver = {
1025 .driver = { 983 .driver = {
1026 .name = "wm8988", 984 .name = "wm8988",
@@ -1029,8 +987,6 @@ static struct spi_driver wm8988_spi_driver = {
1029 }, 987 },
1030 .probe = wm8988_spi_probe, 988 .probe = wm8988_spi_probe,
1031 .remove = __devexit_p(wm8988_spi_remove), 989 .remove = __devexit_p(wm8988_spi_remove),
1032 .suspend = wm8988_spi_suspend,
1033 .resume = wm8988_spi_resume,
1034}; 990};
1035#endif 991#endif
1036 992
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 2d702db4131d..341481e0e830 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -920,7 +920,6 @@ static int wm8990_add_widgets(struct snd_soc_codec *codec)
920 /* set up the WM8990 audio map */ 920 /* set up the WM8990 audio map */
921 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 921 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
922 922
923 snd_soc_dapm_new_widgets(codec);
924 return 0; 923 return 0;
925} 924}
926 925
@@ -972,8 +971,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
972 pll_div->k = K; 971 pll_div->k = K;
973} 972}
974 973
975static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, 974static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
976 int pll_id, unsigned int freq_in, unsigned int freq_out) 975 int source, unsigned int freq_in, unsigned int freq_out)
977{ 976{
978 u16 reg; 977 u16 reg;
979 struct snd_soc_codec *codec = codec_dai->codec; 978 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1409,16 +1408,9 @@ static int wm8990_init(struct snd_soc_device *socdev)
1409 snd_soc_add_controls(codec, wm8990_snd_controls, 1408 snd_soc_add_controls(codec, wm8990_snd_controls,
1410 ARRAY_SIZE(wm8990_snd_controls)); 1409 ARRAY_SIZE(wm8990_snd_controls));
1411 wm8990_add_widgets(codec); 1410 wm8990_add_widgets(codec);
1412 ret = snd_soc_init_card(socdev); 1411
1413 if (ret < 0) {
1414 printk(KERN_ERR "wm8990: failed to register card\n");
1415 goto card_err;
1416 }
1417 return ret; 1412 return ret;
1418 1413
1419card_err:
1420 snd_soc_free_pcms(socdev);
1421 snd_soc_dapm_free(socdev);
1422pcm_err: 1414pcm_err:
1423 kfree(codec->reg_cache); 1415 kfree(codec->reg_cache);
1424 return ret; 1416 return ret;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d9987999e92c..5e32f2ed5fc2 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -422,7 +422,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
422 return 0; 422 return 0;
423} 423}
424 424
425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, 425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
426 unsigned int Fref, unsigned int Fout) 426 unsigned int Fref, unsigned int Fout)
427{ 427{
428 struct snd_soc_codec *codec = dai->codec; 428 struct snd_soc_codec *codec = dai->codec;
@@ -1464,19 +1464,8 @@ static int wm8993_probe(struct platform_device *pdev)
1464 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, 1464 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
1465 wm8993->pdata.lineout2_diff); 1465 wm8993->pdata.lineout2_diff);
1466 1466
1467 snd_soc_dapm_new_widgets(codec);
1468
1469 ret = snd_soc_init_card(socdev);
1470 if (ret < 0) {
1471 dev_err(codec->dev, "failed to register card\n");
1472 goto card_err;
1473 }
1474
1475 return ret; 1467 return ret;
1476 1468
1477card_err:
1478 snd_soc_free_pcms(socdev);
1479 snd_soc_dapm_free(socdev);
1480err: 1469err:
1481 return ret; 1470 return ret;
1482} 1471}
@@ -1572,33 +1561,15 @@ static int wm8993_i2c_probe(struct i2c_client *i2c,
1572 /* Use automatic clock configuration */ 1561 /* Use automatic clock configuration */
1573 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); 1562 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1574 1563
1575 if (!wm8993->pdata.lineout1_diff) 1564 wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
1576 snd_soc_update_bits(codec, WM8993_LINE_MIXER1, 1565 wm8993->pdata.lineout2_diff,
1577 WM8993_LINEOUT1_MODE, 1566 wm8993->pdata.lineout1fb,
1578 WM8993_LINEOUT1_MODE); 1567 wm8993->pdata.lineout2fb,
1579 if (!wm8993->pdata.lineout2_diff) 1568 wm8993->pdata.jd_scthr,
1580 snd_soc_update_bits(codec, WM8993_LINE_MIXER2, 1569 wm8993->pdata.jd_thr,
1581 WM8993_LINEOUT2_MODE, 1570 wm8993->pdata.micbias1_lvl,
1582 WM8993_LINEOUT2_MODE); 1571 wm8993->pdata.micbias2_lvl);
1583 1572
1584 if (wm8993->pdata.lineout1fb)
1585 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1586 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1587
1588 if (wm8993->pdata.lineout2fb)
1589 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1590 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1591
1592 /* Apply the microphone bias/detection configuration - the
1593 * platform data is directly applicable to the register. */
1594 snd_soc_update_bits(codec, WM8993_MICBIAS,
1595 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1596 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1597 wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
1598 wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
1599 wm8993->pdata.micbias1_lvl |
1600 wm8993->pdata.micbias1_lvl << 1);
1601
1602 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1573 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1603 if (ret != 0) 1574 if (ret != 0)
1604 goto err; 1575 goto err;
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 686e5aa97206..c468497314ba 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1262,19 +1262,9 @@ static int wm9081_probe(struct platform_device *pdev)
1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets, 1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
1263 ARRAY_SIZE(wm9081_dapm_widgets)); 1263 ARRAY_SIZE(wm9081_dapm_widgets));
1264 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 1264 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1265 snd_soc_dapm_new_widgets(codec);
1266
1267 ret = snd_soc_init_card(socdev);
1268 if (ret < 0) {
1269 dev_err(codec->dev, "failed to register card: %d\n", ret);
1270 goto card_err;
1271 }
1272 1265
1273 return ret; 1266 return ret;
1274 1267
1275card_err:
1276 snd_soc_free_pcms(socdev);
1277 snd_soc_dapm_free(socdev);
1278pcm_err: 1268pcm_err:
1279 return ret; 1269 return ret;
1280} 1270}
@@ -1452,21 +1442,6 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1452 return 0; 1442 return 0;
1453} 1443}
1454 1444
1455#ifdef CONFIG_PM
1456static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1457{
1458 return snd_soc_suspend_device(&client->dev);
1459}
1460
1461static int wm9081_i2c_resume(struct i2c_client *client)
1462{
1463 return snd_soc_resume_device(&client->dev);
1464}
1465#else
1466#define wm9081_i2c_suspend NULL
1467#define wm9081_i2c_resume NULL
1468#endif
1469
1470static const struct i2c_device_id wm9081_i2c_id[] = { 1445static const struct i2c_device_id wm9081_i2c_id[] = {
1471 { "wm9081", 0 }, 1446 { "wm9081", 0 },
1472 { } 1447 { }
@@ -1480,8 +1455,6 @@ static struct i2c_driver wm9081_i2c_driver = {
1480 }, 1455 },
1481 .probe = wm9081_i2c_probe, 1456 .probe = wm9081_i2c_probe,
1482 .remove = __devexit_p(wm9081_i2c_remove), 1457 .remove = __devexit_p(wm9081_i2c_remove),
1483 .suspend = wm9081_i2c_suspend,
1484 .resume = wm9081_i2c_resume,
1485 .id_table = wm9081_i2c_id, 1458 .id_table = wm9081_i2c_id,
1486}; 1459};
1487 1460
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index e7d2840d9e59..ec54c6da9856 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -205,7 +205,6 @@ static int wm9705_add_widgets(struct snd_soc_codec *codec)
205 snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, 205 snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets,
206 ARRAY_SIZE(wm9705_dapm_widgets)); 206 ARRAY_SIZE(wm9705_dapm_widgets));
207 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 207 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
208 snd_soc_dapm_new_widgets(codec);
209 208
210 return 0; 209 return 0;
211} 210}
@@ -403,12 +402,6 @@ static int wm9705_soc_probe(struct platform_device *pdev)
403 ARRAY_SIZE(wm9705_snd_ac97_controls)); 402 ARRAY_SIZE(wm9705_snd_ac97_controls));
404 wm9705_add_widgets(codec); 403 wm9705_add_widgets(codec);
405 404
406 ret = snd_soc_init_card(socdev);
407 if (ret < 0) {
408 printk(KERN_ERR "wm9705: failed to register card\n");
409 goto reset_err;
410 }
411
412 return 0; 405 return 0;
413 406
414reset_err: 407reset_err:
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 1fd4e88f50cf..0ac1215dcd9b 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -436,7 +436,6 @@ static int wm9712_add_widgets(struct snd_soc_codec *codec)
436 436
437 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 437 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
438 438
439 snd_soc_dapm_new_widgets(codec);
440 return 0; 439 return 0;
441} 440}
442 441
@@ -695,17 +694,11 @@ static int wm9712_soc_probe(struct platform_device *pdev)
695 snd_soc_add_controls(codec, wm9712_snd_ac97_controls, 694 snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
696 ARRAY_SIZE(wm9712_snd_ac97_controls)); 695 ARRAY_SIZE(wm9712_snd_ac97_controls));
697 wm9712_add_widgets(codec); 696 wm9712_add_widgets(codec);
698 ret = snd_soc_init_card(socdev);
699 if (ret < 0) {
700 printk(KERN_ERR "wm9712: failed to register card\n");
701 goto reset_err;
702 }
703 697
704 return 0; 698 return 0;
705 699
706reset_err: 700reset_err:
707 snd_soc_free_pcms(socdev); 701 snd_soc_free_pcms(socdev);
708
709pcm_err: 702pcm_err:
710 snd_soc_free_ac97_codec(codec); 703 snd_soc_free_ac97_codec(codec);
711 704
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index abed37acf787..c58aab375edb 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -165,9 +165,9 @@ SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
165SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0), 165SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
166SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1), 166SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
167 167
168SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1), 168SOC_SINGLE("Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
169SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1), 169SOC_SINGLE("Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
170SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1), 170SOC_SINGLE("Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
171 171
172SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1), 172SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
173SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1), 173SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
@@ -266,7 +266,7 @@ static int mixer_event(struct snd_soc_dapm_widget *w,
266 266
267/* Left Headphone Mixers */ 267/* Left Headphone Mixers */
268static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { 268static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
269SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0), 269SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0),
270SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), 270SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
271SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), 271SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
272SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), 272SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
@@ -276,7 +276,7 @@ SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
276 276
277/* Right Headphone Mixers */ 277/* Right Headphone Mixers */
278static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { 278static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
279SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0), 279SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0),
280SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), 280SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
281SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), 281SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
282SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), 282SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
@@ -294,7 +294,7 @@ SOC_DAPM_ENUM("Route", wm9713_enum[0]);
294 294
295/* Speaker Mixer */ 295/* Speaker Mixer */
296static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = { 296static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
297SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1), 297SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 11, 1, 1),
298SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1), 298SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
299SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1), 299SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
300SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1), 300SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
@@ -304,7 +304,7 @@ SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
304 304
305/* Mono Mixer */ 305/* Mono Mixer */
306static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = { 306static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
307SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1), 307SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 7, 1, 1),
308SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1), 308SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
309SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1), 309SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
310SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1), 310SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
@@ -463,7 +463,7 @@ SND_SOC_DAPM_VMID("VMID"),
463 463
464static const struct snd_soc_dapm_route audio_map[] = { 464static const struct snd_soc_dapm_route audio_map[] = {
465 /* left HP mixer */ 465 /* left HP mixer */
466 {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, 466 {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"},
467 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, 467 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
468 {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"}, 468 {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
469 {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"}, 469 {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"},
@@ -472,7 +472,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
472 {"Left HP Mixer", NULL, "Capture Headphone Mux"}, 472 {"Left HP Mixer", NULL, "Capture Headphone Mux"},
473 473
474 /* right HP mixer */ 474 /* right HP mixer */
475 {"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, 475 {"Right HP Mixer", "Beep Playback Switch", "PCBEEP"},
476 {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"}, 476 {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"},
477 {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"}, 477 {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
478 {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"}, 478 {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"},
@@ -491,7 +491,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
491 {"Capture Mixer", NULL, "Right Capture Source"}, 491 {"Capture Mixer", NULL, "Right Capture Source"},
492 492
493 /* speaker mixer */ 493 /* speaker mixer */
494 {"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"}, 494 {"Speaker Mixer", "Beep Playback Switch", "PCBEEP"},
495 {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"}, 495 {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"},
496 {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"}, 496 {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
497 {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"}, 497 {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"},
@@ -499,7 +499,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
499 {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"}, 499 {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"},
500 500
501 /* mono mixer */ 501 /* mono mixer */
502 {"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"}, 502 {"Mono Mixer", "Beep Playback Switch", "PCBEEP"},
503 {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, 503 {"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
504 {"Mono Mixer", "Aux Playback Switch", "Aux DAC"}, 504 {"Mono Mixer", "Aux Playback Switch", "Aux DAC"},
505 {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"}, 505 {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"},
@@ -625,7 +625,6 @@ static int wm9713_add_widgets(struct snd_soc_codec *codec)
625 625
626 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 626 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
627 627
628 snd_soc_dapm_new_widgets(codec);
629 return 0; 628 return 0;
630} 629}
631 630
@@ -800,8 +799,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
800 return 0; 799 return 0;
801} 800}
802 801
803static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, 802static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
804 int pll_id, unsigned int freq_in, unsigned int freq_out) 803 int source, unsigned int freq_in, unsigned int freq_out)
805{ 804{
806 struct snd_soc_codec *codec = codec_dai->codec; 805 struct snd_soc_codec *codec = codec_dai->codec;
807 return wm9713_set_pll(codec, pll_id, freq_in, freq_out); 806 return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
@@ -1247,14 +1246,11 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1247 snd_soc_add_controls(codec, wm9713_snd_ac97_controls, 1246 snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
1248 ARRAY_SIZE(wm9713_snd_ac97_controls)); 1247 ARRAY_SIZE(wm9713_snd_ac97_controls));
1249 wm9713_add_widgets(codec); 1248 wm9713_add_widgets(codec);
1250 ret = snd_soc_init_card(socdev); 1249
1251 if (ret < 0)
1252 goto reset_err;
1253 return 0; 1250 return 0;
1254 1251
1255reset_err: 1252reset_err:
1256 snd_soc_free_pcms(socdev); 1253 snd_soc_free_pcms(socdev);
1257
1258pcm_err: 1254pcm_err:
1259 snd_soc_free_ac97_codec(codec); 1255 snd_soc_free_ac97_codec(codec);
1260 1256
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index e542027eea89..d73c30536a2c 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -438,11 +438,11 @@ static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
438SND_SOC_DAPM_INPUT("IN1LN"), 438SND_SOC_DAPM_INPUT("IN1LN"),
439SND_SOC_DAPM_INPUT("IN1LP"), 439SND_SOC_DAPM_INPUT("IN1LP"),
440SND_SOC_DAPM_INPUT("IN2LN"), 440SND_SOC_DAPM_INPUT("IN2LN"),
441SND_SOC_DAPM_INPUT("IN2LP/VXRN"), 441SND_SOC_DAPM_INPUT("IN2LP:VXRN"),
442SND_SOC_DAPM_INPUT("IN1RN"), 442SND_SOC_DAPM_INPUT("IN1RN"),
443SND_SOC_DAPM_INPUT("IN1RP"), 443SND_SOC_DAPM_INPUT("IN1RP"),
444SND_SOC_DAPM_INPUT("IN2RN"), 444SND_SOC_DAPM_INPUT("IN2RN"),
445SND_SOC_DAPM_INPUT("IN2RP/VXRP"), 445SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
446 446
447SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), 447SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
448SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), 448SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
@@ -537,14 +537,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
537 { "IN1R PGA", "IN1RP Switch", "IN1RP" }, 537 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
538 { "IN1R PGA", "IN1RN Switch", "IN1RN" }, 538 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
539 539
540 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, 540 { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" },
541 { "IN2L PGA", "IN2LN Switch", "IN2LN" }, 541 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
542 542
543 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, 543 { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" },
544 { "IN2R PGA", "IN2RN Switch", "IN2RN" }, 544 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
545 545
546 { "Direct Voice", NULL, "IN2LP/VXRN" }, 546 { "Direct Voice", NULL, "IN2LP:VXRN" },
547 { "Direct Voice", NULL, "IN2RP/VXRP" }, 547 { "Direct Voice", NULL, "IN2RP:VXRP" },
548 548
549 { "MIXINL", "IN1L Switch", "IN1L PGA" }, 549 { "MIXINL", "IN1L Switch", "IN1L PGA" },
550 { "MIXINL", "IN2L Switch", "IN2L PGA" }, 550 { "MIXINL", "IN2L Switch", "IN2L PGA" },
@@ -565,7 +565,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
565 { "Left Output Mixer", "Right Input Switch", "MIXINR" }, 565 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
566 { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, 566 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
567 { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, 567 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
568 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, 568 { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" },
569 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, 569 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
570 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, 570 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
571 571
@@ -573,7 +573,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
573 { "Right Output Mixer", "Right Input Switch", "MIXINR" }, 573 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
574 { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, 574 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
575 { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, 575 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
576 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, 576 { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" },
577 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, 577 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
578 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, 578 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
579 579
@@ -738,6 +738,41 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
738} 738}
739EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); 739EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
740 740
741int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
742 int lineout1_diff, int lineout2_diff,
743 int lineout1fb, int lineout2fb,
744 int jd_scthr, int jd_thr, int micbias1_lvl,
745 int micbias2_lvl)
746{
747 if (!lineout1_diff)
748 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
749 WM8993_LINEOUT1_MODE,
750 WM8993_LINEOUT1_MODE);
751 if (!lineout2_diff)
752 snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
753 WM8993_LINEOUT2_MODE,
754 WM8993_LINEOUT2_MODE);
755
756 if (lineout1fb)
757 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
758 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
759
760 if (lineout2fb)
761 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
762 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
763
764 snd_soc_update_bits(codec, WM8993_MICBIAS,
765 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
766 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
767 jd_scthr << WM8993_JD_SCTHR_SHIFT |
768 jd_thr << WM8993_JD_THR_SHIFT |
769 micbias1_lvl |
770 micbias2_lvl << WM8993_MICB2_LVL_SHIFT);
771
772 return 0;
773}
774EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
775
741MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); 776MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
742MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 777MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
743MODULE_LICENSE("GPL"); 778MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index ec09cb6a2939..36d3fba1de8b 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -20,5 +20,10 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
20 20
21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); 21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); 22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int);
23extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
24 int lineout1_diff, int lineout2_diff,
25 int lineout1fb, int lineout2fb,
26 int jd_scthr, int jd_thr,
27 int micbias1_lvl, int micbias2_lvl);
23 28
24#endif 29#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 4dfd4ad9d90e..047ee39418c0 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -13,9 +13,9 @@ config SND_DAVINCI_SOC_MCASP
13 tristate 13 tristate
14 14
15config SND_DAVINCI_SOC_EVM 15config SND_DAVINCI_SOC_EVM
16 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" 16 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
17 depends on SND_DAVINCI_SOC 17 depends on SND_DAVINCI_SOC
18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM 18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
19 select SND_DAVINCI_SOC_I2S 19 select SND_DAVINCI_SOC_I2S
20 select SND_SOC_TLV320AIC3X 20 select SND_SOC_TLV320AIC3X
21 help 21 help
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 67414f659405..7ccbe6684fc2 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -45,7 +45,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
45 unsigned sysclk; 45 unsigned sysclk;
46 46
47 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 47 /* ASP1 on DM355 EVM is clocked by an external oscillator */
48 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm()) 48 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
49 machine_is_davinci_dm365_evm())
49 sysclk = 27000000; 50 sysclk = 27000000;
50 51
51 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 52 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -176,7 +177,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
176 .ops = &evm_ops, 177 .ops = &evm_ops,
177}; 178};
178 179
179/* davinci-evm audio machine driver */ 180/* davinci dm6446, dm355 or dm365 evm audio machine driver */
180static struct snd_soc_card snd_soc_card_evm = { 181static struct snd_soc_card snd_soc_card_evm = {
181 .name = "DaVinci EVM", 182 .name = "DaVinci EVM",
182 .platform = &davinci_soc_platform, 183 .platform = &davinci_soc_platform,
@@ -243,7 +244,7 @@ static int __init evm_init(void)
243 int index; 244 int index;
244 int ret; 245 int ret;
245 246
246 if (machine_is_davinci_evm()) { 247 if (machine_is_davinci_evm() || machine_is_davinci_dm365_evm()) {
247 evm_snd_dev_data = &evm_snd_devdata; 248 evm_snd_dev_data = &evm_snd_devdata;
248 index = 0; 249 index = 0;
249 } else if (machine_is_davinci_dm355_evm()) { 250 } else if (machine_is_davinci_dm355_evm()) {
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 4ae707048021..6362ca05506e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -97,12 +97,24 @@ enum {
97 DAVINCI_MCBSP_WORD_32, 97 DAVINCI_MCBSP_WORD_32,
98}; 98};
99 99
100static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = {
101 [SNDRV_PCM_FORMAT_S8] = 1,
102 [SNDRV_PCM_FORMAT_S16_LE] = 2,
103 [SNDRV_PCM_FORMAT_S32_LE] = 4,
104};
105
106static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = {
107 [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8,
108 [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16,
109 [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32,
110};
111
112static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
113 [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE,
114 [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE,
115};
116
100struct davinci_mcbsp_dev { 117struct davinci_mcbsp_dev {
101 /*
102 * dma_params must be first because rtd->dai->cpu_dai->private_data
103 * is cast to a pointer of an array of struct davinci_pcm_dma_params in
104 * davinci_pcm_open.
105 */
106 struct davinci_pcm_dma_params dma_params[2]; 118 struct davinci_pcm_dma_params dma_params[2];
107 void __iomem *base; 119 void __iomem *base;
108#define MOD_DSP_A 0 120#define MOD_DSP_A 0
@@ -110,6 +122,27 @@ struct davinci_mcbsp_dev {
110 int mode; 122 int mode;
111 u32 pcr; 123 u32 pcr;
112 struct clk *clk; 124 struct clk *clk;
125 /*
126 * Combining both channels into 1 element will at least double the
127 * amount of time between servicing the dma channel, increase
128 * effiency, and reduce the chance of overrun/underrun. But,
129 * it will result in the left & right channels being swapped.
130 *
131 * If relabeling the left and right channels is not possible,
132 * you may want to let the codec know to swap them back.
133 *
134 * It may allow x10 the amount of time to service dma requests,
135 * if the codec is master and is using an unnecessarily fast bit clock
136 * (ie. tlvaic23b), independent of the sample rate. So, having an
137 * entire frame at once means it can be serviced at the sample rate
138 * instead of the bit clock rate.
139 *
140 * In the now unlikely case that an underrun still
141 * occurs, both the left and right samples will be repeated
142 * so that no pops are heard, and the left and right channels
143 * won't end up being swapped because of the underrun.
144 */
145 unsigned enable_channel_combine:1;
113}; 146};
114 147
115static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, 148static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -349,6 +382,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
349 int mcbsp_word_length; 382 int mcbsp_word_length;
350 unsigned int rcr, xcr, srgr; 383 unsigned int rcr, xcr, srgr;
351 u32 spcr; 384 u32 spcr;
385 snd_pcm_format_t fmt;
386 unsigned element_cnt = 1;
352 387
353 /* general line settings */ 388 /* general line settings */
354 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 389 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -378,27 +413,24 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
378 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); 413 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
379 } 414 }
380 /* Determine xfer data type */ 415 /* Determine xfer data type */
381 switch (params_format(params)) { 416 fmt = params_format(params);
382 case SNDRV_PCM_FORMAT_S8: 417 if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) {
383 dma_params->data_type = 1;
384 mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
385 break;
386 case SNDRV_PCM_FORMAT_S16_LE:
387 dma_params->data_type = 2;
388 mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
389 break;
390 case SNDRV_PCM_FORMAT_S32_LE:
391 dma_params->data_type = 4;
392 mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
393 break;
394 default:
395 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); 418 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
396 return -EINVAL; 419 return -EINVAL;
397 } 420 }
398 421
399 dma_params->acnt = dma_params->data_type; 422 if (params_channels(params) == 2) {
400 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); 423 element_cnt = 2;
401 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); 424 if (double_fmt[fmt] && dev->enable_channel_combine) {
425 element_cnt = 1;
426 fmt = double_fmt[fmt];
427 }
428 }
429 dma_params->acnt = dma_params->data_type = data_type[fmt];
430 dma_params->fifo_level = 0;
431 mcbsp_word_length = asp_word_length[fmt];
432 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
433 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
402 434
403 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 435 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
404 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); 436 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
@@ -513,7 +545,13 @@ static int davinci_i2s_probe(struct platform_device *pdev)
513 ret = -ENOMEM; 545 ret = -ENOMEM;
514 goto err_release_region; 546 goto err_release_region;
515 } 547 }
516 548 if (pdata) {
549 dev->enable_channel_combine = pdata->enable_channel_combine;
550 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size =
551 pdata->sram_size_playback;
552 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
553 pdata->sram_size_capture;
554 }
517 dev->clk = clk_get(&pdev->dev, NULL); 555 dev->clk = clk_get(&pdev->dev, NULL);
518 if (IS_ERR(dev->clk)) { 556 if (IS_ERR(dev->clk)) {
519 ret = -ENODEV; 557 ret = -ENODEV;
@@ -547,6 +585,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
547 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 585 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
548 586
549 davinci_i2s_dai.private_data = dev; 587 davinci_i2s_dai.private_data = dev;
588 davinci_i2s_dai.dma_data = dev->dma_params;
550 ret = snd_soc_register_dai(&davinci_i2s_dai); 589 ret = snd_soc_register_dai(&davinci_i2s_dai);
551 if (ret != 0) 590 if (ret != 0)
552 goto err_free_mem; 591 goto err_free_mem;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 5d1f98a4c978..0a302e1080d9 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -714,16 +714,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
714 struct davinci_pcm_dma_params *dma_params = 714 struct davinci_pcm_dma_params *dma_params =
715 &dev->dma_params[substream->stream]; 715 &dev->dma_params[substream->stream];
716 int word_length; 716 int word_length;
717 u8 numevt; 717 u8 fifo_level;
718 718
719 davinci_hw_common_param(dev, substream->stream); 719 davinci_hw_common_param(dev, substream->stream);
720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
721 numevt = dev->txnumevt; 721 fifo_level = dev->txnumevt;
722 else 722 else
723 numevt = dev->rxnumevt; 723 fifo_level = dev->rxnumevt;
724
725 if (!numevt)
726 numevt = 1;
727 724
728 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) 725 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
729 davinci_hw_dit_param(dev); 726 davinci_hw_dit_param(dev);
@@ -751,12 +748,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
751 return -EINVAL; 748 return -EINVAL;
752 } 749 }
753 750
754 if (dev->version == MCASP_VERSION_2) { 751 if (dev->version == MCASP_VERSION_2 && !fifo_level)
755 dma_params->data_type *= numevt; 752 dma_params->acnt = 4;
756 dma_params->acnt = 4 * numevt; 753 else
757 } else
758 dma_params->acnt = dma_params->data_type; 754 dma_params->acnt = dma_params->data_type;
759 755
756 dma_params->fifo_level = fifo_level;
760 davinci_config_channel_size(dev, word_length); 757 davinci_config_channel_size(dev, word_length);
761 758
762 return 0; 759 return 0;
@@ -907,6 +904,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
907 904
908 dma_data->channel = res->start; 905 dma_data->channel = res->start;
909 davinci_mcasp_dai[pdata->op_mode].private_data = dev; 906 davinci_mcasp_dai[pdata->op_mode].private_data = dev;
907 davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params;
910 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; 908 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
911 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); 909 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
912 910
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 9d179cc88f7b..582c9249ef09 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -39,11 +39,6 @@ enum {
39}; 39};
40 40
41struct davinci_audio_dev { 41struct davinci_audio_dev {
42 /*
43 * dma_params must be first because rtd->dai->cpu_dai->private_data
44 * is cast to a pointer of an array of struct davinci_pcm_dma_params in
45 * davinci_pcm_open.
46 */
47 struct davinci_pcm_dma_params dma_params[2]; 42 struct davinci_pcm_dma_params dma_params[2];
48 void __iomem *base; 43 void __iomem *base;
49 int sample_rate; 44 int sample_rate;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index c73a915f233f..ad4d7f47a86b 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * added SRAM ping/pong (C) 2008 Troy Kisky <troy.kisky@boundarydevices.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -23,10 +24,29 @@
23 24
24#include <asm/dma.h> 25#include <asm/dma.h>
25#include <mach/edma.h> 26#include <mach/edma.h>
27#include <mach/sram.h>
26 28
27#include "davinci-pcm.h" 29#include "davinci-pcm.h"
28 30
29static struct snd_pcm_hardware davinci_pcm_hardware = { 31#ifdef DEBUG
32static void print_buf_info(int slot, char *name)
33{
34 struct edmacc_param p;
35 if (slot < 0)
36 return;
37 edma_read_slot(slot, &p);
38 printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
39 name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
40 printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
41 p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
42}
43#else
44static void print_buf_info(int slot, char *name)
45{
46}
47#endif
48
49static struct snd_pcm_hardware pcm_hardware_playback = {
30 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 50 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
31 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 51 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
32 SNDRV_PCM_INFO_PAUSE), 52 SNDRV_PCM_INFO_PAUSE),
@@ -48,102 +68,432 @@ static struct snd_pcm_hardware davinci_pcm_hardware = {
48 .fifo_size = 0, 68 .fifo_size = 0,
49}; 69};
50 70
71static struct snd_pcm_hardware pcm_hardware_capture = {
72 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE),
75 .formats = (SNDRV_PCM_FMTBIT_S16_LE),
76 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
77 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
78 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
79 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
80 SNDRV_PCM_RATE_KNOT),
81 .rate_min = 8000,
82 .rate_max = 96000,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 128 * 1024,
86 .period_bytes_min = 32,
87 .period_bytes_max = 8 * 1024,
88 .periods_min = 16,
89 .periods_max = 255,
90 .fifo_size = 0,
91};
92
93/*
94 * How ping/pong works....
95 *
96 * Playback:
97 * ram_params - copys 2*ping_size from start of SDRAM to iram,
98 * links to ram_link2
99 * ram_link2 - copys rest of SDRAM to iram in ping_size units,
100 * links to ram_link
101 * ram_link - copys entire SDRAM to iram in ping_size uints,
102 * links to self
103 *
104 * asp_params - same as asp_link[0]
105 * asp_link[0] - copys from lower half of iram to asp port
106 * links to asp_link[1], triggers iram copy event on completion
107 * asp_link[1] - copys from upper half of iram to asp port
108 * links to asp_link[0], triggers iram copy event on completion
109 * triggers interrupt only needed to let upper SOC levels update position
110 * in stream on completion
111 *
112 * When playback is started:
113 * ram_params started
114 * asp_params started
115 *
116 * Capture:
117 * ram_params - same as ram_link,
118 * links to ram_link
119 * ram_link - same as playback
120 * links to self
121 *
122 * asp_params - same as playback
123 * asp_link[0] - same as playback
124 * asp_link[1] - same as playback
125 *
126 * When capture is started:
127 * asp_params started
128 */
51struct davinci_runtime_data { 129struct davinci_runtime_data {
52 spinlock_t lock; 130 spinlock_t lock;
53 int period; /* current DMA period */ 131 int period; /* current DMA period */
54 int master_lch; /* Master DMA channel */ 132 int asp_channel; /* Master DMA channel */
55 int slave_lch; /* linked parameter RAM reload slot */ 133 int asp_link[2]; /* asp parameter link channel, ping/pong */
56 struct davinci_pcm_dma_params *params; /* DMA params */ 134 struct davinci_pcm_dma_params *params; /* DMA params */
135 int ram_channel;
136 int ram_link;
137 int ram_link2;
138 struct edmacc_param asp_params;
139 struct edmacc_param ram_params;
57}; 140};
58 141
142/*
143 * Not used with ping/pong
144 */
59static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) 145static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
60{ 146{
61 struct davinci_runtime_data *prtd = substream->runtime->private_data; 147 struct davinci_runtime_data *prtd = substream->runtime->private_data;
62 struct snd_pcm_runtime *runtime = substream->runtime; 148 struct snd_pcm_runtime *runtime = substream->runtime;
63 int lch = prtd->slave_lch; 149 int link = prtd->asp_link[0];
64 unsigned int period_size; 150 unsigned int period_size;
65 unsigned int dma_offset; 151 unsigned int dma_offset;
66 dma_addr_t dma_pos; 152 dma_addr_t dma_pos;
67 dma_addr_t src, dst; 153 dma_addr_t src, dst;
68 unsigned short src_bidx, dst_bidx; 154 unsigned short src_bidx, dst_bidx;
155 unsigned short src_cidx, dst_cidx;
69 unsigned int data_type; 156 unsigned int data_type;
70 unsigned short acnt; 157 unsigned short acnt;
71 unsigned int count; 158 unsigned int count;
159 unsigned int fifo_level;
72 160
73 period_size = snd_pcm_lib_period_bytes(substream); 161 period_size = snd_pcm_lib_period_bytes(substream);
74 dma_offset = prtd->period * period_size; 162 dma_offset = prtd->period * period_size;
75 dma_pos = runtime->dma_addr + dma_offset; 163 dma_pos = runtime->dma_addr + dma_offset;
164 fifo_level = prtd->params->fifo_level;
76 165
77 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " 166 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
78 "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size); 167 "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);
79 168
80 data_type = prtd->params->data_type; 169 data_type = prtd->params->data_type;
81 count = period_size / data_type; 170 count = period_size / data_type;
171 if (fifo_level)
172 count /= fifo_level;
82 173
83 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
84 src = dma_pos; 175 src = dma_pos;
85 dst = prtd->params->dma_addr; 176 dst = prtd->params->dma_addr;
86 src_bidx = data_type; 177 src_bidx = data_type;
87 dst_bidx = 0; 178 dst_bidx = 0;
179 src_cidx = data_type * fifo_level;
180 dst_cidx = 0;
88 } else { 181 } else {
89 src = prtd->params->dma_addr; 182 src = prtd->params->dma_addr;
90 dst = dma_pos; 183 dst = dma_pos;
91 src_bidx = 0; 184 src_bidx = 0;
92 dst_bidx = data_type; 185 dst_bidx = data_type;
186 src_cidx = 0;
187 dst_cidx = data_type * fifo_level;
93 } 188 }
94 189
95 acnt = prtd->params->acnt; 190 acnt = prtd->params->acnt;
96 edma_set_src(lch, src, INCR, W8BIT); 191 edma_set_src(link, src, INCR, W8BIT);
97 edma_set_dest(lch, dst, INCR, W8BIT); 192 edma_set_dest(link, dst, INCR, W8BIT);
98 edma_set_src_index(lch, src_bidx, 0); 193
99 edma_set_dest_index(lch, dst_bidx, 0); 194 edma_set_src_index(link, src_bidx, src_cidx);
100 edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC); 195 edma_set_dest_index(link, dst_bidx, dst_cidx);
196
197 if (!fifo_level)
198 edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
199 else
200 edma_set_transfer_params(link, acnt, fifo_level, count,
201 fifo_level, ABSYNC);
101 202
102 prtd->period++; 203 prtd->period++;
103 if (unlikely(prtd->period >= runtime->periods)) 204 if (unlikely(prtd->period >= runtime->periods))
104 prtd->period = 0; 205 prtd->period = 0;
105} 206}
106 207
107static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data) 208static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
108{ 209{
109 struct snd_pcm_substream *substream = data; 210 struct snd_pcm_substream *substream = data;
110 struct davinci_runtime_data *prtd = substream->runtime->private_data; 211 struct davinci_runtime_data *prtd = substream->runtime->private_data;
111 212
112 pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status); 213 print_buf_info(prtd->ram_channel, "i ram_channel");
214 pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
113 215
114 if (unlikely(ch_status != DMA_COMPLETE)) 216 if (unlikely(ch_status != DMA_COMPLETE))
115 return; 217 return;
116 218
117 if (snd_pcm_running(substream)) { 219 if (snd_pcm_running(substream)) {
220 if (prtd->ram_channel < 0) {
221 /* No ping/pong must fix up link dma data*/
222 spin_lock(&prtd->lock);
223 davinci_pcm_enqueue_dma(substream);
224 spin_unlock(&prtd->lock);
225 }
118 snd_pcm_period_elapsed(substream); 226 snd_pcm_period_elapsed(substream);
227 }
228}
229
230static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
231 struct snd_pcm_hardware *ppcm)
232{
233 struct snd_dma_buffer *buf = &substream->dma_buffer;
234 struct snd_dma_buffer *iram_dma = NULL;
235 dma_addr_t iram_phys = 0;
236 void *iram_virt = NULL;
237
238 if (buf->private_data || !size)
239 return 0;
240
241 ppcm->period_bytes_max = size;
242 iram_virt = sram_alloc(size, &iram_phys);
243 if (!iram_virt)
244 goto exit1;
245 iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
246 if (!iram_dma)
247 goto exit2;
248 iram_dma->area = iram_virt;
249 iram_dma->addr = iram_phys;
250 memset(iram_dma->area, 0, size);
251 iram_dma->bytes = size;
252 buf->private_data = iram_dma;
253 return 0;
254exit2:
255 if (iram_virt)
256 sram_free(iram_virt, size);
257exit1:
258 return -ENOMEM;
259}
260
261/*
262 * Only used with ping/pong.
263 * This is called after runtime->dma_addr, period_bytes and data_type are valid
264 */
265static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
266{
267 unsigned short ram_src_cidx, ram_dst_cidx;
268 struct snd_pcm_runtime *runtime = substream->runtime;
269 struct davinci_runtime_data *prtd = runtime->private_data;
270 struct snd_dma_buffer *iram_dma =
271 (struct snd_dma_buffer *)substream->dma_buffer.private_data;
272 struct davinci_pcm_dma_params *params = prtd->params;
273 unsigned int data_type = params->data_type;
274 unsigned int acnt = params->acnt;
275 /* divide by 2 for ping/pong */
276 unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
277 int link = prtd->asp_link[1];
278 unsigned int fifo_level = prtd->params->fifo_level;
279 unsigned int count;
280 if ((data_type == 0) || (data_type > 4)) {
281 printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type);
282 return -EINVAL;
283 }
284 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
285 dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
286 ram_src_cidx = ping_size;
287 ram_dst_cidx = -ping_size;
288 edma_set_src(link, asp_src_pong, INCR, W8BIT);
289
290 link = prtd->asp_link[0];
291 edma_set_src_index(link, data_type, data_type * fifo_level);
292 link = prtd->asp_link[1];
293 edma_set_src_index(link, data_type, data_type * fifo_level);
294
295 link = prtd->ram_link;
296 edma_set_src(link, runtime->dma_addr, INCR, W32BIT);
297 } else {
298 dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
299 ram_src_cidx = -ping_size;
300 ram_dst_cidx = ping_size;
301 edma_set_dest(link, asp_dst_pong, INCR, W8BIT);
302
303 link = prtd->asp_link[0];
304 edma_set_dest_index(link, data_type, data_type * fifo_level);
305 link = prtd->asp_link[1];
306 edma_set_dest_index(link, data_type, data_type * fifo_level);
307
308 link = prtd->ram_link;
309 edma_set_dest(link, runtime->dma_addr, INCR, W32BIT);
310 }
119 311
120 spin_lock(&prtd->lock); 312 if (!fifo_level) {
121 davinci_pcm_enqueue_dma(substream); 313 count = ping_size / data_type;
122 spin_unlock(&prtd->lock); 314 edma_set_transfer_params(prtd->asp_link[0], acnt, count,
315 1, 0, ASYNC);
316 edma_set_transfer_params(prtd->asp_link[1], acnt, count,
317 1, 0, ASYNC);
318 } else {
319 count = ping_size / (data_type * fifo_level);
320 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
321 count, fifo_level, ABSYNC);
322 edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level,
323 count, fifo_level, ABSYNC);
123 } 324 }
325
326 link = prtd->ram_link;
327 edma_set_src_index(link, ping_size, ram_src_cidx);
328 edma_set_dest_index(link, ping_size, ram_dst_cidx);
329 edma_set_transfer_params(link, ping_size, 2,
330 runtime->periods, 2, ASYNC);
331
332 /* init master params */
333 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
334 edma_read_slot(prtd->ram_link, &prtd->ram_params);
335 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
336 struct edmacc_param p_ram;
337 /* Copy entire iram buffer before playback started */
338 prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1);
339 /* 0 dst_bidx */
340 prtd->ram_params.src_dst_bidx = (ping_size << 1);
341 /* 0 dst_cidx */
342 prtd->ram_params.src_dst_cidx = (ping_size << 1);
343 prtd->ram_params.ccnt = 1;
344
345 /* Skip 1st period */
346 edma_read_slot(prtd->ram_link, &p_ram);
347 p_ram.src += (ping_size << 1);
348 p_ram.ccnt -= 1;
349 edma_write_slot(prtd->ram_link2, &p_ram);
350 /*
351 * When 1st started, ram -> iram dma channel will fill the
352 * entire iram. Then, whenever a ping/pong asp buffer finishes,
353 * 1/2 iram will be filled.
354 */
355 prtd->ram_params.link_bcntrld =
356 EDMA_CHAN_SLOT(prtd->ram_link2) << 5;
357 }
358 return 0;
359}
360
361/* 1 asp tx or rx channel using 2 parameter channels
362 * 1 ram to/from iram channel using 1 parameter channel
363 *
364 * Playback
365 * ram copy channel kicks off first,
366 * 1st ram copy of entire iram buffer completion kicks off asp channel
367 * asp tcc always kicks off ram copy of 1/2 iram buffer
368 *
369 * Record
370 * asp channel starts, tcc kicks off ram copy
371 */
372static int request_ping_pong(struct snd_pcm_substream *substream,
373 struct davinci_runtime_data *prtd,
374 struct snd_dma_buffer *iram_dma)
375{
376 dma_addr_t asp_src_ping;
377 dma_addr_t asp_dst_ping;
378 int link;
379 struct davinci_pcm_dma_params *params = prtd->params;
380
381 /* Request ram master channel */
382 link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
383 davinci_pcm_dma_irq, substream,
384 EVENTQ_1);
385 if (link < 0)
386 goto exit1;
387
388 /* Request ram link channel */
389 link = prtd->ram_link = edma_alloc_slot(
390 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
391 if (link < 0)
392 goto exit2;
393
394 link = prtd->asp_link[1] = edma_alloc_slot(
395 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
396 if (link < 0)
397 goto exit3;
398
399 prtd->ram_link2 = -1;
400 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
401 link = prtd->ram_link2 = edma_alloc_slot(
402 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
403 if (link < 0)
404 goto exit4;
405 }
406 /* circle ping-pong buffers */
407 edma_link(prtd->asp_link[0], prtd->asp_link[1]);
408 edma_link(prtd->asp_link[1], prtd->asp_link[0]);
409 /* circle ram buffers */
410 edma_link(prtd->ram_link, prtd->ram_link);
411
412 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
413 asp_src_ping = iram_dma->addr;
414 asp_dst_ping = params->dma_addr; /* fifo */
415 } else {
416 asp_src_ping = params->dma_addr; /* fifo */
417 asp_dst_ping = iram_dma->addr;
418 }
419 /* ping */
420 link = prtd->asp_link[0];
421 edma_set_src(link, asp_src_ping, INCR, W16BIT);
422 edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
423 edma_set_src_index(link, 0, 0);
424 edma_set_dest_index(link, 0, 0);
425
426 edma_read_slot(link, &prtd->asp_params);
427 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
428 prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f);
429 edma_write_slot(link, &prtd->asp_params);
430
431 /* pong */
432 link = prtd->asp_link[1];
433 edma_set_src(link, asp_src_ping, INCR, W16BIT);
434 edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
435 edma_set_src_index(link, 0, 0);
436 edma_set_dest_index(link, 0, 0);
437
438 edma_read_slot(link, &prtd->asp_params);
439 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
440 /* interrupt after every pong completion */
441 prtd->asp_params.opt |= TCINTEN | TCCHEN |
442 EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel));
443 edma_write_slot(link, &prtd->asp_params);
444
445 /* ram */
446 link = prtd->ram_link;
447 edma_set_src(link, iram_dma->addr, INCR, W32BIT);
448 edma_set_dest(link, iram_dma->addr, INCR, W32BIT);
449 pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
450 "for asp:%u %u %u\n", __func__,
451 prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
452 prtd->asp_channel, prtd->asp_link[0],
453 prtd->asp_link[1]);
454 return 0;
455exit4:
456 edma_free_channel(prtd->asp_link[1]);
457 prtd->asp_link[1] = -1;
458exit3:
459 edma_free_channel(prtd->ram_link);
460 prtd->ram_link = -1;
461exit2:
462 edma_free_channel(prtd->ram_channel);
463 prtd->ram_channel = -1;
464exit1:
465 return link;
124} 466}
125 467
126static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) 468static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
127{ 469{
470 struct snd_dma_buffer *iram_dma;
128 struct davinci_runtime_data *prtd = substream->runtime->private_data; 471 struct davinci_runtime_data *prtd = substream->runtime->private_data;
129 struct edmacc_param p_ram; 472 struct davinci_pcm_dma_params *params = prtd->params;
130 int ret; 473 int link;
131 474
132 /* Request master DMA channel */ 475 if (!params)
133 ret = edma_alloc_channel(prtd->params->channel, 476 return -ENODEV;
134 davinci_pcm_dma_irq, substream,
135 EVENTQ_0);
136 if (ret < 0)
137 return ret;
138 prtd->master_lch = ret;
139 477
140 /* Request parameter RAM reload slot */ 478 /* Request asp master DMA channel */
141 ret = edma_alloc_slot(EDMA_CTLR(prtd->master_lch), EDMA_SLOT_ANY); 479 link = prtd->asp_channel = edma_alloc_channel(params->channel,
142 if (ret < 0) { 480 davinci_pcm_dma_irq, substream, EVENTQ_0);
143 edma_free_channel(prtd->master_lch); 481 if (link < 0)
144 return ret; 482 goto exit1;
483
484 /* Request asp link channels */
485 link = prtd->asp_link[0] = edma_alloc_slot(
486 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
487 if (link < 0)
488 goto exit2;
489
490 iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
491 if (iram_dma) {
492 if (request_ping_pong(substream, prtd, iram_dma) == 0)
493 return 0;
494 printk(KERN_WARNING "%s: dma channel allocation failed,"
495 "not using sram\n", __func__);
145 } 496 }
146 prtd->slave_lch = ret;
147 497
148 /* Issue transfer completion IRQ when the channel completes a 498 /* Issue transfer completion IRQ when the channel completes a
149 * transfer, then always reload from the same slot (by a kind 499 * transfer, then always reload from the same slot (by a kind
@@ -154,12 +504,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
154 * the buffer and its length (ccnt) ... use it as a template 504 * the buffer and its length (ccnt) ... use it as a template
155 * so davinci_pcm_enqueue_dma() takes less time in IRQ. 505 * so davinci_pcm_enqueue_dma() takes less time in IRQ.
156 */ 506 */
157 edma_read_slot(prtd->slave_lch, &p_ram); 507 edma_read_slot(link, &prtd->asp_params);
158 p_ram.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(prtd->master_lch)); 508 prtd->asp_params.opt |= TCINTEN |
159 p_ram.link_bcntrld = EDMA_CHAN_SLOT(prtd->slave_lch) << 5; 509 EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
160 edma_write_slot(prtd->slave_lch, &p_ram); 510 prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5;
161 511 edma_write_slot(link, &prtd->asp_params);
162 return 0; 512 return 0;
513exit2:
514 edma_free_channel(prtd->asp_channel);
515 prtd->asp_channel = -1;
516exit1:
517 return link;
163} 518}
164 519
165static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 520static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -173,12 +528,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
173 case SNDRV_PCM_TRIGGER_START: 528 case SNDRV_PCM_TRIGGER_START:
174 case SNDRV_PCM_TRIGGER_RESUME: 529 case SNDRV_PCM_TRIGGER_RESUME:
175 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 530 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
176 edma_start(prtd->master_lch); 531 edma_resume(prtd->asp_channel);
177 break; 532 break;
178 case SNDRV_PCM_TRIGGER_STOP: 533 case SNDRV_PCM_TRIGGER_STOP:
179 case SNDRV_PCM_TRIGGER_SUSPEND: 534 case SNDRV_PCM_TRIGGER_SUSPEND:
180 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 535 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
181 edma_stop(prtd->master_lch); 536 edma_pause(prtd->asp_channel);
182 break; 537 break;
183 default: 538 default:
184 ret = -EINVAL; 539 ret = -EINVAL;
@@ -193,15 +548,37 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
193static int davinci_pcm_prepare(struct snd_pcm_substream *substream) 548static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
194{ 549{
195 struct davinci_runtime_data *prtd = substream->runtime->private_data; 550 struct davinci_runtime_data *prtd = substream->runtime->private_data;
196 struct edmacc_param temp;
197 551
552 if (prtd->ram_channel >= 0) {
553 int ret = ping_pong_dma_setup(substream);
554 if (ret < 0)
555 return ret;
556
557 edma_write_slot(prtd->ram_channel, &prtd->ram_params);
558 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
559
560 print_buf_info(prtd->ram_channel, "ram_channel");
561 print_buf_info(prtd->ram_link, "ram_link");
562 print_buf_info(prtd->ram_link2, "ram_link2");
563 print_buf_info(prtd->asp_channel, "asp_channel");
564 print_buf_info(prtd->asp_link[0], "asp_link[0]");
565 print_buf_info(prtd->asp_link[1], "asp_link[1]");
566
567 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
568 /* copy 1st iram buffer */
569 edma_start(prtd->ram_channel);
570 }
571 edma_start(prtd->asp_channel);
572 return 0;
573 }
198 prtd->period = 0; 574 prtd->period = 0;
199 davinci_pcm_enqueue_dma(substream); 575 davinci_pcm_enqueue_dma(substream);
200 576
201 /* Copy self-linked parameter RAM entry into master channel */ 577 /* Copy self-linked parameter RAM entry into master channel */
202 edma_read_slot(prtd->slave_lch, &temp); 578 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
203 edma_write_slot(prtd->master_lch, &temp); 579 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
204 davinci_pcm_enqueue_dma(substream); 580 davinci_pcm_enqueue_dma(substream);
581 edma_start(prtd->asp_channel);
205 582
206 return 0; 583 return 0;
207} 584}
@@ -212,20 +589,53 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
212 struct snd_pcm_runtime *runtime = substream->runtime; 589 struct snd_pcm_runtime *runtime = substream->runtime;
213 struct davinci_runtime_data *prtd = runtime->private_data; 590 struct davinci_runtime_data *prtd = runtime->private_data;
214 unsigned int offset; 591 unsigned int offset;
215 dma_addr_t count; 592 int asp_count;
216 dma_addr_t src, dst; 593 dma_addr_t asp_src, asp_dst;
217 594
218 spin_lock(&prtd->lock); 595 spin_lock(&prtd->lock);
219 596 if (prtd->ram_channel >= 0) {
220 edma_get_position(prtd->master_lch, &src, &dst); 597 int ram_count;
221 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 598 int mod_ram;
222 count = src - runtime->dma_addr; 599 dma_addr_t ram_src, ram_dst;
223 else 600 unsigned int period_size = snd_pcm_lib_period_bytes(substream);
224 count = dst - runtime->dma_addr; 601 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
225 602 /* reading ram before asp should be safe
603 * as long as the asp transfers less than a ping size
604 * of bytes between the 2 reads
605 */
606 edma_get_position(prtd->ram_channel,
607 &ram_src, &ram_dst);
608 edma_get_position(prtd->asp_channel,
609 &asp_src, &asp_dst);
610 asp_count = asp_src - prtd->asp_params.src;
611 ram_count = ram_src - prtd->ram_params.src;
612 mod_ram = ram_count % period_size;
613 mod_ram -= asp_count;
614 if (mod_ram < 0)
615 mod_ram += period_size;
616 else if (mod_ram == 0) {
617 if (snd_pcm_running(substream))
618 mod_ram += period_size;
619 }
620 ram_count -= mod_ram;
621 if (ram_count < 0)
622 ram_count += period_size * runtime->periods;
623 } else {
624 edma_get_position(prtd->ram_channel,
625 &ram_src, &ram_dst);
626 ram_count = ram_dst - prtd->ram_params.dst;
627 }
628 asp_count = ram_count;
629 } else {
630 edma_get_position(prtd->asp_channel, &asp_src, &asp_dst);
631 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
632 asp_count = asp_src - runtime->dma_addr;
633 else
634 asp_count = asp_dst - runtime->dma_addr;
635 }
226 spin_unlock(&prtd->lock); 636 spin_unlock(&prtd->lock);
227 637
228 offset = bytes_to_frames(runtime, count); 638 offset = bytes_to_frames(runtime, asp_count);
229 if (offset >= runtime->buffer_size) 639 if (offset >= runtime->buffer_size)
230 offset = 0; 640 offset = 0;
231 641
@@ -236,14 +646,19 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
236{ 646{
237 struct snd_pcm_runtime *runtime = substream->runtime; 647 struct snd_pcm_runtime *runtime = substream->runtime;
238 struct davinci_runtime_data *prtd; 648 struct davinci_runtime_data *prtd;
649 struct snd_pcm_hardware *ppcm;
239 int ret = 0; 650 int ret = 0;
240 struct snd_soc_pcm_runtime *rtd = substream->private_data; 651 struct snd_soc_pcm_runtime *rtd = substream->private_data;
241 struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->private_data; 652 struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data;
242 struct davinci_pcm_dma_params *params = &pa[substream->stream]; 653 struct davinci_pcm_dma_params *params;
243 if (!params) 654 if (!pa)
244 return -ENODEV; 655 return -ENODEV;
656 params = &pa[substream->stream];
245 657
246 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); 658 ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
659 &pcm_hardware_playback : &pcm_hardware_capture;
660 allocate_sram(substream, params->sram_size, ppcm);
661 snd_soc_set_runtime_hwparams(substream, ppcm);
247 /* ensure that buffer size is a multiple of period size */ 662 /* ensure that buffer size is a multiple of period size */
248 ret = snd_pcm_hw_constraint_integer(runtime, 663 ret = snd_pcm_hw_constraint_integer(runtime,
249 SNDRV_PCM_HW_PARAM_PERIODS); 664 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -256,6 +671,11 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
256 671
257 spin_lock_init(&prtd->lock); 672 spin_lock_init(&prtd->lock);
258 prtd->params = params; 673 prtd->params = params;
674 prtd->asp_channel = -1;
675 prtd->asp_link[0] = prtd->asp_link[1] = -1;
676 prtd->ram_channel = -1;
677 prtd->ram_link = -1;
678 prtd->ram_link2 = -1;
259 679
260 runtime->private_data = prtd; 680 runtime->private_data = prtd;
261 681
@@ -273,10 +693,29 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
273 struct snd_pcm_runtime *runtime = substream->runtime; 693 struct snd_pcm_runtime *runtime = substream->runtime;
274 struct davinci_runtime_data *prtd = runtime->private_data; 694 struct davinci_runtime_data *prtd = runtime->private_data;
275 695
276 edma_unlink(prtd->slave_lch); 696 if (prtd->ram_channel >= 0)
277 697 edma_stop(prtd->ram_channel);
278 edma_free_slot(prtd->slave_lch); 698 if (prtd->asp_channel >= 0)
279 edma_free_channel(prtd->master_lch); 699 edma_stop(prtd->asp_channel);
700 if (prtd->asp_link[0] >= 0)
701 edma_unlink(prtd->asp_link[0]);
702 if (prtd->asp_link[1] >= 0)
703 edma_unlink(prtd->asp_link[1]);
704 if (prtd->ram_link >= 0)
705 edma_unlink(prtd->ram_link);
706
707 if (prtd->asp_link[0] >= 0)
708 edma_free_slot(prtd->asp_link[0]);
709 if (prtd->asp_link[1] >= 0)
710 edma_free_slot(prtd->asp_link[1]);
711 if (prtd->asp_channel >= 0)
712 edma_free_channel(prtd->asp_channel);
713 if (prtd->ram_link >= 0)
714 edma_free_slot(prtd->ram_link);
715 if (prtd->ram_link2 >= 0)
716 edma_free_slot(prtd->ram_link2);
717 if (prtd->ram_channel >= 0)
718 edma_free_channel(prtd->ram_channel);
280 719
281 kfree(prtd); 720 kfree(prtd);
282 721
@@ -318,11 +757,11 @@ static struct snd_pcm_ops davinci_pcm_ops = {
318 .mmap = davinci_pcm_mmap, 757 .mmap = davinci_pcm_mmap,
319}; 758};
320 759
321static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 760static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
761 size_t size)
322{ 762{
323 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 763 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
324 struct snd_dma_buffer *buf = &substream->dma_buffer; 764 struct snd_dma_buffer *buf = &substream->dma_buffer;
325 size_t size = davinci_pcm_hardware.buffer_bytes_max;
326 765
327 buf->dev.type = SNDRV_DMA_TYPE_DEV; 766 buf->dev.type = SNDRV_DMA_TYPE_DEV;
328 buf->dev.dev = pcm->card->dev; 767 buf->dev.dev = pcm->card->dev;
@@ -347,6 +786,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
347 int stream; 786 int stream;
348 787
349 for (stream = 0; stream < 2; stream++) { 788 for (stream = 0; stream < 2; stream++) {
789 struct snd_dma_buffer *iram_dma;
350 substream = pcm->streams[stream].substream; 790 substream = pcm->streams[stream].substream;
351 if (!substream) 791 if (!substream)
352 continue; 792 continue;
@@ -358,6 +798,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
358 dma_free_writecombine(pcm->card->dev, buf->bytes, 798 dma_free_writecombine(pcm->card->dev, buf->bytes,
359 buf->area, buf->addr); 799 buf->area, buf->addr);
360 buf->area = NULL; 800 buf->area = NULL;
801 iram_dma = (struct snd_dma_buffer *)buf->private_data;
802 if (iram_dma) {
803 sram_free(iram_dma->area, iram_dma->bytes);
804 kfree(iram_dma);
805 }
361 } 806 }
362} 807}
363 808
@@ -375,14 +820,16 @@ static int davinci_pcm_new(struct snd_card *card,
375 820
376 if (dai->playback.channels_min) { 821 if (dai->playback.channels_min) {
377 ret = davinci_pcm_preallocate_dma_buffer(pcm, 822 ret = davinci_pcm_preallocate_dma_buffer(pcm,
378 SNDRV_PCM_STREAM_PLAYBACK); 823 SNDRV_PCM_STREAM_PLAYBACK,
824 pcm_hardware_playback.buffer_bytes_max);
379 if (ret) 825 if (ret)
380 return ret; 826 return ret;
381 } 827 }
382 828
383 if (dai->capture.channels_min) { 829 if (dai->capture.channels_min) {
384 ret = davinci_pcm_preallocate_dma_buffer(pcm, 830 ret = davinci_pcm_preallocate_dma_buffer(pcm,
385 SNDRV_PCM_STREAM_CAPTURE); 831 SNDRV_PCM_STREAM_CAPTURE,
832 pcm_hardware_capture.buffer_bytes_max);
386 if (ret) 833 if (ret)
387 return ret; 834 return ret;
388 } 835 }
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 8746606efc89..0764944cf10f 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -20,9 +20,11 @@ struct davinci_pcm_dma_params {
20 int channel; /* sync dma channel ID */ 20 int channel; /* sync dma channel ID */
21 unsigned short acnt; 21 unsigned short acnt;
22 dma_addr_t dma_addr; /* device physical address for DMA */ 22 dma_addr_t dma_addr; /* device physical address for DMA */
23 unsigned sram_size;
23 enum dma_event_q eventq_no; /* event queue number */ 24 enum dma_event_q eventq_no; /* event queue number */
24 unsigned char data_type; /* xfer data type */ 25 unsigned char data_type; /* xfer data type */
25 unsigned char convert_mono_stereo; 26 unsigned char convert_mono_stereo;
27 unsigned int fifo_level;
26}; 28};
27 29
28 30
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 6096d22283e6..30ed568afb2e 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -58,47 +58,15 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
58 /* Prepare and enqueue the next buffer descriptor */ 58 /* Prepare and enqueue the next buffer descriptor */
59 bd = bcom_prepare_next_buffer(s->bcom_task); 59 bd = bcom_prepare_next_buffer(s->bcom_task);
60 bd->status = s->period_bytes; 60 bd->status = s->period_bytes;
61 bd->data[0] = s->period_next_pt; 61 bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes);
62 bcom_submit_next_buffer(s->bcom_task, NULL); 62 bcom_submit_next_buffer(s->bcom_task, NULL);
63 63
64 /* Update for next period */ 64 /* Update for next period */
65 s->period_next_pt += s->period_bytes; 65 s->period_next = (s->period_next + 1) % s->runtime->periods;
66 if (s->period_next_pt >= s->period_end)
67 s->period_next_pt = s->period_start;
68}
69
70static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
71{
72 if (s->appl_ptr > s->runtime->control->appl_ptr) {
73 /*
74 * In this case s->runtime->control->appl_ptr has wrapped around.
75 * Play the data to the end of the boundary, then wrap our own
76 * appl_ptr back around.
77 */
78 while (s->appl_ptr < s->runtime->boundary) {
79 if (bcom_queue_full(s->bcom_task))
80 return;
81
82 s->appl_ptr += s->period_size;
83
84 psc_dma_bcom_enqueue_next_buffer(s);
85 }
86 s->appl_ptr -= s->runtime->boundary;
87 }
88
89 while (s->appl_ptr < s->runtime->control->appl_ptr) {
90
91 if (bcom_queue_full(s->bcom_task))
92 return;
93
94 s->appl_ptr += s->period_size;
95
96 psc_dma_bcom_enqueue_next_buffer(s);
97 }
98} 66}
99 67
100/* Bestcomm DMA irq handler */ 68/* Bestcomm DMA irq handler */
101static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream) 69static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
102{ 70{
103 struct psc_dma_stream *s = _psc_dma_stream; 71 struct psc_dma_stream *s = _psc_dma_stream;
104 72
@@ -108,34 +76,8 @@ static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream)
108 while (bcom_buffer_done(s->bcom_task)) { 76 while (bcom_buffer_done(s->bcom_task)) {
109 bcom_retrieve_buffer(s->bcom_task, NULL, NULL); 77 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
110 78
111 s->period_current_pt += s->period_bytes; 79 s->period_current = (s->period_current+1) % s->runtime->periods;
112 if (s->period_current_pt >= s->period_end) 80 s->period_count++;
113 s->period_current_pt = s->period_start;
114 }
115 psc_dma_bcom_enqueue_tx(s);
116 spin_unlock(&s->psc_dma->lock);
117
118 /* If the stream is active, then also inform the PCM middle layer
119 * of the period finished event. */
120 if (s->active)
121 snd_pcm_period_elapsed(s->stream);
122
123 return IRQ_HANDLED;
124}
125
126static irqreturn_t psc_dma_bcom_irq_rx(int irq, void *_psc_dma_stream)
127{
128 struct psc_dma_stream *s = _psc_dma_stream;
129
130 spin_lock(&s->psc_dma->lock);
131 /* For each finished period, dequeue the completed period buffer
132 * and enqueue a new one in it's place. */
133 while (bcom_buffer_done(s->bcom_task)) {
134 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
135
136 s->period_current_pt += s->period_bytes;
137 if (s->period_current_pt >= s->period_end)
138 s->period_current_pt = s->period_start;
139 81
140 psc_dma_bcom_enqueue_next_buffer(s); 82 psc_dma_bcom_enqueue_next_buffer(s);
141 } 83 }
@@ -166,54 +108,38 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
166 struct snd_soc_pcm_runtime *rtd = substream->private_data; 108 struct snd_soc_pcm_runtime *rtd = substream->private_data;
167 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 109 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
168 struct snd_pcm_runtime *runtime = substream->runtime; 110 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct psc_dma_stream *s; 111 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
170 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 112 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
171 u16 imr; 113 u16 imr;
172 unsigned long flags; 114 unsigned long flags;
173 int i; 115 int i;
174 116
175 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
176 s = &psc_dma->capture;
177 else
178 s = &psc_dma->playback;
179
180 dev_dbg(psc_dma->dev, "psc_dma_trigger(substream=%p, cmd=%i)"
181 " stream_id=%i\n",
182 substream, cmd, substream->pstr->stream);
183
184 switch (cmd) { 117 switch (cmd) {
185 case SNDRV_PCM_TRIGGER_START: 118 case SNDRV_PCM_TRIGGER_START:
119 dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n",
120 substream->pstr->stream, runtime->frame_bits,
121 (int)runtime->period_size, runtime->periods);
186 s->period_bytes = frames_to_bytes(runtime, 122 s->period_bytes = frames_to_bytes(runtime,
187 runtime->period_size); 123 runtime->period_size);
188 s->period_start = virt_to_phys(runtime->dma_area); 124 s->period_next = 0;
189 s->period_end = s->period_start + 125 s->period_current = 0;
190 (s->period_bytes * runtime->periods);
191 s->period_next_pt = s->period_start;
192 s->period_current_pt = s->period_start;
193 s->period_size = runtime->period_size;
194 s->active = 1; 126 s->active = 1;
195 127 s->period_count = 0;
196 /* track appl_ptr so that we have a better chance of detecting
197 * end of stream and not over running it.
198 */
199 s->runtime = runtime; 128 s->runtime = runtime;
200 s->appl_ptr = s->runtime->control->appl_ptr -
201 (runtime->period_size * runtime->periods);
202 129
203 /* Fill up the bestcomm bd queue and enable DMA. 130 /* Fill up the bestcomm bd queue and enable DMA.
204 * This will begin filling the PSC's fifo. 131 * This will begin filling the PSC's fifo.
205 */ 132 */
206 spin_lock_irqsave(&psc_dma->lock, flags); 133 spin_lock_irqsave(&psc_dma->lock, flags);
207 134
208 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 135 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
209 bcom_gen_bd_rx_reset(s->bcom_task); 136 bcom_gen_bd_rx_reset(s->bcom_task);
210 for (i = 0; i < runtime->periods; i++) 137 else
211 if (!bcom_queue_full(s->bcom_task))
212 psc_dma_bcom_enqueue_next_buffer(s);
213 } else {
214 bcom_gen_bd_tx_reset(s->bcom_task); 138 bcom_gen_bd_tx_reset(s->bcom_task);
215 psc_dma_bcom_enqueue_tx(s); 139
216 } 140 for (i = 0; i < runtime->periods; i++)
141 if (!bcom_queue_full(s->bcom_task))
142 psc_dma_bcom_enqueue_next_buffer(s);
217 143
218 bcom_enable(s->bcom_task); 144 bcom_enable(s->bcom_task);
219 spin_unlock_irqrestore(&psc_dma->lock, flags); 145 spin_unlock_irqrestore(&psc_dma->lock, flags);
@@ -223,6 +149,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
223 break; 149 break;
224 150
225 case SNDRV_PCM_TRIGGER_STOP: 151 case SNDRV_PCM_TRIGGER_STOP:
152 dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n",
153 substream->pstr->stream, s->period_count);
226 s->active = 0; 154 s->active = 0;
227 155
228 spin_lock_irqsave(&psc_dma->lock, flags); 156 spin_lock_irqsave(&psc_dma->lock, flags);
@@ -236,7 +164,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
236 break; 164 break;
237 165
238 default: 166 default:
239 dev_dbg(psc_dma->dev, "invalid command\n"); 167 dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n",
168 substream->pstr->stream, cmd);
240 return -EINVAL; 169 return -EINVAL;
241 } 170 }
242 171
@@ -343,7 +272,7 @@ psc_dma_pointer(struct snd_pcm_substream *substream)
343 else 272 else
344 s = &psc_dma->playback; 273 s = &psc_dma->playback;
345 274
346 count = s->period_current_pt - s->period_start; 275 count = s->period_current * s->period_bytes;
347 276
348 return bytes_to_frames(substream->runtime, count); 277 return bytes_to_frames(substream->runtime, count);
349} 278}
@@ -532,11 +461,9 @@ int mpc5200_audio_dma_create(struct of_device *op)
532 461
533 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED, 462 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
534 "psc-dma-status", psc_dma); 463 "psc-dma-status", psc_dma);
535 rc |= request_irq(psc_dma->capture.irq, 464 rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED,
536 &psc_dma_bcom_irq_rx, IRQF_SHARED,
537 "psc-dma-capture", &psc_dma->capture); 465 "psc-dma-capture", &psc_dma->capture);
538 rc |= request_irq(psc_dma->playback.irq, 466 rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED,
539 &psc_dma_bcom_irq_tx, IRQF_SHARED,
540 "psc-dma-playback", &psc_dma->playback); 467 "psc-dma-playback", &psc_dma->playback);
541 if (rc) { 468 if (rc) {
542 ret = -ENODEV; 469 ret = -ENODEV;
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 8d396bb9d9fe..22208b373fb9 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -13,26 +13,25 @@
13 * @psc_dma: pointer back to parent psc_dma data structure 13 * @psc_dma: pointer back to parent psc_dma data structure
14 * @bcom_task: bestcomm task structure 14 * @bcom_task: bestcomm task structure
15 * @irq: irq number for bestcomm task 15 * @irq: irq number for bestcomm task
16 * @period_start: physical address of start of DMA region
17 * @period_end: physical address of end of DMA region 16 * @period_end: physical address of end of DMA region
18 * @period_next_pt: physical address of next DMA buffer to enqueue 17 * @period_next_pt: physical address of next DMA buffer to enqueue
19 * @period_bytes: size of DMA period in bytes 18 * @period_bytes: size of DMA period in bytes
19 * @ac97_slot_bits: Enable bits for turning on the correct AC97 slot
20 */ 20 */
21struct psc_dma_stream { 21struct psc_dma_stream {
22 struct snd_pcm_runtime *runtime; 22 struct snd_pcm_runtime *runtime;
23 snd_pcm_uframes_t appl_ptr;
24
25 int active; 23 int active;
26 struct psc_dma *psc_dma; 24 struct psc_dma *psc_dma;
27 struct bcom_task *bcom_task; 25 struct bcom_task *bcom_task;
28 int irq; 26 int irq;
29 struct snd_pcm_substream *stream; 27 struct snd_pcm_substream *stream;
30 dma_addr_t period_start; 28 int period_next;
31 dma_addr_t period_end; 29 int period_current;
32 dma_addr_t period_next_pt;
33 dma_addr_t period_current_pt;
34 int period_bytes; 30 int period_bytes;
35 int period_size; 31 int period_count;
32
33 /* AC97 state */
34 u32 ac97_slot_bits;
36}; 35};
37 36
38/** 37/**
@@ -73,6 +72,15 @@ struct psc_dma {
73 } stats; 72 } stats;
74}; 73};
75 74
75/* Utility for retrieving psc_dma_stream structure from a substream */
76inline struct psc_dma_stream *
77to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
78{
79 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
80 return &psc_dma->capture;
81 return &psc_dma->playback;
82}
83
76int mpc5200_audio_dma_create(struct of_device *op); 84int mpc5200_audio_dma_create(struct of_device *op);
77int mpc5200_audio_dma_destroy(struct of_device *op); 85int mpc5200_audio_dma_destroy(struct of_device *op);
78 86
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index c4ae3e096bb9..3dbc7f7cd7b9 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -130,6 +130,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
130 struct snd_soc_dai *cpu_dai) 130 struct snd_soc_dai *cpu_dai)
131{ 131{
132 struct psc_dma *psc_dma = cpu_dai->private_data; 132 struct psc_dma *psc_dma = cpu_dai->private_data;
133 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
133 134
134 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 135 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
135 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i" 136 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
@@ -140,20 +141,10 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
140 params_channels(params), params_rate(params), 141 params_channels(params), params_rate(params),
141 params_format(params)); 142 params_format(params));
142 143
143 144 /* Determine the set of enable bits to turn on */
144 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 145 s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;
145 if (params_channels(params) == 1) 146 if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)
146 psc_dma->slots |= 0x00000100; 147 s->ac97_slot_bits <<= 16;
147 else
148 psc_dma->slots |= 0x00000300;
149 } else {
150 if (params_channels(params) == 1)
151 psc_dma->slots |= 0x01000000;
152 else
153 psc_dma->slots |= 0x03000000;
154 }
155 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
156
157 return 0; 148 return 0;
158} 149}
159 150
@@ -163,6 +154,8 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
163{ 154{
164 struct psc_dma *psc_dma = cpu_dai->private_data; 155 struct psc_dma *psc_dma = cpu_dai->private_data;
165 156
157 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
158
166 if (params_channels(params) == 1) 159 if (params_channels(params) == 1)
167 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000); 160 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
168 else 161 else
@@ -176,14 +169,24 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
176{ 169{
177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 170 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 171 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
172 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
179 173
180 switch (cmd) { 174 switch (cmd) {
175 case SNDRV_PCM_TRIGGER_START:
176 dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",
177 substream->pstr->stream);
178
179 /* Set the slot enable bits */
180 psc_dma->slots |= s->ac97_slot_bits;
181 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
182 break;
183
181 case SNDRV_PCM_TRIGGER_STOP: 184 case SNDRV_PCM_TRIGGER_STOP:
182 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) 185 dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n",
183 psc_dma->slots &= 0xFFFF0000; 186 substream->pstr->stream);
184 else
185 psc_dma->slots &= 0x0000FFFF;
186 187
188 /* Clear the slot enable bits */
189 psc_dma->slots &= ~(s->ac97_slot_bits);
187 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots); 190 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
188 break; 191 break;
189 } 192 }
diff --git a/sound/soc/imx/mx27vis_wm8974.c b/sound/soc/imx/mx27vis_wm8974.c
index e4dcb539108a..0267d2d91685 100644
--- a/sound/soc/imx/mx27vis_wm8974.c
+++ b/sound/soc/imx/mx27vis_wm8974.c
@@ -157,7 +157,7 @@ static int mx27vis_hifi_hw_params(struct snd_pcm_substream *substream,
157 157
158 158
159 /* codec PLL input is 25 MHz */ 159 /* codec PLL input is 25 MHz */
160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG,
161 25000000, pll_out); 161 25000000, pll_out);
162 if (ret < 0) { 162 if (ret < 0) {
163 printk(KERN_ERR "Error when setting PLL input\n"); 163 printk(KERN_ERR "Error when setting PLL input\n");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 653a362425df..61952aa6cd5a 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -43,12 +43,13 @@ config SND_OMAP_SOC_OSK5912
43 Say Y if you want to add support for SoC audio on osk5912. 43 Say Y if you want to add support for SoC audio on osk5912.
44 44
45config SND_OMAP_SOC_OVERO 45config SND_OMAP_SOC_OVERO
46 tristate "SoC Audio support for Gumstix Overo" 46 tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35"
47 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO 47 depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35)
48 select SND_OMAP_SOC_MCBSP 48 select SND_OMAP_SOC_MCBSP
49 select SND_SOC_TWL4030 49 select SND_SOC_TWL4030
50 help 50 help
51 Say Y if you want to add support for SoC audio on the Gumstix Overo. 51 Say Y if you want to add support for SoC audio on the
52 Gumstix Overo or CompuLab CM-T35
52 53
53config SND_OMAP_SOC_OMAP2EVM 54config SND_OMAP_SOC_OMAP2EVM
54 tristate "SoC Audio support for OMAP2EVM board" 55 tristate "SoC Audio support for OMAP2EVM board"
@@ -66,6 +67,15 @@ config SND_OMAP_SOC_OMAP3EVM
66 help 67 help
67 Say Y if you want to add support for SoC audio on the omap3evm board. 68 Say Y if you want to add support for SoC audio on the omap3evm board.
68 69
70config SND_OMAP_SOC_AM3517EVM
71 tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
72 depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
73 select SND_OMAP_SOC_MCBSP
74 select SND_SOC_TLV320AIC23
75 help
76 Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
77 EVM.
78
69config SND_OMAP_SOC_SDP3430 79config SND_OMAP_SOC_SDP3430
70 tristate "SoC Audio support for Texas Instruments SDP3430" 80 tristate "SoC Audio support for Texas Instruments SDP3430"
71 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP 81 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
@@ -99,3 +109,10 @@ config SND_OMAP_SOC_ZOOM2
99 help 109 help
100 Say Y if you want to add support for Soc audio on Zoom2 board. 110 Say Y if you want to add support for Soc audio on Zoom2 board.
101 111
112config SND_OMAP_SOC_IGEP0020
113 tristate "SoC Audio support for IGEP v2"
114 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020
115 select SND_OMAP_SOC_MCBSP
116 select SND_SOC_TWL4030
117 help
118 Say Y if you want to add support for Soc audio on IGEP v2 board.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 02d69471dcb5..d49458a29bb7 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -12,10 +12,12 @@ snd-soc-osk5912-objs := osk5912.o
12snd-soc-overo-objs := overo.o 12snd-soc-overo-objs := overo.o
13snd-soc-omap2evm-objs := omap2evm.o 13snd-soc-omap2evm-objs := omap2evm.o
14snd-soc-omap3evm-objs := omap3evm.o 14snd-soc-omap3evm-objs := omap3evm.o
15snd-soc-am3517evm-objs := am3517evm.o
15snd-soc-sdp3430-objs := sdp3430.o 16snd-soc-sdp3430-objs := sdp3430.o
16snd-soc-omap3pandora-objs := omap3pandora.o 17snd-soc-omap3pandora-objs := omap3pandora.o
17snd-soc-omap3beagle-objs := omap3beagle.o 18snd-soc-omap3beagle-objs := omap3beagle.o
18snd-soc-zoom2-objs := zoom2.o 19snd-soc-zoom2-objs := zoom2.o
20snd-soc-igep0020-objs := igep0020.o
19 21
20obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 22obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
21obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o 23obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
@@ -23,7 +25,9 @@ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
23obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 25obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
24obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 26obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
25obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o 27obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
28obj-$(CONFIG_MACH_OMAP3517EVM) += snd-soc-am3517evm.o
26obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 29obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
27obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 30obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
28obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 31obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
29obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o 32obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
33obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
new file mode 100644
index 000000000000..135901b2ea11
--- /dev/null
+++ b/sound/soc/omap/am3517evm.c
@@ -0,0 +1,202 @@
1/*
2 * am3517evm.c -- ALSA SoC support for OMAP3517 / AM3517 EVM
3 *
4 * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
5 *
6 * Based on sound/soc/omap/beagle.c by Steve Sakoman
7 *
8 * Copyright (C) 2009 Texas Instruments Incorporated
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
15 * whether express or implied; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include <mach/gpio.h>
30#include <plat/mcbsp.h>
31
32#include "omap-mcbsp.h"
33#include "omap-pcm.h"
34
35#include "../codecs/tlv320aic23.h"
36
37#define CODEC_CLOCK 12000000
38
39static int am3517evm_hw_params(struct snd_pcm_substream *substream,
40 struct snd_pcm_hw_params *params)
41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
44 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
45 int ret;
46
47 /* Set codec DAI configuration */
48 ret = snd_soc_dai_set_fmt(codec_dai,
49 SND_SOC_DAIFMT_DSP_B |
50 SND_SOC_DAIFMT_NB_NF |
51 SND_SOC_DAIFMT_CBM_CFM);
52 if (ret < 0) {
53 printk(KERN_ERR "can't set codec DAI configuration\n");
54 return ret;
55 }
56
57 /* Set cpu DAI configuration */
58 ret = snd_soc_dai_set_fmt(cpu_dai,
59 SND_SOC_DAIFMT_DSP_B |
60 SND_SOC_DAIFMT_NB_NF |
61 SND_SOC_DAIFMT_CBM_CFM);
62 if (ret < 0) {
63 printk(KERN_ERR "can't set cpu DAI configuration\n");
64 return ret;
65 }
66
67 /* Set the codec system clock for DAC and ADC */
68 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
69 CODEC_CLOCK, SND_SOC_CLOCK_IN);
70 if (ret < 0) {
71 printk(KERN_ERR "can't set codec system clock\n");
72 return ret;
73 }
74
75 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0,
76 SND_SOC_CLOCK_IN);
77 if (ret < 0) {
78 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n");
79 return ret;
80 }
81
82 snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
83 SND_SOC_CLOCK_IN);
84 if (ret < 0) {
85 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
86 return ret;
87 }
88
89 return 0;
90}
91
92static struct snd_soc_ops am3517evm_ops = {
93 .hw_params = am3517evm_hw_params,
94};
95
96/* am3517evm machine dapm widgets */
97static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
98 SND_SOC_DAPM_HP("Line Out", NULL),
99 SND_SOC_DAPM_LINE("Line In", NULL),
100 SND_SOC_DAPM_MIC("Mic In", NULL),
101};
102
103static const struct snd_soc_dapm_route audio_map[] = {
104 /* Line Out connected to LLOUT, RLOUT */
105 {"Line Out", NULL, "LOUT"},
106 {"Line Out", NULL, "ROUT"},
107
108 {"LLINEIN", NULL, "Line In"},
109 {"RLINEIN", NULL, "Line In"},
110
111 {"MICIN", NULL, "Mic In"},
112};
113
114static int am3517evm_aic23_init(struct snd_soc_codec *codec)
115{
116 /* Add am3517-evm specific widgets */
117 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
118 ARRAY_SIZE(tlv320aic23_dapm_widgets));
119
120 /* Set up davinci-evm specific audio path audio_map */
121 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
122
123 /* always connected */
124 snd_soc_dapm_enable_pin(codec, "Line Out");
125 snd_soc_dapm_enable_pin(codec, "Line In");
126 snd_soc_dapm_enable_pin(codec, "Mic In");
127
128 snd_soc_dapm_sync(codec);
129
130 return 0;
131}
132
133/* Digital audio interface glue - connects codec <--> CPU */
134static struct snd_soc_dai_link am3517evm_dai = {
135 .name = "TLV320AIC23",
136 .stream_name = "AIC23",
137 .cpu_dai = &omap_mcbsp_dai[0],
138 .codec_dai = &tlv320aic23_dai,
139 .init = am3517evm_aic23_init,
140 .ops = &am3517evm_ops,
141};
142
143/* Audio machine driver */
144static struct snd_soc_card snd_soc_am3517evm = {
145 .name = "am3517evm",
146 .platform = &omap_soc_platform,
147 .dai_link = &am3517evm_dai,
148 .num_links = 1,
149};
150
151/* Audio subsystem */
152static struct snd_soc_device am3517evm_snd_devdata = {
153 .card = &snd_soc_am3517evm,
154 .codec_dev = &soc_codec_dev_tlv320aic23,
155};
156
157static struct platform_device *am3517evm_snd_device;
158
159static int __init am3517evm_soc_init(void)
160{
161 int ret;
162
163 if (!machine_is_omap3517evm()) {
164 pr_err("Not OMAP3517 / AM3517 EVM!\n");
165 return -ENODEV;
166 }
167 pr_info("OMAP3517 / AM3517 EVM SoC init\n");
168
169 am3517evm_snd_device = platform_device_alloc("soc-audio", -1);
170 if (!am3517evm_snd_device) {
171 printk(KERN_ERR "Platform device allocation failed\n");
172 return -ENOMEM;
173 }
174
175 platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata);
176 am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev;
177 *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */
178
179 ret = platform_device_add(am3517evm_snd_device);
180 if (ret)
181 goto err1;
182
183 return 0;
184
185err1:
186 printk(KERN_ERR "Unable to add platform device\n");
187 platform_device_put(am3517evm_snd_device);
188
189 return ret;
190}
191
192static void __exit am3517evm_soc_exit(void)
193{
194 platform_device_unregister(am3517evm_snd_device);
195}
196
197module_init(am3517evm_soc_init);
198module_exit(am3517evm_soc_exit);
199
200MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
201MODULE_DESCRIPTION("ALSA SoC OMAP3517 / AM3517 EVM");
202MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 5a5166ac7279..ae0fc9b135d4 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -40,7 +40,7 @@
40 40
41 41
42/* Board specific DAPM widgets */ 42/* Board specific DAPM widgets */
43 const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { 43static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
44 /* Handset */ 44 /* Handset */
45 SND_SOC_DAPM_MIC("Mouthpiece", NULL), 45 SND_SOC_DAPM_MIC("Mouthpiece", NULL),
46 SND_SOC_DAPM_HP("Earpiece", NULL), 46 SND_SOC_DAPM_HP("Earpiece", NULL),
@@ -81,7 +81,7 @@ static const char *ams_delta_audio_mode[] =
81 (1 << AMS_DELTA_SPEAKER)) 81 (1 << AMS_DELTA_SPEAKER))
82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) 82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
83 83
84unsigned short ams_delta_audio_mode_pins[] = { 84static const unsigned short ams_delta_audio_mode_pins[] = {
85 AMS_DELTA_MIXED, 85 AMS_DELTA_MIXED,
86 AMS_DELTA_HANDSET, 86 AMS_DELTA_HANDSET,
87 AMS_DELTA_HANDSFREE, 87 AMS_DELTA_HANDSFREE,
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
new file mode 100644
index 000000000000..3583c429f9be
--- /dev/null
+++ b/sound/soc/omap/igep0020.c
@@ -0,0 +1,148 @@
1/*
2 * igep0020.c -- SoC audio for IGEP v2
3 *
4 * Based on sound/soc/omap/overo.c by Steve Sakoman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <plat/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38static int igep2_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 int ret;
45
46 /* Set codec DAI configuration */
47 ret = snd_soc_dai_set_fmt(codec_dai,
48 SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM);
51 if (ret < 0) {
52 printk(KERN_ERR "can't set codec DAI configuration\n");
53 return ret;
54 }
55
56 /* Set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai,
58 SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBM_CFM);
61 if (ret < 0) {
62 printk(KERN_ERR "can't set cpu DAI configuration\n");
63 return ret;
64 }
65
66 /* Set the codec system clock for DAC and ADC */
67 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
68 SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 printk(KERN_ERR "can't set codec system clock\n");
71 return ret;
72 }
73
74 return 0;
75}
76
77static struct snd_soc_ops igep2_ops = {
78 .hw_params = igep2_hw_params,
79};
80
81/* Digital audio interface glue - connects codec <--> CPU */
82static struct snd_soc_dai_link igep2_dai = {
83 .name = "TWL4030",
84 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
87 .ops = &igep2_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_igep2 = {
92 .name = "igep2",
93 .platform = &omap_soc_platform,
94 .dai_link = &igep2_dai,
95 .num_links = 1,
96};
97
98/* Audio subsystem */
99static struct snd_soc_device igep2_snd_devdata = {
100 .card = &snd_soc_card_igep2,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *igep2_snd_device;
105
106static int __init igep2_soc_init(void)
107{
108 int ret;
109
110 if (!machine_is_igep0020()) {
111 pr_debug("Not IGEP v2!\n");
112 return -ENODEV;
113 }
114 printk(KERN_INFO "IGEP v2 SoC init\n");
115
116 igep2_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!igep2_snd_device) {
118 printk(KERN_ERR "Platform device allocation failed\n");
119 return -ENOMEM;
120 }
121
122 platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata);
123 igep2_snd_devdata.dev = &igep2_snd_device->dev;
124 *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */
125
126 ret = platform_device_add(igep2_snd_device);
127 if (ret)
128 goto err1;
129
130 return 0;
131
132err1:
133 printk(KERN_ERR "Unable to add platform device\n");
134 platform_device_put(igep2_snd_device);
135
136 return ret;
137}
138module_init(igep2_soc_init);
139
140static void __exit igep2_soc_exit(void)
141{
142 platform_device_unregister(igep2_snd_device);
143}
144module_exit(igep2_soc_exit);
145
146MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>");
147MODULE_DESCRIPTION("ALSA SoC IGEP v2");
148MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 3341f49402ca..45be94201c89 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -49,6 +49,8 @@ struct omap_mcbsp_data {
49 */ 49 */
50 int active; 50 int active;
51 int configured; 51 int configured;
52 unsigned int in_freq;
53 int clk_div;
52}; 54};
53 55
54#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) 56#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
@@ -257,7 +259,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
257 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 259 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
258 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; 260 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
259 unsigned long port; 261 unsigned long port;
260 unsigned int format; 262 unsigned int format, div, framesize, master;
261 263
262 if (cpu_class_is_omap1()) { 264 if (cpu_class_is_omap1()) {
263 dma = omap1_dma_reqs[bus_id][substream->stream]; 265 dma = omap1_dma_reqs[bus_id][substream->stream];
@@ -294,28 +296,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
294 296
295 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; 297 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
296 wpf = channels = params_channels(params); 298 wpf = channels = params_channels(params);
297 switch (channels) { 299 if (channels == 2 && format == SND_SOC_DAIFMT_I2S) {
298 case 2: 300 /* Use dual-phase frames */
299 if (format == SND_SOC_DAIFMT_I2S) { 301 regs->rcr2 |= RPHASE;
300 /* Use dual-phase frames */ 302 regs->xcr2 |= XPHASE;
301 regs->rcr2 |= RPHASE; 303 /* Set 1 word per (McBSP) frame for phase1 and phase2 */
302 regs->xcr2 |= XPHASE; 304 wpf--;
303 /* Set 1 word per (McBSP) frame for phase1 and phase2 */ 305 regs->rcr2 |= RFRLEN2(wpf - 1);
304 wpf--; 306 regs->xcr2 |= XFRLEN2(wpf - 1);
305 regs->rcr2 |= RFRLEN2(wpf - 1);
306 regs->xcr2 |= XFRLEN2(wpf - 1);
307 }
308 case 1:
309 case 4:
310 /* Set word per (McBSP) frame for phase1 */
311 regs->rcr1 |= RFRLEN1(wpf - 1);
312 regs->xcr1 |= XFRLEN1(wpf - 1);
313 break;
314 default:
315 /* Unsupported number of channels */
316 return -EINVAL;
317 } 307 }
318 308
309 regs->rcr1 |= RFRLEN1(wpf - 1);
310 regs->xcr1 |= XFRLEN1(wpf - 1);
311
319 switch (params_format(params)) { 312 switch (params_format(params)) {
320 case SNDRV_PCM_FORMAT_S16_LE: 313 case SNDRV_PCM_FORMAT_S16_LE:
321 /* Set word lengths */ 314 /* Set word lengths */
@@ -330,15 +323,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
330 return -EINVAL; 323 return -EINVAL;
331 } 324 }
332 325
326 /* In McBSP master modes, FRAME (i.e. sample rate) is generated
327 * by _counting_ BCLKs. Calculate frame size in BCLKs */
328 master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
329 if (master == SND_SOC_DAIFMT_CBS_CFS) {
330 div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
331 framesize = (mcbsp_data->in_freq / div) / params_rate(params);
332
333 if (framesize < wlen * channels) {
334 printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
335 "channels\n", __func__);
336 return -EINVAL;
337 }
338 } else
339 framesize = wlen * channels;
340
333 /* Set FS period and length in terms of bit clock periods */ 341 /* Set FS period and length in terms of bit clock periods */
334 switch (format) { 342 switch (format) {
335 case SND_SOC_DAIFMT_I2S: 343 case SND_SOC_DAIFMT_I2S:
336 regs->srgr2 |= FPER(wlen * channels - 1); 344 regs->srgr2 |= FPER(framesize - 1);
337 regs->srgr1 |= FWID(wlen - 1); 345 regs->srgr1 |= FWID((framesize >> 1) - 1);
338 break; 346 break;
339 case SND_SOC_DAIFMT_DSP_A: 347 case SND_SOC_DAIFMT_DSP_A:
340 case SND_SOC_DAIFMT_DSP_B: 348 case SND_SOC_DAIFMT_DSP_B:
341 regs->srgr2 |= FPER(wlen * channels - 1); 349 regs->srgr2 |= FPER(framesize - 1);
342 regs->srgr1 |= FWID(0); 350 regs->srgr1 |= FWID(0);
343 break; 351 break;
344 } 352 }
@@ -454,6 +462,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
454 if (div_id != OMAP_MCBSP_CLKGDV) 462 if (div_id != OMAP_MCBSP_CLKGDV)
455 return -ENODEV; 463 return -ENODEV;
456 464
465 mcbsp_data->clk_div = div;
457 regs->srgr1 |= CLKGDV(div - 1); 466 regs->srgr1 |= CLKGDV(div - 1);
458 467
459 return 0; 468 return 0;
@@ -554,6 +563,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
554 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 563 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
555 int err = 0; 564 int err = 0;
556 565
566 mcbsp_data->in_freq = freq;
567
557 switch (clk_id) { 568 switch (clk_id) {
558 case OMAP_MCBSP_SYSCLK_CLK: 569 case OMAP_MCBSP_SYSCLK_CLK:
559 regs->srgr2 |= CLKSM; 570 regs->srgr2 |= CLKSM;
@@ -598,13 +609,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
598 .id = (link_id), \ 609 .id = (link_id), \
599 .playback = { \ 610 .playback = { \
600 .channels_min = 1, \ 611 .channels_min = 1, \
601 .channels_max = 4, \ 612 .channels_max = 16, \
602 .rates = OMAP_MCBSP_RATES, \ 613 .rates = OMAP_MCBSP_RATES, \
603 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 614 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
604 }, \ 615 }, \
605 .capture = { \ 616 .capture = { \
606 .channels_min = 1, \ 617 .channels_min = 1, \
607 .channels_max = 4, \ 618 .channels_max = 16, \
608 .rates = OMAP_MCBSP_RATES, \ 619 .rates = OMAP_MCBSP_RATES, \
609 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 620 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
610 }, \ 621 }, \
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 13aa380de162..f484dcd63408 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -93,10 +93,17 @@ static struct snd_soc_card snd_soc_omap3evm = {
93 .num_links = 1, 93 .num_links = 1,
94}; 94};
95 95
96/* twl4030 setup */
97static struct twl4030_setup_data twl4030_setup = {
98 .ramp_delay_value = 4,
99 .sysclk = 26000,
100};
101
96/* Audio subsystem */ 102/* Audio subsystem */
97static struct snd_soc_device omap3evm_snd_devdata = { 103static struct snd_soc_device omap3evm_snd_devdata = {
98 .card = &snd_soc_omap3evm, 104 .card = &snd_soc_omap3evm,
99 .codec_dev = &soc_codec_dev_twl4030, 105 .codec_dev = &soc_codec_dev_twl4030,
106 .codec_data = &twl4030_setup,
100}; 107};
101 108
102static struct platform_device *omap3evm_snd_device; 109static struct platform_device *omap3evm_snd_device;
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 0cd06f5dd356..71b2c161158d 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -40,9 +40,12 @@
40 40
41#define PREFIX "ASoC omap3pandora: " 41#define PREFIX "ASoC omap3pandora: "
42 42
43static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, 43static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream,
44 struct snd_soc_dai *cpu_dai, unsigned int fmt) 44 struct snd_pcm_hw_params *params, unsigned int fmt)
45{ 45{
46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
47 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
48 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
46 int ret; 49 int ret;
47 50
48 /* Set codec DAI configuration */ 51 /* Set codec DAI configuration */
@@ -68,8 +71,9 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
68 } 71 }
69 72
70 /* Set McBSP clock to external */ 73 /* Set McBSP clock to external */
71 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0, 74 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT,
72 SND_SOC_CLOCK_IN); 75 256 * params_rate(params),
76 SND_SOC_CLOCK_IN);
73 if (ret < 0) { 77 if (ret < 0) {
74 pr_err(PREFIX "can't set cpu system clock\n"); 78 pr_err(PREFIX "can't set cpu system clock\n");
75 return ret; 79 return ret;
@@ -87,11 +91,7 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
87static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, 91static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *params) 92 struct snd_pcm_hw_params *params)
89{ 93{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data; 94 return omap3pandora_cmn_hw_params(substream, params,
91 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
93
94 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
95 SND_SOC_DAIFMT_I2S | 95 SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_IB_NF | 96 SND_SOC_DAIFMT_IB_NF |
97 SND_SOC_DAIFMT_CBS_CFS); 97 SND_SOC_DAIFMT_CBS_CFS);
@@ -100,11 +100,7 @@ static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
100static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream, 100static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
101 struct snd_pcm_hw_params *params) 101 struct snd_pcm_hw_params *params)
102{ 102{
103 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 return omap3pandora_cmn_hw_params(substream, params,
104 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
105 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
106
107 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
108 SND_SOC_DAIFMT_I2S | 104 SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF | 105 SND_SOC_DAIFMT_NB_NF |
110 SND_SOC_DAIFMT_CBS_CFS); 106 SND_SOC_DAIFMT_CBS_CFS);
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index ec4f8fd8b3a2..97a4d6308bd6 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -107,8 +107,8 @@ static int __init overo_soc_init(void)
107{ 107{
108 int ret; 108 int ret;
109 109
110 if (!machine_is_overo()) { 110 if (!(machine_is_overo() || machine_is_cm_t35())) {
111 pr_debug("Not Overo!\n"); 111 pr_debug("Incomatible machine!\n");
112 return -ENODEV; 112 return -ENODEV;
113 } 113 }
114 printk(KERN_INFO "overo SoC init\n"); 114 printk(KERN_INFO "overo SoC init\n");
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index dcb3181bb340..376e14a9c273 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -90,7 +90,8 @@ config SND_PXA2XX_SOC_E800
90 90
91config SND_PXA2XX_SOC_EM_X270 91config SND_PXA2XX_SOC_EM_X270
92 tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300" 92 tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300"
93 depends on SND_PXA2XX_SOC && MACH_EM_X270 93 depends on SND_PXA2XX_SOC && (MACH_EM_X270 || MACH_EXEDA || \
94 MACH_CM_X300)
94 select SND_PXA2XX_SOC_AC97 95 select SND_PXA2XX_SOC_AC97
95 select SND_SOC_WM9712 96 select SND_SOC_WM9712
96 help 97 help
@@ -117,6 +118,15 @@ config SND_SOC_ZYLONITE
117 Say Y if you want to add support for SoC audio on the 118 Say Y if you want to add support for SoC audio on the
118 Marvell Zylonite reference platform. 119 Marvell Zylonite reference platform.
119 120
121config SND_SOC_RAUMFELD
122 tristate "SoC Audio support Raumfeld audio adapter"
123 depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR)
124 select SND_PXA_SOC_SSP
125 select SND_SOC_CS4270
126 select SND_SOC_AK4104
127 help
128 Say Y if you want to add support for SoC audio on Raumfeld devices
129
120config SND_PXA2XX_SOC_MAGICIAN 130config SND_PXA2XX_SOC_MAGICIAN
121 tristate "SoC Audio support for HTC Magician" 131 tristate "SoC Audio support for HTC Magician"
122 depends on SND_PXA2XX_SOC && MACH_MAGICIAN 132 depends on SND_PXA2XX_SOC && MACH_MAGICIAN
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 6e096b480335..f3e08fd40ca2 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -23,6 +23,7 @@ snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o 23snd-soc-magician-objs := magician.o
24snd-soc-mioa701-objs := mioa701_wm9713.o 24snd-soc-mioa701-objs := mioa701_wm9713.o
25snd-soc-imote2-objs := imote2.o 25snd-soc-imote2-objs := imote2.o
26snd-soc-raumfeld-objs := raumfeld.o
26 27
27obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 28obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
28obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 29obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -37,3 +38,4 @@ obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
37obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 38obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
38obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 39obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
39obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 40obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
41obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 9f7c61e23daf..4c8d99a8d386 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -213,7 +213,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
213 return ret; 213 return ret;
214 214
215 /* set SSP audio pll clock */ 215 /* set SSP audio pll clock */
216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps); 216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps);
217 if (ret < 0) 217 if (ret < 0)
218 return ret; 218 return ret;
219 219
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index d11a6d7e384a..3bd7712f029b 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -305,8 +305,8 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
305/* 305/*
306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only) 306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
307 */ 307 */
308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, 308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
309 int pll_id, unsigned int freq_in, unsigned int freq_out) 309 int source, unsigned int freq_in, unsigned int freq_out)
310{ 310{
311 struct ssp_priv *priv = cpu_dai->private_data; 311 struct ssp_priv *priv = cpu_dai->private_data;
312 struct ssp_device *ssp = priv->dev.ssp; 312 struct ssp_device *ssp = priv->dev.ssp;
@@ -760,13 +760,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
760 .resume = pxa_ssp_resume, 760 .resume = pxa_ssp_resume,
761 .playback = { 761 .playback = {
762 .channels_min = 1, 762 .channels_min = 1,
763 .channels_max = 2, 763 .channels_max = 8,
764 .rates = PXA_SSP_RATES, 764 .rates = PXA_SSP_RATES,
765 .formats = PXA_SSP_FORMATS, 765 .formats = PXA_SSP_FORMATS,
766 }, 766 },
767 .capture = { 767 .capture = {
768 .channels_min = 1, 768 .channels_min = 1,
769 .channels_max = 2, 769 .channels_max = 8,
770 .rates = PXA_SSP_RATES, 770 .rates = PXA_SSP_RATES,
771 .formats = PXA_SSP_FORMATS, 771 .formats = PXA_SSP_FORMATS,
772 }, 772 },
@@ -780,13 +780,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
780 .resume = pxa_ssp_resume, 780 .resume = pxa_ssp_resume,
781 .playback = { 781 .playback = {
782 .channels_min = 1, 782 .channels_min = 1,
783 .channels_max = 2, 783 .channels_max = 8,
784 .rates = PXA_SSP_RATES, 784 .rates = PXA_SSP_RATES,
785 .formats = PXA_SSP_FORMATS, 785 .formats = PXA_SSP_FORMATS,
786 }, 786 },
787 .capture = { 787 .capture = {
788 .channels_min = 1, 788 .channels_min = 1,
789 .channels_max = 2, 789 .channels_max = 8,
790 .rates = PXA_SSP_RATES, 790 .rates = PXA_SSP_RATES,
791 .formats = PXA_SSP_FORMATS, 791 .formats = PXA_SSP_FORMATS,
792 }, 792 },
@@ -801,13 +801,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
801 .resume = pxa_ssp_resume, 801 .resume = pxa_ssp_resume,
802 .playback = { 802 .playback = {
803 .channels_min = 1, 803 .channels_min = 1,
804 .channels_max = 2, 804 .channels_max = 8,
805 .rates = PXA_SSP_RATES, 805 .rates = PXA_SSP_RATES,
806 .formats = PXA_SSP_FORMATS, 806 .formats = PXA_SSP_FORMATS,
807 }, 807 },
808 .capture = { 808 .capture = {
809 .channels_min = 1, 809 .channels_min = 1,
810 .channels_max = 2, 810 .channels_max = 8,
811 .rates = PXA_SSP_RATES, 811 .rates = PXA_SSP_RATES,
812 .formats = PXA_SSP_FORMATS, 812 .formats = PXA_SSP_FORMATS,
813 }, 813 },
@@ -822,13 +822,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
822 .resume = pxa_ssp_resume, 822 .resume = pxa_ssp_resume,
823 .playback = { 823 .playback = {
824 .channels_min = 1, 824 .channels_min = 1,
825 .channels_max = 2, 825 .channels_max = 8,
826 .rates = PXA_SSP_RATES, 826 .rates = PXA_SSP_RATES,
827 .formats = PXA_SSP_FORMATS, 827 .formats = PXA_SSP_FORMATS,
828 }, 828 },
829 .capture = { 829 .capture = {
830 .channels_min = 1, 830 .channels_min = 1,
831 .channels_max = 2, 831 .channels_max = 8,
832 .rates = PXA_SSP_RATES, 832 .rates = PXA_SSP_RATES,
833 .formats = PXA_SSP_FORMATS, 833 .formats = PXA_SSP_FORMATS,
834 }, 834 },
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
new file mode 100644
index 000000000000..acfce1c0f1c9
--- /dev/null
+++ b/sound/soc/pxa/raumfeld.c
@@ -0,0 +1,335 @@
1/*
2 * raumfeld_audio.c -- SoC audio for Raumfeld audio devices
3 *
4 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
5 *
6 * based on code from:
7 *
8 * Wolfson Microelectronics PLC.
9 * Openedhand Ltd.
10 * Liam Girdwood <lrg@slimlogic.co.uk>
11 * Richard Purdie <richard@openedhand.com>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/module.h>
20#include <linux/i2c.h>
21#include <linux/delay.h>
22#include <linux/gpio.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28
29#include "../codecs/cs4270.h"
30#include "../codecs/ak4104.h"
31#include "pxa2xx-pcm.h"
32#include "pxa-ssp.h"
33
34#define GPIO_SPDIF_RESET (38)
35#define GPIO_MCLK_RESET (111)
36#define GPIO_CODEC_RESET (120)
37
38static struct i2c_client *max9486_client;
39static struct i2c_board_info max9486_hwmon_info = {
40 I2C_BOARD_INFO("max9485", 0x63),
41};
42
43#define MAX9485_MCLK_FREQ_112896 0x22
44#define MAX9485_MCLK_FREQ_122880 0x23
45
46static void set_max9485_clk(char clk)
47{
48 i2c_master_send(max9486_client, &clk, 1);
49}
50
51static void raumfeld_enable_audio(bool en)
52{
53 if (en) {
54 gpio_set_value(GPIO_MCLK_RESET, 1);
55
56 /* wait some time to let the clocks become stable */
57 msleep(100);
58
59 gpio_set_value(GPIO_SPDIF_RESET, 1);
60 gpio_set_value(GPIO_CODEC_RESET, 1);
61 } else {
62 gpio_set_value(GPIO_MCLK_RESET, 0);
63 gpio_set_value(GPIO_SPDIF_RESET, 0);
64 gpio_set_value(GPIO_CODEC_RESET, 0);
65 }
66}
67
68/* CS4270 */
69static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
70{
71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
73
74 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
75
76 return snd_soc_dai_set_sysclk(codec_dai, 0, 11289600, 0);
77}
78
79static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream,
80 struct snd_pcm_hw_params *params)
81{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
84 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
85 unsigned int fmt, clk = 0;
86 int ret = 0;
87
88 switch (params_rate(params)) {
89 case 8000:
90 case 16000:
91 case 48000:
92 case 96000:
93 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
94 clk = 12288000;
95 break;
96 case 11025:
97 case 22050:
98 case 44100:
99 case 88200:
100 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
101 clk = 11289600;
102 break;
103 }
104
105 fmt = SND_SOC_DAIFMT_I2S |
106 SND_SOC_DAIFMT_NB_NF |
107 SND_SOC_DAIFMT_CBS_CFS;
108
109 /* setup the CODEC DAI */
110 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
111 if (ret < 0)
112 return ret;
113
114 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0);
115 if (ret < 0)
116 return ret;
117
118 /* setup the CPU DAI */
119 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
120 if (ret < 0)
121 return ret;
122
123 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
124 if (ret < 0)
125 return ret;
126
127 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
128 if (ret < 0)
129 return ret;
130
131 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, 0, 1);
132 if (ret < 0)
133 return ret;
134
135 return 0;
136}
137
138static struct snd_soc_ops raumfeld_cs4270_ops = {
139 .startup = raumfeld_cs4270_startup,
140 .hw_params = raumfeld_cs4270_hw_params,
141};
142
143static int raumfeld_line_suspend(struct platform_device *pdev, pm_message_t state)
144{
145 raumfeld_enable_audio(false);
146 return 0;
147}
148
149static int raumfeld_line_resume(struct platform_device *pdev)
150{
151 raumfeld_enable_audio(true);
152 return 0;
153}
154
155static struct snd_soc_dai_link raumfeld_line_dai = {
156 .name = "CS4270",
157 .stream_name = "CS4270",
158 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
159 .codec_dai = &cs4270_dai,
160 .ops = &raumfeld_cs4270_ops,
161};
162
163static struct snd_soc_card snd_soc_line_raumfeld = {
164 .name = "Raumfeld analog",
165 .platform = &pxa2xx_soc_platform,
166 .dai_link = &raumfeld_line_dai,
167 .suspend_post = raumfeld_line_suspend,
168 .resume_pre = raumfeld_line_resume,
169 .num_links = 1,
170};
171
172
173/* AK4104 */
174
175static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream,
176 struct snd_pcm_hw_params *params)
177{
178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
180 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
181 int fmt, ret = 0, clk = 0;
182
183 switch (params_rate(params)) {
184 case 8000:
185 case 16000:
186 case 48000:
187 case 96000:
188 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
189 clk = 12288000;
190 break;
191 case 11025:
192 case 22050:
193 case 44100:
194 case 88200:
195 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
196 clk = 11289600;
197 break;
198 }
199
200 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
201
202 /* setup the CODEC DAI */
203 ret = snd_soc_dai_set_fmt(codec_dai, fmt | SND_SOC_DAIFMT_CBS_CFS);
204 if (ret < 0)
205 return ret;
206
207 /* setup the CPU DAI */
208 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
209 if (ret < 0)
210 return ret;
211
212 ret = snd_soc_dai_set_fmt(cpu_dai, fmt | SND_SOC_DAIFMT_CBS_CFS);
213 if (ret < 0)
214 return ret;
215
216 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
217 if (ret < 0)
218 return ret;
219
220 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, 0, 1);
221 if (ret < 0)
222 return ret;
223
224 return 0;
225}
226
227static struct snd_soc_ops raumfeld_ak4104_ops = {
228 .hw_params = raumfeld_ak4104_hw_params,
229};
230
231static struct snd_soc_dai_link raumfeld_spdif_dai = {
232 .name = "ak4104",
233 .stream_name = "Playback",
234 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP2],
235 .codec_dai = &ak4104_dai,
236 .ops = &raumfeld_ak4104_ops,
237};
238
239static struct snd_soc_card snd_soc_spdif_raumfeld = {
240 .name = "Raumfeld S/PDIF",
241 .platform = &pxa2xx_soc_platform,
242 .dai_link = &raumfeld_spdif_dai,
243 .num_links = 1
244};
245
246/* raumfeld_audio audio subsystem */
247static struct snd_soc_device raumfeld_line_devdata = {
248 .card = &snd_soc_line_raumfeld,
249 .codec_dev = &soc_codec_device_cs4270,
250};
251
252static struct snd_soc_device raumfeld_spdif_devdata = {
253 .card = &snd_soc_spdif_raumfeld,
254 .codec_dev = &soc_codec_device_ak4104,
255};
256
257static struct platform_device *raumfeld_audio_line_device;
258static struct platform_device *raumfeld_audio_spdif_device;
259
260static int __init raumfeld_audio_init(void)
261{
262 int ret;
263
264 if (!machine_is_raumfeld_speaker() &&
265 !machine_is_raumfeld_connector())
266 return 0;
267
268 max9486_client = i2c_new_device(i2c_get_adapter(0),
269 &max9486_hwmon_info);
270
271 if (!max9486_client)
272 return -ENOMEM;
273
274 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
275
276 /* LINE */
277 raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0);
278 if (!raumfeld_audio_line_device)
279 return -ENOMEM;
280
281 platform_set_drvdata(raumfeld_audio_line_device,
282 &raumfeld_line_devdata);
283 raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev;
284 ret = platform_device_add(raumfeld_audio_line_device);
285 if (ret)
286 platform_device_put(raumfeld_audio_line_device);
287
288 /* no S/PDIF on Speakers */
289 if (machine_is_raumfeld_speaker())
290 return ret;
291
292 /* S/PDIF */
293 raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1);
294 if (!raumfeld_audio_spdif_device) {
295 platform_device_put(raumfeld_audio_line_device);
296 return -ENOMEM;
297 }
298
299 platform_set_drvdata(raumfeld_audio_spdif_device,
300 &raumfeld_spdif_devdata);
301 raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev;
302 ret = platform_device_add(raumfeld_audio_spdif_device);
303 if (ret) {
304 platform_device_put(raumfeld_audio_line_device);
305 platform_device_put(raumfeld_audio_spdif_device);
306 }
307
308 raumfeld_enable_audio(true);
309
310 return ret;
311}
312
313static void __exit raumfeld_audio_exit(void)
314{
315 raumfeld_enable_audio(false);
316
317 platform_device_unregister(raumfeld_audio_line_device);
318
319 if (machine_is_raumfeld_connector())
320 platform_device_unregister(raumfeld_audio_spdif_device);
321
322 i2c_unregister_device(max9486_client);
323
324 gpio_free(GPIO_MCLK_RESET);
325 gpio_free(GPIO_CODEC_RESET);
326 gpio_free(GPIO_SPDIF_RESET);
327}
328
329module_init(raumfeld_audio_init);
330module_exit(raumfeld_audio_exit);
331
332/* Module information */
333MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
334MODULE_DESCRIPTION("Raumfeld audio SoC");
335MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index 9a386b4c4ed1..dd678ae24398 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -74,7 +74,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
74static int zylonite_wm9713_init(struct snd_soc_codec *codec) 74static int zylonite_wm9713_init(struct snd_soc_codec *codec)
75{ 75{
76 if (clk_pout) 76 if (clk_pout)
77 snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); 77 snd_soc_dai_set_pll(&codec->dai[0], 0, 0,
78 clk_get_rate(pout), 0);
78 79
79 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, 80 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
80 ARRAY_SIZE(zylonite_dapm_widgets)); 81 ARRAY_SIZE(zylonite_dapm_widgets));
@@ -128,7 +129,7 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
128 if (ret < 0) 129 if (ret < 0)
129 return ret; 130 return ret;
130 131
131 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); 132 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out);
132 if (ret < 0) 133 if (ret < 0)
133 return ret; 134 return ret;
134 135
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 923428fc1adb..b489f1ae103d 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -24,6 +24,9 @@ config SND_S3C64XX_SOC_I2S
24 select SND_S3C_I2SV2_SOC 24 select SND_S3C_I2SV2_SOC
25 select S3C64XX_DMA 25 select S3C64XX_DMA
26 26
27config SND_S3C_SOC_PCM
28 tristate
29
27config SND_S3C2443_SOC_AC97 30config SND_S3C2443_SOC_AC97
28 tristate 31 tristate
29 select S3C2410_DMA 32 select S3C2410_DMA
@@ -56,6 +59,15 @@ config SND_S3C24XX_SOC_JIVE_WM8750
56 help 59 help
57 Sat Y if you want to add support for SoC audio on the Jive. 60 Sat Y if you want to add support for SoC audio on the Jive.
58 61
62config SND_S3C64XX_SOC_WM8580
63 tristate "SoC I2S Audio support for WM8580 on SMDK64XX"
64 depends on SND_S3C24XX_SOC && (MACH_SMDK6400 || MACH_SMDK6410)
65 depends on BROKEN
66 select SND_SOC_WM8580
67 select SND_S3C64XX_SOC_I2S
68 help
69 Sat Y if you want to add support for SoC audio on the SMDK64XX.
70
59config SND_S3C24XX_SOC_SMDK2443_WM9710 71config SND_S3C24XX_SOC_SMDK2443_WM9710
60 tristate "SoC AC97 Audio support for SMDK2443 - WM9710" 72 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
61 depends on SND_S3C24XX_SOC && MACH_SMDK2443 73 depends on SND_S3C24XX_SOC && MACH_SMDK2443
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 99f5a7dd3fc6..b744657733d7 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -1,10 +1,11 @@
1# S3c24XX Platform Support 1# S3c24XX Platform Support
2snd-soc-s3c24xx-objs := s3c24xx-pcm.o 2snd-soc-s3c24xx-objs := s3c-dma.o
3snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o 3snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
4snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o 4snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
5snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o 5snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o
6snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o 6snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o
7snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o 7snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
8snd-soc-s3c-pcm-objs := s3c-pcm.o
8 9
9obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o 10obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
10obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o 11obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
12obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o 13obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
13obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o 14obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
14obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o 15obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
16obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o
15 17
16# S3C24XX Machine Support 18# S3C24XX Machine Support
17snd-soc-jive-wm8750-objs := jive_wm8750.o 19snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -23,6 +25,7 @@ snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
23snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o 25snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
24snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o 26snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
25snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o 27snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
28snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
26 29
27obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 30obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
28obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 31obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -33,4 +36,5 @@ obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
33obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o 36obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
34obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o 37obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
35obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o 38obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
39obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
36 40
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
index 93e6c87b7399..59dc2c6b56d9 100644
--- a/sound/soc/s3c24xx/jive_wm8750.c
+++ b/sound/soc/s3c24xx/jive_wm8750.c
@@ -25,7 +25,7 @@
25 25
26#include <asm/mach-types.h> 26#include <asm/mach-types.h>
27 27
28#include "s3c24xx-pcm.h" 28#include "s3c-dma.h"
29#include "s3c2412-i2s.h" 29#include "s3c2412-i2s.h"
30 30
31#include "../codecs/wm8750.h" 31#include "../codecs/wm8750.h"
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index 12c71482d258..d00d359a03e6 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -24,7 +24,7 @@
24#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25 25
26#include "../codecs/ac97.h" 26#include "../codecs/ac97.h"
27#include "s3c24xx-pcm.h" 27#include "s3c-dma.h"
28#include "s3c24xx-ac97.h" 28#include "s3c24xx-ac97.h"
29 29
30static struct snd_soc_card ln2440sbc; 30static struct snd_soc_card ln2440sbc;
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
index 0c52e36ddd87..dea83d30a5c9 100644
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -32,7 +32,7 @@
32#include <asm/io.h> 32#include <asm/io.h>
33#include <mach/gta02.h> 33#include <mach/gta02.h>
34#include "../codecs/wm8753.h" 34#include "../codecs/wm8753.h"
35#include "s3c24xx-pcm.h" 35#include "s3c-dma.h"
36#include "s3c24xx-i2s.h" 36#include "s3c24xx-i2s.h"
37 37
38static struct snd_soc_card neo1973_gta02; 38static struct snd_soc_card neo1973_gta02;
@@ -119,7 +119,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
119 return ret; 119 return ret;
120 120
121 /* codec PLL input is PCLK/4 */ 121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
123 iis_clkrate / 4, pll_out); 123 iis_clkrate / 4, pll_out);
124 if (ret < 0) 124 if (ret < 0)
125 return ret; 125 return ret;
@@ -133,7 +133,7 @@ static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
134 134
135 /* disable the PLL */ 135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); 136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
137} 137}
138 138
139/* 139/*
@@ -183,7 +183,7 @@ static int neo1973_gta02_voice_hw_params(
183 return ret; 183 return ret;
184 184
185 /* configue and enable PLL for 12.288MHz output */ 185 /* configue and enable PLL for 12.288MHz output */
186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
187 iis_clkrate / 4, 12288000); 187 iis_clkrate / 4, 12288000);
188 if (ret < 0) 188 if (ret < 0)
189 return ret; 189 return ret;
@@ -197,7 +197,7 @@ static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
198 198
199 /* disable the PLL */ 199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); 200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
201} 201}
202 202
203static struct snd_soc_ops neo1973_gta02_voice_ops = { 203static struct snd_soc_ops neo1973_gta02_voice_ops = {
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 906709e6dd5f..0cb4f86f6d1e 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -29,7 +29,6 @@
29#include <mach/regs-clock.h> 29#include <mach/regs-clock.h>
30#include <mach/regs-gpio.h> 30#include <mach/regs-gpio.h>
31#include <mach/hardware.h> 31#include <mach/hardware.h>
32#include <plat/audio.h>
33#include <linux/io.h> 32#include <linux/io.h>
34#include <mach/spi-gpio.h> 33#include <mach/spi-gpio.h>
35 34
@@ -37,7 +36,7 @@
37 36
38#include "../codecs/wm8753.h" 37#include "../codecs/wm8753.h"
39#include "lm4857.h" 38#include "lm4857.h"
40#include "s3c24xx-pcm.h" 39#include "s3c-dma.h"
41#include "s3c24xx-i2s.h" 40#include "s3c24xx-i2s.h"
42 41
43/* define the scenarios */ 42/* define the scenarios */
@@ -137,7 +136,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
137 return ret; 136 return ret;
138 137
139 /* codec PLL input is PCLK/4 */ 138 /* codec PLL input is PCLK/4 */
140 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 139 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
141 iis_clkrate / 4, pll_out); 140 iis_clkrate / 4, pll_out);
142 if (ret < 0) 141 if (ret < 0)
143 return ret; 142 return ret;
@@ -153,7 +152,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
153 pr_debug("Entered %s\n", __func__); 152 pr_debug("Entered %s\n", __func__);
154 153
155 /* disable the PLL */ 154 /* disable the PLL */
156 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); 155 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
157} 156}
158 157
159/* 158/*
@@ -203,7 +202,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
203 return ret; 202 return ret;
204 203
205 /* configue and enable PLL for 12.288MHz output */ 204 /* configue and enable PLL for 12.288MHz output */
206 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 205 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
207 iis_clkrate / 4, 12288000); 206 iis_clkrate / 4, 12288000);
208 if (ret < 0) 207 if (ret < 0)
209 return ret; 208 return ret;
@@ -219,7 +218,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
219 pr_debug("Entered %s\n", __func__); 218 pr_debug("Entered %s\n", __func__);
220 219
221 /* disable the PLL */ 220 /* disable the PLL */
222 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); 221 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
223} 222}
224 223
225static struct snd_soc_ops neo1973_voice_ops = { 224static struct snd_soc_ops neo1973_voice_ops = {
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c-dma.c
index 1f35c6fcf5fd..7725e26d6c91 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c-dma.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * s3c24xx-pcm.c -- ALSA Soc Audio Layer 2 * s3c-dma.c -- ALSA Soc Audio Layer
3 * 3 *
4 * (c) 2006 Wolfson Microelectronics PLC. 4 * (c) 2006 Wolfson Microelectronics PLC.
5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com 5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
@@ -29,11 +29,10 @@
29#include <asm/dma.h> 29#include <asm/dma.h>
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <mach/dma.h> 31#include <mach/dma.h>
32#include <plat/audio.h>
33 32
34#include "s3c24xx-pcm.h" 33#include "s3c-dma.h"
35 34
36static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { 35static const struct snd_pcm_hardware s3c_dma_hardware = {
37 .info = SNDRV_PCM_INFO_INTERLEAVED | 36 .info = SNDRV_PCM_INFO_INTERLEAVED |
38 SNDRV_PCM_INFO_BLOCK_TRANSFER | 37 SNDRV_PCM_INFO_BLOCK_TRANSFER |
39 SNDRV_PCM_INFO_MMAP | 38 SNDRV_PCM_INFO_MMAP |
@@ -63,15 +62,15 @@ struct s3c24xx_runtime_data {
63 dma_addr_t dma_start; 62 dma_addr_t dma_start;
64 dma_addr_t dma_pos; 63 dma_addr_t dma_pos;
65 dma_addr_t dma_end; 64 dma_addr_t dma_end;
66 struct s3c24xx_pcm_dma_params *params; 65 struct s3c_dma_params *params;
67}; 66};
68 67
69/* s3c24xx_pcm_enqueue 68/* s3c_dma_enqueue
70 * 69 *
71 * place a dma buffer onto the queue for the dma system 70 * place a dma buffer onto the queue for the dma system
72 * to handle. 71 * to handle.
73*/ 72*/
74static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) 73static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
75{ 74{
76 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 75 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
77 dma_addr_t pos = prtd->dma_pos; 76 dma_addr_t pos = prtd->dma_pos;
@@ -80,12 +79,13 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
80 79
81 pr_debug("Entered %s\n", __func__); 80 pr_debug("Entered %s\n", __func__);
82 81
83 if (s3c_dma_has_circular()) { 82 if (s3c_dma_has_circular())
84 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; 83 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
85 } else 84 else
86 limit = prtd->dma_limit; 85 limit = prtd->dma_limit;
87 86
88 pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit); 87 pr_debug("%s: loaded %d, limit %d\n",
88 __func__, prtd->dma_loaded, limit);
89 89
90 while (prtd->dma_loaded < limit) { 90 while (prtd->dma_loaded < limit) {
91 unsigned long len = prtd->dma_period; 91 unsigned long len = prtd->dma_period;
@@ -133,19 +133,19 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
133 spin_lock(&prtd->lock); 133 spin_lock(&prtd->lock);
134 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { 134 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
135 prtd->dma_loaded--; 135 prtd->dma_loaded--;
136 s3c24xx_pcm_enqueue(substream); 136 s3c_dma_enqueue(substream);
137 } 137 }
138 138
139 spin_unlock(&prtd->lock); 139 spin_unlock(&prtd->lock);
140} 140}
141 141
142static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, 142static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params) 143 struct snd_pcm_hw_params *params)
144{ 144{
145 struct snd_pcm_runtime *runtime = substream->runtime; 145 struct snd_pcm_runtime *runtime = substream->runtime;
146 struct s3c24xx_runtime_data *prtd = runtime->private_data; 146 struct s3c24xx_runtime_data *prtd = runtime->private_data;
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; 148 struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data;
149 unsigned long totbytes = params_buffer_bytes(params); 149 unsigned long totbytes = params_buffer_bytes(params);
150 int ret = 0; 150 int ret = 0;
151 151
@@ -198,7 +198,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
198 return 0; 198 return 0;
199} 199}
200 200
201static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) 201static int s3c_dma_hw_free(struct snd_pcm_substream *substream)
202{ 202{
203 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 203 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
204 204
@@ -215,7 +215,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
215 return 0; 215 return 0;
216} 216}
217 217
218static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) 218static int s3c_dma_prepare(struct snd_pcm_substream *substream)
219{ 219{
220 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 220 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
221 int ret = 0; 221 int ret = 0;
@@ -248,12 +248,12 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
248 prtd->dma_pos = prtd->dma_start; 248 prtd->dma_pos = prtd->dma_start;
249 249
250 /* enqueue dma buffers */ 250 /* enqueue dma buffers */
251 s3c24xx_pcm_enqueue(substream); 251 s3c_dma_enqueue(substream);
252 252
253 return ret; 253 return ret;
254} 254}
255 255
256static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 256static int s3c_dma_trigger(struct snd_pcm_substream *substream, int cmd)
257{ 257{
258 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 258 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
259 int ret = 0; 259 int ret = 0;
@@ -288,7 +288,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
288} 288}
289 289
290static snd_pcm_uframes_t 290static snd_pcm_uframes_t
291s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) 291s3c_dma_pointer(struct snd_pcm_substream *substream)
292{ 292{
293 struct snd_pcm_runtime *runtime = substream->runtime; 293 struct snd_pcm_runtime *runtime = substream->runtime;
294 struct s3c24xx_runtime_data *prtd = runtime->private_data; 294 struct s3c24xx_runtime_data *prtd = runtime->private_data;
@@ -323,7 +323,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
323 return bytes_to_frames(substream->runtime, res); 323 return bytes_to_frames(substream->runtime, res);
324} 324}
325 325
326static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) 326static int s3c_dma_open(struct snd_pcm_substream *substream)
327{ 327{
328 struct snd_pcm_runtime *runtime = substream->runtime; 328 struct snd_pcm_runtime *runtime = substream->runtime;
329 struct s3c24xx_runtime_data *prtd; 329 struct s3c24xx_runtime_data *prtd;
@@ -331,7 +331,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
331 pr_debug("Entered %s\n", __func__); 331 pr_debug("Entered %s\n", __func__);
332 332
333 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 333 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
334 snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); 334 snd_soc_set_runtime_hwparams(substream, &s3c_dma_hardware);
335 335
336 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); 336 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
337 if (prtd == NULL) 337 if (prtd == NULL)
@@ -343,7 +343,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
343 return 0; 343 return 0;
344} 344}
345 345
346static int s3c24xx_pcm_close(struct snd_pcm_substream *substream) 346static int s3c_dma_close(struct snd_pcm_substream *substream)
347{ 347{
348 struct snd_pcm_runtime *runtime = substream->runtime; 348 struct snd_pcm_runtime *runtime = substream->runtime;
349 struct s3c24xx_runtime_data *prtd = runtime->private_data; 349 struct s3c24xx_runtime_data *prtd = runtime->private_data;
@@ -351,14 +351,14 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
351 pr_debug("Entered %s\n", __func__); 351 pr_debug("Entered %s\n", __func__);
352 352
353 if (!prtd) 353 if (!prtd)
354 pr_debug("s3c24xx_pcm_close called with prtd == NULL\n"); 354 pr_debug("s3c_dma_close called with prtd == NULL\n");
355 355
356 kfree(prtd); 356 kfree(prtd);
357 357
358 return 0; 358 return 0;
359} 359}
360 360
361static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, 361static int s3c_dma_mmap(struct snd_pcm_substream *substream,
362 struct vm_area_struct *vma) 362 struct vm_area_struct *vma)
363{ 363{
364 struct snd_pcm_runtime *runtime = substream->runtime; 364 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -371,23 +371,23 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
371 runtime->dma_bytes); 371 runtime->dma_bytes);
372} 372}
373 373
374static struct snd_pcm_ops s3c24xx_pcm_ops = { 374static struct snd_pcm_ops s3c_dma_ops = {
375 .open = s3c24xx_pcm_open, 375 .open = s3c_dma_open,
376 .close = s3c24xx_pcm_close, 376 .close = s3c_dma_close,
377 .ioctl = snd_pcm_lib_ioctl, 377 .ioctl = snd_pcm_lib_ioctl,
378 .hw_params = s3c24xx_pcm_hw_params, 378 .hw_params = s3c_dma_hw_params,
379 .hw_free = s3c24xx_pcm_hw_free, 379 .hw_free = s3c_dma_hw_free,
380 .prepare = s3c24xx_pcm_prepare, 380 .prepare = s3c_dma_prepare,
381 .trigger = s3c24xx_pcm_trigger, 381 .trigger = s3c_dma_trigger,
382 .pointer = s3c24xx_pcm_pointer, 382 .pointer = s3c_dma_pointer,
383 .mmap = s3c24xx_pcm_mmap, 383 .mmap = s3c_dma_mmap,
384}; 384};
385 385
386static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 386static int s3c_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
387{ 387{
388 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 388 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
389 struct snd_dma_buffer *buf = &substream->dma_buffer; 389 struct snd_dma_buffer *buf = &substream->dma_buffer;
390 size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; 390 size_t size = s3c_dma_hardware.buffer_bytes_max;
391 391
392 pr_debug("Entered %s\n", __func__); 392 pr_debug("Entered %s\n", __func__);
393 393
@@ -402,7 +402,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
402 return 0; 402 return 0;
403} 403}
404 404
405static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm) 405static void s3c_dma_free_dma_buffers(struct snd_pcm *pcm)
406{ 406{
407 struct snd_pcm_substream *substream; 407 struct snd_pcm_substream *substream;
408 struct snd_dma_buffer *buf; 408 struct snd_dma_buffer *buf;
@@ -425,9 +425,9 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
425 } 425 }
426} 426}
427 427
428static u64 s3c24xx_pcm_dmamask = DMA_BIT_MASK(32); 428static u64 s3c_dma_mask = DMA_BIT_MASK(32);
429 429
430static int s3c24xx_pcm_new(struct snd_card *card, 430static int s3c_dma_new(struct snd_card *card,
431 struct snd_soc_dai *dai, struct snd_pcm *pcm) 431 struct snd_soc_dai *dai, struct snd_pcm *pcm)
432{ 432{
433 int ret = 0; 433 int ret = 0;
@@ -435,19 +435,19 @@ static int s3c24xx_pcm_new(struct snd_card *card,
435 pr_debug("Entered %s\n", __func__); 435 pr_debug("Entered %s\n", __func__);
436 436
437 if (!card->dev->dma_mask) 437 if (!card->dev->dma_mask)
438 card->dev->dma_mask = &s3c24xx_pcm_dmamask; 438 card->dev->dma_mask = &s3c_dma_mask;
439 if (!card->dev->coherent_dma_mask) 439 if (!card->dev->coherent_dma_mask)
440 card->dev->coherent_dma_mask = 0xffffffff; 440 card->dev->coherent_dma_mask = 0xffffffff;
441 441
442 if (dai->playback.channels_min) { 442 if (dai->playback.channels_min) {
443 ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, 443 ret = s3c_preallocate_dma_buffer(pcm,
444 SNDRV_PCM_STREAM_PLAYBACK); 444 SNDRV_PCM_STREAM_PLAYBACK);
445 if (ret) 445 if (ret)
446 goto out; 446 goto out;
447 } 447 }
448 448
449 if (dai->capture.channels_min) { 449 if (dai->capture.channels_min) {
450 ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, 450 ret = s3c_preallocate_dma_buffer(pcm,
451 SNDRV_PCM_STREAM_CAPTURE); 451 SNDRV_PCM_STREAM_CAPTURE);
452 if (ret) 452 if (ret)
453 goto out; 453 goto out;
@@ -458,9 +458,9 @@ static int s3c24xx_pcm_new(struct snd_card *card,
458 458
459struct snd_soc_platform s3c24xx_soc_platform = { 459struct snd_soc_platform s3c24xx_soc_platform = {
460 .name = "s3c24xx-audio", 460 .name = "s3c24xx-audio",
461 .pcm_ops = &s3c24xx_pcm_ops, 461 .pcm_ops = &s3c_dma_ops,
462 .pcm_new = s3c24xx_pcm_new, 462 .pcm_new = s3c_dma_new,
463 .pcm_free = s3c24xx_pcm_free_dma_buffers, 463 .pcm_free = s3c_dma_free_dma_buffers,
464}; 464};
465EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); 465EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
466 466
@@ -477,5 +477,5 @@ static void __exit s3c24xx_soc_platform_exit(void)
477module_exit(s3c24xx_soc_platform_exit); 477module_exit(s3c24xx_soc_platform_exit);
478 478
479MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 479MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
480MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); 480MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
481MODULE_LICENSE("GPL"); 481MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.h b/sound/soc/s3c24xx/s3c-dma.h
index 0088c79822ea..69bb6bf6fc1c 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.h
+++ b/sound/soc/s3c24xx/s3c-dma.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * s3c24xx-pcm.h -- 2 * s3c-dma.h --
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the 5 * under the terms of the GNU General Public License as published by the
@@ -9,13 +9,13 @@
9 * ALSA PCM interface for the Samsung S3C24xx CPU 9 * ALSA PCM interface for the Samsung S3C24xx CPU
10 */ 10 */
11 11
12#ifndef _S3C24XX_PCM_H 12#ifndef _S3C_AUDIO_H
13#define _S3C24XX_PCM_H 13#define _S3C_AUDIO_H
14 14
15#define ST_RUNNING (1<<0) 15#define ST_RUNNING (1<<0)
16#define ST_OPENED (1<<1) 16#define ST_OPENED (1<<1)
17 17
18struct s3c24xx_pcm_dma_params { 18struct s3c_dma_params {
19 struct s3c2410_dma_client *client; /* stream identifier */ 19 struct s3c2410_dma_client *client; /* stream identifier */
20 int channel; /* Channel ID */ 20 int channel; /* Channel ID */
21 dma_addr_t dma_addr; 21 dma_addr_t dma_addr;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 9bc4aa35caab..e994d8374fe6 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -32,11 +32,10 @@
32 32
33#include <plat/regs-s3c2412-iis.h> 33#include <plat/regs-s3c2412-iis.h>
34 34
35#include <plat/audio.h>
36#include <mach/dma.h> 35#include <mach/dma.h>
37 36
38#include "s3c-i2s-v2.h" 37#include "s3c-i2s-v2.h"
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40 39
41#undef S3C_IIS_V2_SUPPORTED 40#undef S3C_IIS_V2_SUPPORTED
42 41
@@ -312,12 +311,15 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
312 311
313 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 312 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
314 case SND_SOC_DAIFMT_RIGHT_J: 313 case SND_SOC_DAIFMT_RIGHT_J:
314 iismod |= S3C2412_IISMOD_LR_RLOW;
315 iismod |= S3C2412_IISMOD_SDF_MSB; 315 iismod |= S3C2412_IISMOD_SDF_MSB;
316 break; 316 break;
317 case SND_SOC_DAIFMT_LEFT_J: 317 case SND_SOC_DAIFMT_LEFT_J:
318 iismod |= S3C2412_IISMOD_LR_RLOW;
318 iismod |= S3C2412_IISMOD_SDF_LSB; 319 iismod |= S3C2412_IISMOD_SDF_LSB;
319 break; 320 break;
320 case SND_SOC_DAIFMT_I2S: 321 case SND_SOC_DAIFMT_I2S:
322 iismod &= ~S3C2412_IISMOD_LR_RLOW;
321 iismod |= S3C2412_IISMOD_SDF_IIS; 323 iismod |= S3C2412_IISMOD_SDF_IIS;
322 break; 324 break;
323 default: 325 default:
@@ -392,7 +394,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
392 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 394 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
393 unsigned long irqs; 395 unsigned long irqs;
394 int ret = 0; 396 int ret = 0;
395 int channel = ((struct s3c24xx_pcm_dma_params *) 397 int channel = ((struct s3c_dma_params *)
396 rtd->dai->cpu_dai->dma_data)->channel; 398 rtd->dai->cpu_dai->dma_data)->channel;
397 399
398 pr_debug("Entered %s\n", __func__); 400 pr_debug("Entered %s\n", __func__);
@@ -467,6 +469,31 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
467 469
468 switch (div_id) { 470 switch (div_id) {
469 case S3C_I2SV2_DIV_BCLK: 471 case S3C_I2SV2_DIV_BCLK:
472 if (div > 3) {
473 /* convert value to bit field */
474
475 switch (div) {
476 case 16:
477 div = S3C2412_IISMOD_BCLK_16FS;
478 break;
479
480 case 32:
481 div = S3C2412_IISMOD_BCLK_32FS;
482 break;
483
484 case 24:
485 div = S3C2412_IISMOD_BCLK_24FS;
486 break;
487
488 case 48:
489 div = S3C2412_IISMOD_BCLK_48FS;
490 break;
491
492 default:
493 return -EINVAL;
494 }
495 }
496
470 reg = readl(i2s->regs + S3C2412_IISMOD); 497 reg = readl(i2s->regs + S3C2412_IISMOD);
471 reg &= ~S3C2412_IISMOD_BCLK_MASK; 498 reg &= ~S3C2412_IISMOD_BCLK_MASK;
472 writel(reg | div, i2s->regs + S3C2412_IISMOD); 499 writel(reg | div, i2s->regs + S3C2412_IISMOD);
@@ -626,7 +653,7 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
626 } 653 }
627 654
628 i2s->iis_pclk = clk_get(dev, "iis"); 655 i2s->iis_pclk = clk_get(dev, "iis");
629 if (i2s->iis_pclk == NULL) { 656 if (IS_ERR(i2s->iis_pclk)) {
630 dev_err(dev, "failed to get iis_clock\n"); 657 dev_err(dev, "failed to get iis_clock\n");
631 iounmap(i2s->regs); 658 iounmap(i2s->regs);
632 return -ENOENT; 659 return -ENOENT;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
index f66854a77fb2..ecf8eaaed1db 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -49,8 +49,8 @@ struct s3c_i2sv2_info {
49 49
50 unsigned char master; 50 unsigned char master;
51 51
52 struct s3c24xx_pcm_dma_params *dma_playback; 52 struct s3c_dma_params *dma_playback;
53 struct s3c24xx_pcm_dma_params *dma_capture; 53 struct s3c_dma_params *dma_capture;
54 54
55 u32 suspend_iismod; 55 u32 suspend_iismod;
56 u32 suspend_iiscon; 56 u32 suspend_iiscon;
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c
new file mode 100644
index 000000000000..9e61a7c2d9ac
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-pcm.c
@@ -0,0 +1,552 @@
1/* sound/soc/s3c24xx/s3c-pcm.c
2 *
3 * ALSA SoC Audio Layer - S3C PCM-Controller driver
4 *
5 * Copyright (c) 2009 Samsung Electronics Co. Ltd
6 * Author: Jaswinder Singh <jassi.brar@samsung.com>
7 * based upon I2S drivers by Ben Dooks.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/clk.h>
19#include <linux/kernel.h>
20#include <linux/gpio.h>
21#include <linux/io.h>
22
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include <plat/audio.h>
30#include <plat/dma.h>
31
32#include "s3c-dma.h"
33#include "s3c-pcm.h"
34
35static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
36 .name = "PCM Stereo out"
37};
38
39static struct s3c2410_dma_client s3c_pcm_dma_client_in = {
40 .name = "PCM Stereo in"
41};
42
43static struct s3c_dma_params s3c_pcm_stereo_out[] = {
44 [0] = {
45 .client = &s3c_pcm_dma_client_out,
46 .dma_size = 4,
47 },
48 [1] = {
49 .client = &s3c_pcm_dma_client_out,
50 .dma_size = 4,
51 },
52};
53
54static struct s3c_dma_params s3c_pcm_stereo_in[] = {
55 [0] = {
56 .client = &s3c_pcm_dma_client_in,
57 .dma_size = 4,
58 },
59 [1] = {
60 .client = &s3c_pcm_dma_client_in,
61 .dma_size = 4,
62 },
63};
64
65static struct s3c_pcm_info s3c_pcm[2];
66
67static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai)
68{
69 return cpu_dai->private_data;
70}
71
72static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
73{
74 void __iomem *regs = pcm->regs;
75 u32 ctl, clkctl;
76
77 clkctl = readl(regs + S3C_PCM_CLKCTL);
78 ctl = readl(regs + S3C_PCM_CTL);
79 ctl &= ~(S3C_PCM_CTL_TXDIPSTICK_MASK
80 << S3C_PCM_CTL_TXDIPSTICK_SHIFT);
81
82 if (on) {
83 ctl |= S3C_PCM_CTL_TXDMA_EN;
84 ctl |= S3C_PCM_CTL_TXFIFO_EN;
85 ctl |= S3C_PCM_CTL_ENABLE;
86 ctl |= (0x20<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
87 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
88 } else {
89 ctl &= ~S3C_PCM_CTL_TXDMA_EN;
90 ctl &= ~S3C_PCM_CTL_TXFIFO_EN;
91
92 if (!(ctl & S3C_PCM_CTL_RXFIFO_EN)) {
93 ctl &= ~S3C_PCM_CTL_ENABLE;
94 if (!pcm->idleclk)
95 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
96 }
97 }
98
99 writel(clkctl, regs + S3C_PCM_CLKCTL);
100 writel(ctl, regs + S3C_PCM_CTL);
101}
102
103static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on)
104{
105 void __iomem *regs = pcm->regs;
106 u32 ctl, clkctl;
107
108 ctl = readl(regs + S3C_PCM_CTL);
109 clkctl = readl(regs + S3C_PCM_CLKCTL);
110
111 if (on) {
112 ctl |= S3C_PCM_CTL_RXDMA_EN;
113 ctl |= S3C_PCM_CTL_RXFIFO_EN;
114 ctl |= S3C_PCM_CTL_ENABLE;
115 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
116 } else {
117 ctl &= ~S3C_PCM_CTL_RXDMA_EN;
118 ctl &= ~S3C_PCM_CTL_RXFIFO_EN;
119
120 if (!(ctl & S3C_PCM_CTL_TXFIFO_EN)) {
121 ctl &= ~S3C_PCM_CTL_ENABLE;
122 if (!pcm->idleclk)
123 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
124 }
125 }
126
127 writel(clkctl, regs + S3C_PCM_CLKCTL);
128 writel(ctl, regs + S3C_PCM_CTL);
129}
130
131static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
132 struct snd_soc_dai *dai)
133{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai);
136 unsigned long flags;
137
138 dev_dbg(pcm->dev, "Entered %s\n", __func__);
139
140 switch (cmd) {
141 case SNDRV_PCM_TRIGGER_START:
142 case SNDRV_PCM_TRIGGER_RESUME:
143 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
144 spin_lock_irqsave(&pcm->lock, flags);
145
146 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
147 s3c_pcm_snd_rxctrl(pcm, 1);
148 else
149 s3c_pcm_snd_txctrl(pcm, 1);
150
151 spin_unlock_irqrestore(&pcm->lock, flags);
152 break;
153
154 case SNDRV_PCM_TRIGGER_STOP:
155 case SNDRV_PCM_TRIGGER_SUSPEND:
156 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
157 spin_lock_irqsave(&pcm->lock, flags);
158
159 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
160 s3c_pcm_snd_rxctrl(pcm, 0);
161 else
162 s3c_pcm_snd_txctrl(pcm, 0);
163
164 spin_unlock_irqrestore(&pcm->lock, flags);
165 break;
166
167 default:
168 return -EINVAL;
169 }
170
171 return 0;
172}
173
174static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
175 struct snd_pcm_hw_params *params,
176 struct snd_soc_dai *socdai)
177{
178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai_link *dai = rtd->dai;
180 struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
181 void __iomem *regs = pcm->regs;
182 struct clk *clk;
183 int sclk_div, sync_div;
184 unsigned long flags;
185 u32 clkctl;
186
187 dev_dbg(pcm->dev, "Entered %s\n", __func__);
188
189 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
190 dai->cpu_dai->dma_data = pcm->dma_playback;
191 else
192 dai->cpu_dai->dma_data = pcm->dma_capture;
193
194 /* Strictly check for sample size */
195 switch (params_format(params)) {
196 case SNDRV_PCM_FORMAT_S16_LE:
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 spin_lock_irqsave(&pcm->lock, flags);
203
204 /* Get hold of the PCMSOURCE_CLK */
205 clkctl = readl(regs + S3C_PCM_CLKCTL);
206 if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK)
207 clk = pcm->pclk;
208 else
209 clk = pcm->cclk;
210
211 /* Set the SCLK divider */
212 sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs /
213 params_rate(params) / 2 - 1;
214
215 clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK
216 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
217 clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK)
218 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
219
220 /* Set the SYNC divider */
221 sync_div = pcm->sclk_per_fs - 1;
222
223 clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK
224 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
225 clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK)
226 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
227
228 writel(clkctl, regs + S3C_PCM_CLKCTL);
229
230 spin_unlock_irqrestore(&pcm->lock, flags);
231
232 dev_dbg(pcm->dev, "PCMSOURCE_CLK-%lu SCLK=%ufs \
233 SCLK_DIV=%d SYNC_DIV=%d\n",
234 clk_get_rate(clk), pcm->sclk_per_fs,
235 sclk_div, sync_div);
236
237 return 0;
238}
239
240static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
241 unsigned int fmt)
242{
243 struct s3c_pcm_info *pcm = to_info(cpu_dai);
244 void __iomem *regs = pcm->regs;
245 unsigned long flags;
246 int ret = 0;
247 u32 ctl;
248
249 dev_dbg(pcm->dev, "Entered %s\n", __func__);
250
251 spin_lock_irqsave(&pcm->lock, flags);
252
253 ctl = readl(regs + S3C_PCM_CTL);
254
255 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
256 case SND_SOC_DAIFMT_NB_NF:
257 /* Nothing to do, NB_NF by default */
258 break;
259 default:
260 dev_err(pcm->dev, "Unsupported clock inversion!\n");
261 ret = -EINVAL;
262 goto exit;
263 }
264
265 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
266 case SND_SOC_DAIFMT_CBS_CFS:
267 /* Nothing to do, Master by default */
268 break;
269 default:
270 dev_err(pcm->dev, "Unsupported master/slave format!\n");
271 ret = -EINVAL;
272 goto exit;
273 }
274
275 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
276 case SND_SOC_DAIFMT_CONT:
277 pcm->idleclk = 1;
278 break;
279 case SND_SOC_DAIFMT_GATED:
280 pcm->idleclk = 0;
281 break;
282 default:
283 dev_err(pcm->dev, "Invalid Clock gating request!\n");
284 ret = -EINVAL;
285 goto exit;
286 }
287
288 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
289 case SND_SOC_DAIFMT_DSP_A:
290 ctl |= S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
291 ctl |= S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
292 break;
293 case SND_SOC_DAIFMT_DSP_B:
294 ctl &= ~S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
295 ctl &= ~S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
296 break;
297 default:
298 dev_err(pcm->dev, "Unsupported data format!\n");
299 ret = -EINVAL;
300 goto exit;
301 }
302
303 writel(ctl, regs + S3C_PCM_CTL);
304
305exit:
306 spin_unlock_irqrestore(&pcm->lock, flags);
307
308 return ret;
309}
310
311static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
312 int div_id, int div)
313{
314 struct s3c_pcm_info *pcm = to_info(cpu_dai);
315
316 switch (div_id) {
317 case S3C_PCM_SCLK_PER_FS:
318 pcm->sclk_per_fs = div;
319 break;
320
321 default:
322 return -EINVAL;
323 }
324
325 return 0;
326}
327
328static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
329 int clk_id, unsigned int freq, int dir)
330{
331 struct s3c_pcm_info *pcm = to_info(cpu_dai);
332 void __iomem *regs = pcm->regs;
333 u32 clkctl = readl(regs + S3C_PCM_CLKCTL);
334
335 switch (clk_id) {
336 case S3C_PCM_CLKSRC_PCLK:
337 clkctl |= S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
338 break;
339
340 case S3C_PCM_CLKSRC_MUX:
341 clkctl &= ~S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
342
343 if (clk_get_rate(pcm->cclk) != freq)
344 clk_set_rate(pcm->cclk, freq);
345
346 break;
347
348 default:
349 return -EINVAL;
350 }
351
352 writel(clkctl, regs + S3C_PCM_CLKCTL);
353
354 return 0;
355}
356
357static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
358 .set_sysclk = s3c_pcm_set_sysclk,
359 .set_clkdiv = s3c_pcm_set_clkdiv,
360 .trigger = s3c_pcm_trigger,
361 .hw_params = s3c_pcm_hw_params,
362 .set_fmt = s3c_pcm_set_fmt,
363};
364
365#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
366
367#define S3C_PCM_DECLARE(n) \
368{ \
369 .name = "samsung-pcm", \
370 .id = (n), \
371 .symmetric_rates = 1, \
372 .ops = &s3c_pcm_dai_ops, \
373 .playback = { \
374 .channels_min = 2, \
375 .channels_max = 2, \
376 .rates = S3C_PCM_RATES, \
377 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
378 }, \
379 .capture = { \
380 .channels_min = 2, \
381 .channels_max = 2, \
382 .rates = S3C_PCM_RATES, \
383 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
384 }, \
385}
386
387struct snd_soc_dai s3c_pcm_dai[] = {
388 S3C_PCM_DECLARE(0),
389 S3C_PCM_DECLARE(1),
390};
391EXPORT_SYMBOL_GPL(s3c_pcm_dai);
392
393static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
394{
395 struct s3c_pcm_info *pcm;
396 struct snd_soc_dai *dai;
397 struct resource *mem_res, *dmatx_res, *dmarx_res;
398 struct s3c_audio_pdata *pcm_pdata;
399 int ret;
400
401 /* Check for valid device index */
402 if ((pdev->id < 0) || pdev->id >= ARRAY_SIZE(s3c_pcm)) {
403 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
404 return -EINVAL;
405 }
406
407 pcm_pdata = pdev->dev.platform_data;
408
409 /* Check for availability of necessary resource */
410 dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
411 if (!dmatx_res) {
412 dev_err(&pdev->dev, "Unable to get PCM-TX dma resource\n");
413 return -ENXIO;
414 }
415
416 dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
417 if (!dmarx_res) {
418 dev_err(&pdev->dev, "Unable to get PCM-RX dma resource\n");
419 return -ENXIO;
420 }
421
422 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
423 if (!mem_res) {
424 dev_err(&pdev->dev, "Unable to get register resource\n");
425 return -ENXIO;
426 }
427
428 if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) {
429 dev_err(&pdev->dev, "Unable to configure gpio\n");
430 return -EINVAL;
431 }
432
433 pcm = &s3c_pcm[pdev->id];
434 pcm->dev = &pdev->dev;
435
436 spin_lock_init(&pcm->lock);
437
438 dai = &s3c_pcm_dai[pdev->id];
439 dai->dev = &pdev->dev;
440
441 /* Default is 128fs */
442 pcm->sclk_per_fs = 128;
443
444 pcm->cclk = clk_get(&pdev->dev, "audio-bus");
445 if (IS_ERR(pcm->cclk)) {
446 dev_err(&pdev->dev, "failed to get audio-bus\n");
447 ret = PTR_ERR(pcm->cclk);
448 goto err1;
449 }
450 clk_enable(pcm->cclk);
451
452 /* record our pcm structure for later use in the callbacks */
453 dai->private_data = pcm;
454
455 if (!request_mem_region(mem_res->start,
456 resource_size(mem_res), "samsung-pcm")) {
457 dev_err(&pdev->dev, "Unable to request register region\n");
458 ret = -EBUSY;
459 goto err2;
460 }
461
462 pcm->regs = ioremap(mem_res->start, 0x100);
463 if (pcm->regs == NULL) {
464 dev_err(&pdev->dev, "cannot ioremap registers\n");
465 ret = -ENXIO;
466 goto err3;
467 }
468
469 pcm->pclk = clk_get(&pdev->dev, "pcm");
470 if (IS_ERR(pcm->pclk)) {
471 dev_err(&pdev->dev, "failed to get pcm_clock\n");
472 ret = -ENOENT;
473 goto err4;
474 }
475 clk_enable(pcm->pclk);
476
477 ret = snd_soc_register_dai(dai);
478 if (ret != 0) {
479 dev_err(&pdev->dev, "failed to get pcm_clock\n");
480 goto err5;
481 }
482
483 s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
484 + S3C_PCM_RXFIFO;
485 s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
486 + S3C_PCM_TXFIFO;
487
488 s3c_pcm_stereo_in[pdev->id].channel = dmarx_res->start;
489 s3c_pcm_stereo_out[pdev->id].channel = dmatx_res->start;
490
491 pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
492 pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
493
494 return 0;
495
496err5:
497 clk_disable(pcm->pclk);
498 clk_put(pcm->pclk);
499err4:
500 iounmap(pcm->regs);
501err3:
502 release_mem_region(mem_res->start, resource_size(mem_res));
503err2:
504 clk_disable(pcm->cclk);
505 clk_put(pcm->cclk);
506err1:
507 return ret;
508}
509
510static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
511{
512 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
513 struct resource *mem_res;
514
515 iounmap(pcm->regs);
516
517 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
518 release_mem_region(mem_res->start, resource_size(mem_res));
519
520 clk_disable(pcm->cclk);
521 clk_disable(pcm->pclk);
522 clk_put(pcm->pclk);
523 clk_put(pcm->cclk);
524
525 return 0;
526}
527
528static struct platform_driver s3c_pcm_driver = {
529 .probe = s3c_pcm_dev_probe,
530 .remove = s3c_pcm_dev_remove,
531 .driver = {
532 .name = "samsung-pcm",
533 .owner = THIS_MODULE,
534 },
535};
536
537static int __init s3c_pcm_init(void)
538{
539 return platform_driver_register(&s3c_pcm_driver);
540}
541module_init(s3c_pcm_init);
542
543static void __exit s3c_pcm_exit(void)
544{
545 platform_driver_unregister(&s3c_pcm_driver);
546}
547module_exit(s3c_pcm_exit);
548
549/* Module information */
550MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
551MODULE_DESCRIPTION("S3C PCM Controller Driver");
552MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-pcm.h b/sound/soc/s3c24xx/s3c-pcm.h
new file mode 100644
index 000000000000..69ff9971692f
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-pcm.h
@@ -0,0 +1,123 @@
1/* sound/soc/s3c24xx/s3c-pcm.h
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 */
8
9#ifndef __S3C_PCM_H
10#define __S3C_PCM_H __FILE__
11
12/*Register Offsets */
13#define S3C_PCM_CTL (0x00)
14#define S3C_PCM_CLKCTL (0x04)
15#define S3C_PCM_TXFIFO (0x08)
16#define S3C_PCM_RXFIFO (0x0C)
17#define S3C_PCM_IRQCTL (0x10)
18#define S3C_PCM_IRQSTAT (0x14)
19#define S3C_PCM_FIFOSTAT (0x18)
20#define S3C_PCM_CLRINT (0x20)
21
22/* PCM_CTL Bit-Fields */
23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f)
24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13)
25#define S3C_PCM_CTL_RXDIPSTICK_MSK (0x3f<<7)
26#define S3C_PCM_CTL_TXDMA_EN (0x1<<6)
27#define S3C_PCM_CTL_RXDMA_EN (0x1<<5)
28#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4)
29#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1<<3)
30#define S3C_PCM_CTL_TXFIFO_EN (0x1<<2)
31#define S3C_PCM_CTL_RXFIFO_EN (0x1<<1)
32#define S3C_PCM_CTL_ENABLE (0x1<<0)
33
34/* PCM_CLKCTL Bit-Fields */
35#define S3C_PCM_CLKCTL_SERCLK_EN (0x1<<19)
36#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1<<18)
37#define S3C_PCM_CLKCTL_SCLKDIV_MASK (0x1ff)
38#define S3C_PCM_CLKCTL_SYNCDIV_MASK (0x1ff)
39#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT (9)
40#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT (0)
41
42/* PCM_TXFIFO Bit-Fields */
43#define S3C_PCM_TXFIFO_DVALID (0x1<<16)
44#define S3C_PCM_TXFIFO_DATA_MSK (0xffff<<0)
45
46/* PCM_RXFIFO Bit-Fields */
47#define S3C_PCM_RXFIFO_DVALID (0x1<<16)
48#define S3C_PCM_RXFIFO_DATA_MSK (0xffff<<0)
49
50/* PCM_IRQCTL Bit-Fields */
51#define S3C_PCM_IRQCTL_IRQEN (0x1<<14)
52#define S3C_PCM_IRQCTL_WRDEN (0x1<<12)
53#define S3C_PCM_IRQCTL_TXEMPTYEN (0x1<<11)
54#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1<<10)
55#define S3C_PCM_IRQCTL_TXFULLEN (0x1<<9)
56#define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1<<8)
57#define S3C_PCM_IRQCTL_TXSTARVEN (0x1<<7)
58#define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1<<6)
59#define S3C_PCM_IRQCTL_RXEMPTEN (0x1<<5)
60#define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1<<4)
61#define S3C_PCM_IRQCTL_RXFULLEN (0x1<<3)
62#define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1<<2)
63#define S3C_PCM_IRQCTL_RXSTARVEN (0x1<<1)
64#define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1<<0)
65
66/* PCM_IRQSTAT Bit-Fields */
67#define S3C_PCM_IRQSTAT_IRQPND (0x1<<13)
68#define S3C_PCM_IRQSTAT_WRD_XFER (0x1<<12)
69#define S3C_PCM_IRQSTAT_TXEMPTY (0x1<<11)
70#define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1<<10)
71#define S3C_PCM_IRQSTAT_TXFULL (0x1<<9)
72#define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1<<8)
73#define S3C_PCM_IRQSTAT_TXSTARV (0x1<<7)
74#define S3C_PCM_IRQSTAT_TXERROVRFL (0x1<<6)
75#define S3C_PCM_IRQSTAT_RXEMPT (0x1<<5)
76#define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1<<4)
77#define S3C_PCM_IRQSTAT_RXFULL (0x1<<3)
78#define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1<<2)
79#define S3C_PCM_IRQSTAT_RXSTARV (0x1<<1)
80#define S3C_PCM_IRQSTAT_RXERROVRFL (0x1<<0)
81
82/* PCM_FIFOSTAT Bit-Fields */
83#define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f<<14)
84#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1<<13)
85#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1<<12)
86#define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1<<11)
87#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1<<10)
88#define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f<<4)
89#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1<<3)
90#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1<<2)
91#define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1<<1)
92#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1<<0)
93
94#define S3C_PCM_CLKSRC_PCLK 0
95#define S3C_PCM_CLKSRC_MUX 1
96
97#define S3C_PCM_SCLK_PER_FS 0
98
99/**
100 * struct s3c_pcm_info - S3C PCM Controller information
101 * @dev: The parent device passed to use from the probe.
102 * @regs: The pointer to the device register block.
103 * @dma_playback: DMA information for playback channel.
104 * @dma_capture: DMA information for capture channel.
105 */
106struct s3c_pcm_info {
107 spinlock_t lock;
108 struct device *dev;
109 void __iomem *regs;
110
111 unsigned int sclk_per_fs;
112
113 /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
114 unsigned int idleclk;
115
116 struct clk *pclk;
117 struct clk *cclk;
118
119 struct s3c_dma_params *dma_playback;
120 struct s3c_dma_params *dma_capture;
121};
122
123#endif /* __S3C_PCM_H */
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index a587ec40b449..359e59346ba2 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -34,11 +34,10 @@
34 34
35#include <plat/regs-s3c2412-iis.h> 35#include <plat/regs-s3c2412-iis.h>
36 36
37#include <plat/audio.h>
38#include <mach/regs-gpio.h> 37#include <mach/regs-gpio.h>
39#include <mach/dma.h> 38#include <mach/dma.h>
40 39
41#include "s3c24xx-pcm.h" 40#include "s3c-dma.h"
42#include "s3c2412-i2s.h" 41#include "s3c2412-i2s.h"
43 42
44#define S3C2412_I2S_DEBUG 0 43#define S3C2412_I2S_DEBUG 0
@@ -51,14 +50,14 @@ static struct s3c2410_dma_client s3c2412_dma_client_in = {
51 .name = "I2S PCM Stereo in" 50 .name = "I2S PCM Stereo in"
52}; 51};
53 52
54static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_out = { 53static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
55 .client = &s3c2412_dma_client_out, 54 .client = &s3c2412_dma_client_out,
56 .channel = DMACH_I2S_OUT, 55 .channel = DMACH_I2S_OUT,
57 .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, 56 .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD,
58 .dma_size = 4, 57 .dma_size = 4,
59}; 58};
60 59
61static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_in = { 60static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
62 .client = &s3c2412_dma_client_in, 61 .client = &s3c2412_dma_client_in,
63 .channel = DMACH_I2S_IN, 62 .channel = DMACH_I2S_IN,
64 .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, 63 .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD,
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index fc1beb0930b9..0191e3acb0b4 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -32,11 +32,10 @@
32#include <plat/regs-ac97.h> 32#include <plat/regs-ac97.h>
33#include <mach/regs-gpio.h> 33#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h> 34#include <mach/regs-clock.h>
35#include <plat/audio.h>
36#include <asm/dma.h> 35#include <asm/dma.h>
37#include <mach/dma.h> 36#include <mach/dma.h>
38 37
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40#include "s3c24xx-ac97.h" 39#include "s3c24xx-ac97.h"
41 40
42struct s3c24xx_ac97_info { 41struct s3c24xx_ac97_info {
@@ -189,21 +188,21 @@ static struct s3c2410_dma_client s3c2443_dma_client_micin = {
189 .name = "AC97 Mic Mono in" 188 .name = "AC97 Mic Mono in"
190}; 189};
191 190
192static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_out = { 191static struct s3c_dma_params s3c2443_ac97_pcm_stereo_out = {
193 .client = &s3c2443_dma_client_out, 192 .client = &s3c2443_dma_client_out,
194 .channel = DMACH_PCM_OUT, 193 .channel = DMACH_PCM_OUT,
195 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 194 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
196 .dma_size = 4, 195 .dma_size = 4,
197}; 196};
198 197
199static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_in = { 198static struct s3c_dma_params s3c2443_ac97_pcm_stereo_in = {
200 .client = &s3c2443_dma_client_in, 199 .client = &s3c2443_dma_client_in,
201 .channel = DMACH_PCM_IN, 200 .channel = DMACH_PCM_IN,
202 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 201 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
203 .dma_size = 4, 202 .dma_size = 4,
204}; 203};
205 204
206static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = { 205static struct s3c_dma_params s3c2443_ac97_mic_mono_in = {
207 .client = &s3c2443_dma_client_micin, 206 .client = &s3c2443_dma_client_micin,
208 .channel = DMACH_MIC_IN, 207 .channel = DMACH_MIC_IN,
209 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA, 208 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
@@ -291,7 +290,7 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
291{ 290{
292 u32 ac_glbctrl; 291 u32 ac_glbctrl;
293 struct snd_soc_pcm_runtime *rtd = substream->private_data; 292 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 int channel = ((struct s3c24xx_pcm_dma_params *) 293 int channel = ((struct s3c_dma_params *)
295 rtd->dai->cpu_dai->dma_data)->channel; 294 rtd->dai->cpu_dai->dma_data)->channel;
296 295
297 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 296 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
@@ -340,7 +339,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
340{ 339{
341 u32 ac_glbctrl; 340 u32 ac_glbctrl;
342 struct snd_soc_pcm_runtime *rtd = substream->private_data; 341 struct snd_soc_pcm_runtime *rtd = substream->private_data;
343 int channel = ((struct s3c24xx_pcm_dma_params *) 342 int channel = ((struct s3c_dma_params *)
344 rtd->dai->cpu_dai->dma_data)->channel; 343 rtd->dai->cpu_dai->dma_data)->channel;
345 344
346 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 345 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 40e2c4790f0d..0bc5950b9f02 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -32,13 +32,13 @@
32#include <mach/hardware.h> 32#include <mach/hardware.h>
33#include <mach/regs-gpio.h> 33#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h> 34#include <mach/regs-clock.h>
35#include <plat/audio.h> 35
36#include <asm/dma.h> 36#include <asm/dma.h>
37#include <mach/dma.h> 37#include <mach/dma.h>
38 38
39#include <plat/regs-iis.h> 39#include <plat/regs-iis.h>
40 40
41#include "s3c24xx-pcm.h" 41#include "s3c-dma.h"
42#include "s3c24xx-i2s.h" 42#include "s3c24xx-i2s.h"
43 43
44static struct s3c2410_dma_client s3c24xx_dma_client_out = { 44static struct s3c2410_dma_client s3c24xx_dma_client_out = {
@@ -49,14 +49,14 @@ static struct s3c2410_dma_client s3c24xx_dma_client_in = {
49 .name = "I2S PCM Stereo in" 49 .name = "I2S PCM Stereo in"
50}; 50};
51 51
52static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = { 52static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
53 .client = &s3c24xx_dma_client_out, 53 .client = &s3c24xx_dma_client_out,
54 .channel = DMACH_I2S_OUT, 54 .channel = DMACH_I2S_OUT,
55 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, 55 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
56 .dma_size = 2, 56 .dma_size = 2,
57}; 57};
58 58
59static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = { 59static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
60 .client = &s3c24xx_dma_client_in, 60 .client = &s3c24xx_dma_client_in,
61 .channel = DMACH_I2S_IN, 61 .channel = DMACH_I2S_IN,
62 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, 62 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
@@ -258,12 +258,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
258 switch (params_format(params)) { 258 switch (params_format(params)) {
259 case SNDRV_PCM_FORMAT_S8: 259 case SNDRV_PCM_FORMAT_S8:
260 iismod &= ~S3C2410_IISMOD_16BIT; 260 iismod &= ~S3C2410_IISMOD_16BIT;
261 ((struct s3c24xx_pcm_dma_params *) 261 ((struct s3c_dma_params *)
262 rtd->dai->cpu_dai->dma_data)->dma_size = 1; 262 rtd->dai->cpu_dai->dma_data)->dma_size = 1;
263 break; 263 break;
264 case SNDRV_PCM_FORMAT_S16_LE: 264 case SNDRV_PCM_FORMAT_S16_LE:
265 iismod |= S3C2410_IISMOD_16BIT; 265 iismod |= S3C2410_IISMOD_16BIT;
266 ((struct s3c24xx_pcm_dma_params *) 266 ((struct s3c_dma_params *)
267 rtd->dai->cpu_dai->dma_data)->dma_size = 2; 267 rtd->dai->cpu_dai->dma_data)->dma_size = 2;
268 break; 268 break;
269 default: 269 default:
@@ -280,7 +280,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 282 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 int channel = ((struct s3c24xx_pcm_dma_params *) 283 int channel = ((struct s3c_dma_params *)
284 rtd->dai->cpu_dai->dma_data)->channel; 284 rtd->dai->cpu_dai->dma_data)->channel;
285 285
286 pr_debug("Entered %s\n", __func__); 286 pr_debug("Entered %s\n", __func__);
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
index 1966e0d5652d..507b2ed5d58b 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.c
@@ -21,7 +21,7 @@
21 21
22#include <plat/audio-simtec.h> 22#include <plat/audio-simtec.h>
23 23
24#include "s3c24xx-pcm.h" 24#include "s3c-dma.h"
25#include "s3c24xx-i2s.h" 25#include "s3c24xx-i2s.h"
26#include "s3c24xx_simtec.h" 26#include "s3c24xx_simtec.h"
27 27
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
index 8346bd96eaf5..bdf8951af8e3 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
@@ -18,7 +18,7 @@
18 18
19#include <plat/audio-simtec.h> 19#include <plat/audio-simtec.h>
20 20
21#include "s3c24xx-pcm.h" 21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h" 22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h" 23#include "s3c24xx_simtec.h"
24 24
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
index 25797e096175..185c0acb5ce6 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
@@ -18,7 +18,7 @@
18 18
19#include <plat/audio-simtec.h> 19#include <plat/audio-simtec.h>
20 20
21#include "s3c24xx-pcm.h" 21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h" 22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h" 23#include "s3c24xx_simtec.h"
24 24
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
index c215d32d6322..052d59659c29 100644
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -24,7 +24,7 @@
24 24
25#include <plat/regs-iis.h> 25#include <plat/regs-iis.h>
26 26
27#include "s3c24xx-pcm.h" 27#include "s3c-dma.h"
28#include "s3c24xx-i2s.h" 28#include "s3c24xx-i2s.h"
29#include "../codecs/uda134x.h" 29#include "../codecs/uda134x.h"
30 30
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 105a77eeded0..cc7edb5f792d 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -31,12 +31,11 @@
31#include <plat/gpio-bank-d.h> 31#include <plat/gpio-bank-d.h>
32#include <plat/gpio-bank-e.h> 32#include <plat/gpio-bank-e.h>
33#include <plat/gpio-cfg.h> 33#include <plat/gpio-cfg.h>
34#include <plat/audio.h>
35 34
36#include <mach/map.h> 35#include <mach/map.h>
37#include <mach/dma.h> 36#include <mach/dma.h>
38 37
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40#include "s3c64xx-i2s.h" 39#include "s3c64xx-i2s.h"
41 40
42static struct s3c2410_dma_client s3c64xx_dma_client_out = { 41static struct s3c2410_dma_client s3c64xx_dma_client_out = {
@@ -47,7 +46,7 @@ static struct s3c2410_dma_client s3c64xx_dma_client_in = {
47 .name = "I2S PCM Stereo in" 46 .name = "I2S PCM Stereo in"
48}; 47};
49 48
50static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = { 49static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
51 [0] = { 50 [0] = {
52 .channel = DMACH_I2S0_OUT, 51 .channel = DMACH_I2S0_OUT,
53 .client = &s3c64xx_dma_client_out, 52 .client = &s3c64xx_dma_client_out,
@@ -62,7 +61,7 @@ static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
62 }, 61 },
63}; 62};
64 63
65static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = { 64static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[2] = {
66 [0] = { 65 [0] = {
67 .channel = DMACH_I2S0_IN, 66 .channel = DMACH_I2S0_IN,
68 .client = &s3c64xx_dma_client_in, 67 .client = &s3c64xx_dma_client_in,
@@ -99,6 +98,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
99 iismod |= S3C64XX_IISMOD_IMS_SYSMUX; 98 iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
100 break; 99 break;
101 100
101 case S3C64XX_CLKSRC_CDCLK:
102 switch (dir) {
103 case SND_SOC_CLOCK_IN:
104 iismod |= S3C64XX_IISMOD_CDCLKCON;
105 break;
106 case SND_SOC_CLOCK_OUT:
107 iismod &= ~S3C64XX_IISMOD_CDCLKCON;
108 break;
109 default:
110 return -EINVAL;
111 }
112 break;
113
102 default: 114 default:
103 return -EINVAL; 115 return -EINVAL;
104 } 116 }
@@ -111,8 +123,12 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
111struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) 123struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
112{ 124{
113 struct s3c_i2sv2_info *i2s = to_info(dai); 125 struct s3c_i2sv2_info *i2s = to_info(dai);
126 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
114 127
115 return i2s->iis_cclk; 128 if (iismod & S3C64XX_IISMOD_IMS_SYSMUX)
129 return i2s->iis_cclk;
130 else
131 return i2s->iis_pclk;
116} 132}
117EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); 133EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
118 134
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index 02148cee2613..abe7253b55fc 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -25,6 +25,7 @@ struct clk;
25 25
26#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK (0)
27#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX (1)
28#define S3C64XX_CLKSRC_CDCLK (2)
28 29
29extern struct snd_soc_dai s3c64xx_i2s_dai[]; 30extern struct snd_soc_dai s3c64xx_i2s_dai[];
30 31
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index a2a4f5323c17..12b783b12fcb 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -20,7 +20,7 @@
20#include <sound/soc-dapm.h> 20#include <sound/soc-dapm.h>
21 21
22#include "../codecs/ac97.h" 22#include "../codecs/ac97.h"
23#include "s3c24xx-pcm.h" 23#include "s3c-dma.h"
24#include "s3c24xx-ac97.h" 24#include "s3c24xx-ac97.h"
25 25
26static struct snd_soc_card smdk2443; 26static struct snd_soc_card smdk2443;
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
new file mode 100644
index 000000000000..efe4901213a3
--- /dev/null
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -0,0 +1,268 @@
1/*
2 * smdk64xx_wm8580.c
3 *
4 * Copyright (c) 2009 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include "../codecs/wm8580.h"
22#include "s3c-dma.h"
23#include "s3c64xx-i2s.h"
24
25#define S3C64XX_I2S_V4 2
26
27/* SMDK64XX has a 12MHZ crystal attached to WM8580 */
28#define SMDK64XX_WM8580_FREQ 12000000
29
30static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params)
32{
33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
35 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
36 unsigned int pll_out;
37 int bfs, rfs, ret;
38
39 switch (params_format(params)) {
40 case SNDRV_PCM_FORMAT_U8:
41 case SNDRV_PCM_FORMAT_S8:
42 bfs = 16;
43 break;
44 case SNDRV_PCM_FORMAT_U16_LE:
45 case SNDRV_PCM_FORMAT_S16_LE:
46 bfs = 32;
47 break;
48 default:
49 return -EINVAL;
50 }
51
52 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
53 * This criterion can't be met if we request PLL output
54 * as {8000x256, 64000x256, 11025x256}Hz.
55 * As a wayout, we rather change rfs to a minimum value that
56 * results in (params_rate(params) * rfs), and itself, acceptable
57 * to both - the CODEC and the CPU.
58 */
59 switch (params_rate(params)) {
60 case 16000:
61 case 22050:
62 case 32000:
63 case 44100:
64 case 48000:
65 case 88200:
66 case 96000:
67 rfs = 256;
68 break;
69 case 64000:
70 rfs = 384;
71 break;
72 case 8000:
73 case 11025:
74 rfs = 512;
75 break;
76 default:
77 return -EINVAL;
78 }
79 pll_out = params_rate(params) * rfs;
80
81 /* Set the Codec DAI configuration */
82 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
83 | SND_SOC_DAIFMT_NB_NF
84 | SND_SOC_DAIFMT_CBM_CFM);
85 if (ret < 0)
86 return ret;
87
88 /* Set the AP DAI configuration */
89 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
90 | SND_SOC_DAIFMT_NB_NF
91 | SND_SOC_DAIFMT_CBM_CFM);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_CDCLK,
96 0, SND_SOC_CLOCK_IN);
97 if (ret < 0)
98 return ret;
99
100 /* We use PCLK for basic ops in SoC-Slave mode */
101 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
102 0, SND_SOC_CLOCK_IN);
103 if (ret < 0)
104 return ret;
105
106 /* Set WM8580 to drive MCLK from its PLLA */
107 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
108 WM8580_CLKSRC_PLLA);
109 if (ret < 0)
110 return ret;
111
112 /* Explicitly set WM8580-DAC to source from MCLK */
113 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL,
114 WM8580_CLKSRC_MCLK);
115 if (ret < 0)
116 return ret;
117
118 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
119 SMDK64XX_WM8580_FREQ, pll_out);
120 if (ret < 0)
121 return ret;
122
123 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_BCLK, bfs);
124 if (ret < 0)
125 return ret;
126
127 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, rfs);
128 if (ret < 0)
129 return ret;
130
131 return 0;
132}
133
134/*
135 * SMDK64XX WM8580 DAI operations.
136 */
137static struct snd_soc_ops smdk64xx_ops = {
138 .hw_params = smdk64xx_hw_params,
139};
140
141/* SMDK64xx Playback widgets */
142static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
143 SND_SOC_DAPM_HP("Front-L/R", NULL),
144 SND_SOC_DAPM_HP("Center/Sub", NULL),
145 SND_SOC_DAPM_HP("Rear-L/R", NULL),
146};
147
148/* SMDK64xx Capture widgets */
149static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
150 SND_SOC_DAPM_MIC("MicIn", NULL),
151 SND_SOC_DAPM_LINE("LineIn", NULL),
152};
153
154/* SMDK-PAIFTX connections */
155static const struct snd_soc_dapm_route audio_map_tx[] = {
156 /* MicIn feeds AINL */
157 {"AINL", NULL, "MicIn"},
158
159 /* LineIn feeds AINL/R */
160 {"AINL", NULL, "LineIn"},
161 {"AINR", NULL, "LineIn"},
162};
163
164/* SMDK-PAIFRX connections */
165static const struct snd_soc_dapm_route audio_map_rx[] = {
166 /* Front Left/Right are fed VOUT1L/R */
167 {"Front-L/R", NULL, "VOUT1L"},
168 {"Front-L/R", NULL, "VOUT1R"},
169
170 /* Center/Sub are fed VOUT2L/R */
171 {"Center/Sub", NULL, "VOUT2L"},
172 {"Center/Sub", NULL, "VOUT2R"},
173
174 /* Rear Left/Right are fed VOUT3L/R */
175 {"Rear-L/R", NULL, "VOUT3L"},
176 {"Rear-L/R", NULL, "VOUT3R"},
177};
178
179static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
180{
181 /* Add smdk64xx specific Capture widgets */
182 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
183 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
184
185 /* Set up PAIFTX audio path */
186 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx));
187
188 /* Enabling the microphone requires the fitting of a 0R
189 * resistor to connect the line from the microphone jack.
190 */
191 snd_soc_dapm_disable_pin(codec, "MicIn");
192
193 /* signal a DAPM event */
194 snd_soc_dapm_sync(codec);
195
196 return 0;
197}
198
199static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec)
200{
201 /* Add smdk64xx specific Playback widgets */
202 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
203 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
204
205 /* Set up PAIFRX audio path */
206 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx));
207
208 /* signal a DAPM event */
209 snd_soc_dapm_sync(codec);
210
211 return 0;
212}
213
214static struct snd_soc_dai_link smdk64xx_dai[] = {
215{ /* Primary Playback i/f */
216 .name = "WM8580 PAIF RX",
217 .stream_name = "Playback",
218 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
219 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX],
220 .init = smdk64xx_wm8580_init_paifrx,
221 .ops = &smdk64xx_ops,
222},
223{ /* Primary Capture i/f */
224 .name = "WM8580 PAIF TX",
225 .stream_name = "Capture",
226 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
227 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX],
228 .init = smdk64xx_wm8580_init_paiftx,
229 .ops = &smdk64xx_ops,
230},
231};
232
233static struct snd_soc_card smdk64xx = {
234 .name = "smdk64xx",
235 .platform = &s3c24xx_soc_platform,
236 .dai_link = smdk64xx_dai,
237 .num_links = ARRAY_SIZE(smdk64xx_dai),
238};
239
240static struct snd_soc_device smdk64xx_snd_devdata = {
241 .card = &smdk64xx,
242 .codec_dev = &soc_codec_dev_wm8580,
243};
244
245static struct platform_device *smdk64xx_snd_device;
246
247static int __init smdk64xx_audio_init(void)
248{
249 int ret;
250
251 smdk64xx_snd_device = platform_device_alloc("soc-audio", -1);
252 if (!smdk64xx_snd_device)
253 return -ENOMEM;
254
255 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata);
256 smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev;
257 ret = platform_device_add(smdk64xx_snd_device);
258
259 if (ret)
260 platform_device_put(smdk64xx_snd_device);
261
262 return ret;
263}
264module_init(smdk64xx_audio_init);
265
266MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
267MODULE_DESCRIPTION("ALSA SoC SMDK64XX WM8580");
268MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 83b8028e209d..0eb1722f6581 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -423,7 +423,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
423 snd_pcm_lib_preallocate_free_for_all(pcm); 423 snd_pcm_lib_preallocate_free_for_all(pcm);
424} 424}
425 425
426static u64 s6000_pcm_dmamask = DMA_32BIT_MASK; 426static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
427 427
428static int s6000_pcm_new(struct snd_card *card, 428static int s6000_pcm_new(struct snd_card *card,
429 struct snd_soc_dai *dai, struct snd_pcm *pcm) 429 struct snd_soc_dai *dai, struct snd_pcm *pcm)
@@ -435,7 +435,7 @@ static int s6000_pcm_new(struct snd_card *card,
435 if (!card->dev->dma_mask) 435 if (!card->dev->dma_mask)
436 card->dev->dma_mask = &s6000_pcm_dmamask; 436 card->dev->dma_mask = &s6000_pcm_dmamask;
437 if (!card->dev->coherent_dma_mask) 437 if (!card->dev->coherent_dma_mask)
438 card->dev->coherent_dma_mask = DMA_32BIT_MASK; 438 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
439 439
440 if (params->dma_in) { 440 if (params->dma_in) {
441 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in), 441 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 9154b4363db3..9e6976586554 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -23,7 +23,6 @@ config SND_SOC_SH4_SSI
23config SND_SOC_SH4_FSI 23config SND_SOC_SH4_FSI
24 tristate "SH4 FSI support" 24 tristate "SH4 FSI support"
25 depends on CPU_SUBTYPE_SH7724 25 depends on CPU_SUBTYPE_SH7724
26 select SH_DMA
27 help 26 help
28 This option enables FSI sound support 27 This option enables FSI sound support
29 28
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 44123248b630..9c49c11c43ce 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -17,7 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/clk.h> 20#include <linux/pm_runtime.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <sound/core.h> 22#include <sound/core.h>
23#include <sound/pcm.h> 23#include <sound/pcm.h>
@@ -26,8 +26,6 @@
26#include <sound/pcm_params.h> 26#include <sound/pcm_params.h>
27#include <sound/sh_fsi.h> 27#include <sound/sh_fsi.h>
28#include <asm/atomic.h> 28#include <asm/atomic.h>
29#include <asm/dma.h>
30#include <asm/dma-sh.h>
31 29
32#define DO_FMT 0x0000 30#define DO_FMT 0x0000
33#define DOFF_CTL 0x0004 31#define DOFF_CTL 0x0004
@@ -97,7 +95,6 @@ struct fsi_priv {
97 95
98 int fifo_max; 96 int fifo_max;
99 int chan; 97 int chan;
100 int dma_chan;
101 98
102 int byte_offset; 99 int byte_offset;
103 int period_len; 100 int period_len;
@@ -108,7 +105,6 @@ struct fsi_priv {
108struct fsi_master { 105struct fsi_master {
109 void __iomem *base; 106 void __iomem *base;
110 int irq; 107 int irq;
111 struct clk *clk;
112 struct fsi_priv fsia; 108 struct fsi_priv fsia;
113 struct fsi_priv fsib; 109 struct fsi_priv fsib;
114 struct sh_fsi_platform_info *info; 110 struct sh_fsi_platform_info *info;
@@ -308,62 +304,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
308 return residue; 304 return residue;
309} 305}
310 306
311static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
312{
313 int residue;
314 int width;
315 struct snd_pcm_runtime *runtime;
316
317 runtime = fsi->substream->runtime;
318
319 /* get 1 channel data width */
320 width = frames_to_bytes(runtime, 1) / fsi->chan;
321
322 if (2 == width)
323 residue = fsi_get_fifo_residue(fsi, is_play);
324 else
325 residue = get_dma_residue(fsi->dma_chan);
326
327 return residue;
328}
329
330/************************************************************************
331
332
333 basic dma function
334
335
336************************************************************************/
337#define PORTA_DMA 0
338#define PORTB_DMA 1
339
340static int fsi_get_dma_chan(void)
341{
342 if (0 != request_dma(PORTA_DMA, "fsia"))
343 return -EIO;
344
345 if (0 != request_dma(PORTB_DMA, "fsib")) {
346 free_dma(PORTA_DMA);
347 return -EIO;
348 }
349
350 master->fsia.dma_chan = PORTA_DMA;
351 master->fsib.dma_chan = PORTB_DMA;
352
353 return 0;
354}
355
356static void fsi_free_dma_chan(void)
357{
358 dma_wait_for_completion(PORTA_DMA);
359 dma_wait_for_completion(PORTB_DMA);
360 free_dma(PORTA_DMA);
361 free_dma(PORTB_DMA);
362
363 master->fsia.dma_chan = -1;
364 master->fsib.dma_chan = -1;
365}
366
367/************************************************************************ 307/************************************************************************
368 308
369 309
@@ -435,44 +375,6 @@ static void fsi_soft_all_reset(void)
435 mdelay(10); 375 mdelay(10);
436} 376}
437 377
438static void fsi_16data_push(struct fsi_priv *fsi,
439 struct snd_pcm_runtime *runtime,
440 int send)
441{
442 u16 *dma_start;
443 u32 snd;
444 int i;
445
446 /* get dma start position for FSI */
447 dma_start = (u16 *)runtime->dma_area;
448 dma_start += fsi->byte_offset / 2;
449
450 /*
451 * soft dma
452 * FSI can not use DMA when 16bpp
453 */
454 for (i = 0; i < send; i++) {
455 snd = (u32)dma_start[i];
456 fsi_reg_write(fsi, DODT, snd << 8);
457 }
458}
459
460static void fsi_32data_push(struct fsi_priv *fsi,
461 struct snd_pcm_runtime *runtime,
462 int send)
463{
464 u32 *dma_start;
465
466 /* get dma start position for FSI */
467 dma_start = (u32 *)runtime->dma_area;
468 dma_start += fsi->byte_offset / 4;
469
470 dma_wait_for_completion(fsi->dma_chan);
471 dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
472 dma_write(fsi->dma_chan, (u32)dma_start,
473 (u32)(fsi->base + DODT), send * 4);
474}
475
476/* playback interrupt */ 378/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi) 379static int fsi_data_push(struct fsi_priv *fsi)
478{ 380{
@@ -481,6 +383,8 @@ static int fsi_data_push(struct fsi_priv *fsi)
481 int send; 383 int send;
482 int fifo_free; 384 int fifo_free;
483 int width; 385 int width;
386 u8 *start;
387 int i;
484 388
485 if (!fsi || 389 if (!fsi ||
486 !fsi->substream || 390 !fsi->substream ||
@@ -515,12 +419,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
515 if (fifo_free < send) 419 if (fifo_free < send)
516 send = fifo_free; 420 send = fifo_free;
517 421
518 if (2 == width) 422 start = runtime->dma_area;
519 fsi_16data_push(fsi, runtime, send); 423 start += fsi->byte_offset;
520 else if (4 == width) 424
521 fsi_32data_push(fsi, runtime, send); 425 switch (width) {
522 else 426 case 2:
427 for (i = 0; i < send; i++)
428 fsi_reg_write(fsi, DODT,
429 ((u32)*((u16 *)start + i) << 8));
430 break;
431 case 4:
432 for (i = 0; i < send; i++)
433 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
434 break;
435 default:
523 return -EINVAL; 436 return -EINVAL;
437 }
524 438
525 fsi->byte_offset += send * width; 439 fsi->byte_offset += send * width;
526 440
@@ -532,6 +446,75 @@ static int fsi_data_push(struct fsi_priv *fsi)
532 return 0; 446 return 0;
533} 447}
534 448
449static int fsi_data_pop(struct fsi_priv *fsi)
450{
451 struct snd_pcm_runtime *runtime;
452 struct snd_pcm_substream *substream = NULL;
453 int free;
454 int fifo_fill;
455 int width;
456 u8 *start;
457 int i;
458
459 if (!fsi ||
460 !fsi->substream ||
461 !fsi->substream->runtime)
462 return -EINVAL;
463
464 runtime = fsi->substream->runtime;
465
466 /* FSI FIFO has limit.
467 * So, this driver can not send periods data at a time
468 */
469 if (fsi->byte_offset >=
470 fsi->period_len * (fsi->periods + 1)) {
471
472 substream = fsi->substream;
473 fsi->periods = (fsi->periods + 1) % runtime->periods;
474
475 if (0 == fsi->periods)
476 fsi->byte_offset = 0;
477 }
478
479 /* get 1 channel data width */
480 width = frames_to_bytes(runtime, 1) / fsi->chan;
481
482 /* get free space for alsa */
483 free = (fsi->buffer_len - fsi->byte_offset) / width;
484
485 /* get recv size */
486 fifo_fill = fsi_get_fifo_residue(fsi, 0);
487
488 if (free < fifo_fill)
489 fifo_fill = free;
490
491 start = runtime->dma_area;
492 start += fsi->byte_offset;
493
494 switch (width) {
495 case 2:
496 for (i = 0; i < fifo_fill; i++)
497 *((u16 *)start + i) =
498 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
499 break;
500 case 4:
501 for (i = 0; i < fifo_fill; i++)
502 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
503 break;
504 default:
505 return -EINVAL;
506 }
507
508 fsi->byte_offset += fifo_fill * width;
509
510 fsi_irq_enable(fsi, 0);
511
512 if (substream)
513 snd_pcm_period_elapsed(substream);
514
515 return 0;
516}
517
535static irqreturn_t fsi_interrupt(int irq, void *data) 518static irqreturn_t fsi_interrupt(int irq, void *data)
536{ 519{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; 520 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
@@ -545,6 +528,10 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
545 fsi_data_push(&master->fsia); 528 fsi_data_push(&master->fsia);
546 if (int_st & INT_B_OUT) 529 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib); 530 fsi_data_push(&master->fsib);
531 if (int_st & INT_A_IN)
532 fsi_data_pop(&master->fsia);
533 if (int_st & INT_B_IN)
534 fsi_data_pop(&master->fsib);
548 535
549 fsi_master_write(INT_ST, 0x0000000); 536 fsi_master_write(INT_ST, 0x0000000);
550 537
@@ -571,7 +558,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
571 int is_master; 558 int is_master;
572 int ret = 0; 559 int ret = 0;
573 560
574 clk_enable(master->clk); 561 pm_runtime_get_sync(dai->dev);
575 562
576 /* CKG1 */ 563 /* CKG1 */
577 data = is_play ? (1 << 0) : (1 << 4); 564 data = is_play ? (1 << 0) : (1 << 4);
@@ -664,8 +651,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
664 } 651 }
665 652
666 fsi_reg_write(fsi, reg, data); 653 fsi_reg_write(fsi, reg, data);
667 dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
668 msg, fsi->chan, fsi->dma_chan);
669 654
670 /* 655 /*
671 * clear clk reset if master mode 656 * clear clk reset if master mode
@@ -688,7 +673,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
688 fsi_irq_disable(fsi, is_play); 673 fsi_irq_disable(fsi, is_play);
689 fsi_clk_ctrl(fsi, 0); 674 fsi_clk_ctrl(fsi, 0);
690 675
691 clk_disable(master->clk); 676 pm_runtime_put_sync(dai->dev);
692} 677}
693 678
694static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, 679static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -699,16 +684,12 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 684 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0; 685 int ret = 0;
701 686
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) { 687 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START: 688 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream, 689 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size), 690 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size)); 691 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi); 692 ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
712 break; 693 break;
713 case SNDRV_PCM_TRIGGER_STOP: 694 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play); 695 fsi_irq_disable(fsi, is_play);
@@ -780,10 +761,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{ 761{
781 struct snd_pcm_runtime *runtime = substream->runtime; 762 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream); 763 struct fsi_priv *fsi = fsi_get(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location; 764 long location;
785 765
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); 766 location = (fsi->byte_offset - 1);
787 if (location < 0) 767 if (location < 0)
788 location = 0; 768 location = 0;
789 769
@@ -845,7 +825,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
845 .channels_min = 1, 825 .channels_min = 1,
846 .channels_max = 8, 826 .channels_max = 8,
847 }, 827 },
848 /* capture not supported */ 828 .capture = {
829 .rates = FSI_RATES,
830 .formats = FSI_FMTS,
831 .channels_min = 1,
832 .channels_max = 8,
833 },
849 .ops = &fsi_dai_ops, 834 .ops = &fsi_dai_ops,
850 }, 835 },
851 { 836 {
@@ -857,7 +842,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
857 .channels_min = 1, 842 .channels_min = 1,
858 .channels_max = 8, 843 .channels_max = 8,
859 }, 844 },
860 /* capture not supported */ 845 .capture = {
846 .rates = FSI_RATES,
847 .formats = FSI_FMTS,
848 .channels_min = 1,
849 .channels_max = 8,
850 },
861 .ops = &fsi_dai_ops, 851 .ops = &fsi_dai_ops,
862 }, 852 },
863}; 853};
@@ -881,7 +871,6 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
881static int fsi_probe(struct platform_device *pdev) 871static int fsi_probe(struct platform_device *pdev)
882{ 872{
883 struct resource *res; 873 struct resource *res;
884 char clk_name[8];
885 unsigned int irq; 874 unsigned int irq;
886 int ret; 875 int ret;
887 876
@@ -912,23 +901,8 @@ static int fsi_probe(struct platform_device *pdev)
912 master->fsia.base = master->base; 901 master->fsia.base = master->base;
913 master->fsib.base = master->base + 0x40; 902 master->fsib.base = master->base + 0x40;
914 903
915 master->fsia.dma_chan = -1; 904 pm_runtime_enable(&pdev->dev);
916 master->fsib.dma_chan = -1; 905 pm_runtime_resume(&pdev->dev);
917
918 ret = fsi_get_dma_chan();
919 if (ret < 0) {
920 dev_err(&pdev->dev, "cannot get dma api\n");
921 goto exit_iounmap;
922 }
923
924 /* FSI is based on SPU mstp */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO;
930 goto exit_free_dma;
931 }
932 906
933 fsi_soc_dai[0].dev = &pdev->dev; 907 fsi_soc_dai[0].dev = &pdev->dev;
934 fsi_soc_dai[1].dev = &pdev->dev; 908 fsi_soc_dai[1].dev = &pdev->dev;
@@ -938,7 +912,7 @@ static int fsi_probe(struct platform_device *pdev)
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 912 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) { 913 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n"); 914 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma; 915 goto exit_iounmap;
942 } 916 }
943 917
944 ret = snd_soc_register_platform(&fsi_soc_platform); 918 ret = snd_soc_register_platform(&fsi_soc_platform);
@@ -951,10 +925,9 @@ static int fsi_probe(struct platform_device *pdev)
951 925
952exit_free_irq: 926exit_free_irq:
953 free_irq(irq, master); 927 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap: 928exit_iounmap:
957 iounmap(master->base); 929 iounmap(master->base);
930 pm_runtime_disable(&pdev->dev);
958exit_kfree: 931exit_kfree:
959 kfree(master); 932 kfree(master);
960 master = NULL; 933 master = NULL;
@@ -967,9 +940,7 @@ static int fsi_remove(struct platform_device *pdev)
967 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 940 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
968 snd_soc_unregister_platform(&fsi_soc_platform); 941 snd_soc_unregister_platform(&fsi_soc_platform);
969 942
970 clk_put(master->clk); 943 pm_runtime_disable(&pdev->dev);
971
972 fsi_free_dma_chan();
973 944
974 free_irq(master->irq, master); 945 free_irq(master->irq, master);
975 946
@@ -979,9 +950,27 @@ static int fsi_remove(struct platform_device *pdev)
979 return 0; 950 return 0;
980} 951}
981 952
953static int fsi_runtime_nop(struct device *dev)
954{
955 /* Runtime PM callback shared between ->runtime_suspend()
956 * and ->runtime_resume(). Simply returns success.
957 *
958 * This driver re-initializes all registers after
959 * pm_runtime_get_sync() anyway so there is no need
960 * to save and restore registers here.
961 */
962 return 0;
963}
964
965static struct dev_pm_ops fsi_pm_ops = {
966 .runtime_suspend = fsi_runtime_nop,
967 .runtime_resume = fsi_runtime_nop,
968};
969
982static struct platform_driver fsi_driver = { 970static struct platform_driver fsi_driver = {
983 .driver = { 971 .driver = {
984 .name = "sh_fsi", 972 .name = "sh_fsi",
973 .pm = &fsi_pm_ops,
985 }, 974 },
986 .probe = fsi_probe, 975 .probe = fsi_probe,
987 .remove = fsi_remove, 976 .remove = fsi_remove,
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index c8ceddc2a26c..d2505e8b06c9 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -77,6 +77,35 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data,
77#define snd_soc_7_9_spi_write NULL 77#define snd_soc_7_9_spi_write NULL
78#endif 78#endif
79 79
80static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 *cache = codec->reg_cache;
84 u8 data[2];
85
86 BUG_ON(codec->volatile_register);
87
88 data[0] = reg & 0xff;
89 data[1] = value & 0xff;
90
91 if (reg < codec->reg_cache_size)
92 cache[reg] = value;
93
94 if (codec->hw_write(codec->control_data, data, 2) == 2)
95 return 0;
96 else
97 return -EIO;
98}
99
100static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
101 unsigned int reg)
102{
103 u8 *cache = codec->reg_cache;
104 if (reg >= codec->reg_cache_size)
105 return -1;
106 return cache[reg];
107}
108
80static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, 109static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value) 110 unsigned int value)
82{ 111{
@@ -150,9 +179,20 @@ static struct {
150 unsigned int (*read)(struct snd_soc_codec *, unsigned int); 179 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
151 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); 180 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
152} io_types[] = { 181} io_types[] = {
153 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read }, 182 {
154 { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read, 183 .addr_bits = 7, .data_bits = 9,
155 snd_soc_8_16_read_i2c }, 184 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
185 .spi_write = snd_soc_7_9_spi_write
186 },
187 {
188 .addr_bits = 8, .data_bits = 8,
189 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
190 },
191 {
192 .addr_bits = 8, .data_bits = 16,
193 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
194 .i2c_read = snd_soc_8_16_read_i2c,
195 },
156}; 196};
157 197
158/** 198/**
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0a1b2f64bbee..ef8f28284cb9 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -37,7 +37,6 @@
37#include <sound/initval.h> 37#include <sound/initval.h>
38 38
39static DEFINE_MUTEX(pcm_mutex); 39static DEFINE_MUTEX(pcm_mutex);
40static DEFINE_MUTEX(io_mutex);
41static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 40static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
42 41
43#ifdef CONFIG_DEBUG_FS 42#ifdef CONFIG_DEBUG_FS
@@ -81,6 +80,173 @@ static int run_delayed_work(struct delayed_work *dwork)
81 return ret; 80 return ret;
82} 81}
83 82
83/* codec register dump */
84static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
85{
86 int i, step = 1, count = 0;
87
88 if (!codec->reg_cache_size)
89 return 0;
90
91 if (codec->reg_cache_step)
92 step = codec->reg_cache_step;
93
94 count += sprintf(buf, "%s registers\n", codec->name);
95 for (i = 0; i < codec->reg_cache_size; i += step) {
96 if (codec->readable_register && !codec->readable_register(i))
97 continue;
98
99 count += sprintf(buf + count, "%2x: ", i);
100 if (count >= PAGE_SIZE - 1)
101 break;
102
103 if (codec->display_register)
104 count += codec->display_register(codec, buf + count,
105 PAGE_SIZE - count, i);
106 else
107 count += snprintf(buf + count, PAGE_SIZE - count,
108 "%4x", codec->read(codec, i));
109
110 if (count >= PAGE_SIZE - 1)
111 break;
112
113 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
114 if (count >= PAGE_SIZE - 1)
115 break;
116 }
117
118 /* Truncate count; min() would cause a warning */
119 if (count >= PAGE_SIZE)
120 count = PAGE_SIZE - 1;
121
122 return count;
123}
124static ssize_t codec_reg_show(struct device *dev,
125 struct device_attribute *attr, char *buf)
126{
127 struct snd_soc_device *devdata = dev_get_drvdata(dev);
128 return soc_codec_reg_show(devdata->card->codec, buf);
129}
130
131static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
132
133#ifdef CONFIG_DEBUG_FS
134static int codec_reg_open_file(struct inode *inode, struct file *file)
135{
136 file->private_data = inode->i_private;
137 return 0;
138}
139
140static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
141 size_t count, loff_t *ppos)
142{
143 ssize_t ret;
144 struct snd_soc_codec *codec = file->private_data;
145 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
146 if (!buf)
147 return -ENOMEM;
148 ret = soc_codec_reg_show(codec, buf);
149 if (ret >= 0)
150 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
151 kfree(buf);
152 return ret;
153}
154
155static ssize_t codec_reg_write_file(struct file *file,
156 const char __user *user_buf, size_t count, loff_t *ppos)
157{
158 char buf[32];
159 int buf_size;
160 char *start = buf;
161 unsigned long reg, value;
162 int step = 1;
163 struct snd_soc_codec *codec = file->private_data;
164
165 buf_size = min(count, (sizeof(buf)-1));
166 if (copy_from_user(buf, user_buf, buf_size))
167 return -EFAULT;
168 buf[buf_size] = 0;
169
170 if (codec->reg_cache_step)
171 step = codec->reg_cache_step;
172
173 while (*start == ' ')
174 start++;
175 reg = simple_strtoul(start, &start, 16);
176 if ((reg >= codec->reg_cache_size) || (reg % step))
177 return -EINVAL;
178 while (*start == ' ')
179 start++;
180 if (strict_strtoul(start, 16, &value))
181 return -EINVAL;
182 codec->write(codec, reg, value);
183 return buf_size;
184}
185
186static const struct file_operations codec_reg_fops = {
187 .open = codec_reg_open_file,
188 .read = codec_reg_read_file,
189 .write = codec_reg_write_file,
190};
191
192static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
193{
194 char codec_root[128];
195
196 if (codec->dev)
197 snprintf(codec_root, sizeof(codec_root),
198 "%s.%s", codec->name, dev_name(codec->dev));
199 else
200 snprintf(codec_root, sizeof(codec_root),
201 "%s", codec->name);
202
203 codec->debugfs_codec_root = debugfs_create_dir(codec_root,
204 debugfs_root);
205 if (!codec->debugfs_codec_root) {
206 printk(KERN_WARNING
207 "ASoC: Failed to create codec debugfs directory\n");
208 return;
209 }
210
211 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
212 codec->debugfs_codec_root,
213 codec, &codec_reg_fops);
214 if (!codec->debugfs_reg)
215 printk(KERN_WARNING
216 "ASoC: Failed to create codec register debugfs file\n");
217
218 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
219 codec->debugfs_codec_root,
220 &codec->pop_time);
221 if (!codec->debugfs_pop_time)
222 printk(KERN_WARNING
223 "Failed to create pop time debugfs file\n");
224
225 codec->debugfs_dapm = debugfs_create_dir("dapm",
226 codec->debugfs_codec_root);
227 if (!codec->debugfs_dapm)
228 printk(KERN_WARNING
229 "Failed to create DAPM debugfs directory\n");
230
231 snd_soc_dapm_debugfs_init(codec);
232}
233
234static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
235{
236 debugfs_remove_recursive(codec->debugfs_codec_root);
237}
238
239#else
240
241static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
242{
243}
244
245static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
246{
247}
248#endif
249
84#ifdef CONFIG_SND_SOC_AC97_BUS 250#ifdef CONFIG_SND_SOC_AC97_BUS
85/* unregister ac97 codec */ 251/* unregister ac97 codec */
86static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) 252static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
@@ -790,45 +956,6 @@ static int soc_resume(struct device *dev)
790 956
791 return 0; 957 return 0;
792} 958}
793
794/**
795 * snd_soc_suspend_device: Notify core of device suspend
796 *
797 * @dev: Device being suspended.
798 *
799 * In order to ensure that the entire audio subsystem is suspended in a
800 * coordinated fashion ASoC devices should suspend themselves when
801 * called by ASoC. When the standard kernel suspend process asks the
802 * device to suspend it should call this function to initiate a suspend
803 * of the entire ASoC card.
804 *
805 * \note Currently this function is stubbed out.
806 */
807int snd_soc_suspend_device(struct device *dev)
808{
809 return 0;
810}
811EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
812
813/**
814 * snd_soc_resume_device: Notify core of device resume
815 *
816 * @dev: Device being resumed.
817 *
818 * In order to ensure that the entire audio subsystem is resumed in a
819 * coordinated fashion ASoC devices should resume themselves when called
820 * by ASoC. When the standard kernel resume process asks the device
821 * to resume it should call this function. Once all the components of
822 * the card have notified that they are ready to be resumed the card
823 * will be resumed.
824 *
825 * \note Currently this function is stubbed out.
826 */
827int snd_soc_resume_device(struct device *dev)
828{
829 return 0;
830}
831EXPORT_SYMBOL_GPL(snd_soc_resume_device);
832#else 959#else
833#define soc_suspend NULL 960#define soc_suspend NULL
834#define soc_resume NULL 961#define soc_resume NULL
@@ -843,6 +970,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
843 struct platform_device, 970 struct platform_device,
844 dev); 971 dev);
845 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; 972 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
973 struct snd_soc_codec *codec;
846 struct snd_soc_platform *platform; 974 struct snd_soc_platform *platform;
847 struct snd_soc_dai *dai; 975 struct snd_soc_dai *dai;
848 int i, found, ret, ac97; 976 int i, found, ret, ac97;
@@ -931,6 +1059,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
931 if (ret < 0) 1059 if (ret < 0)
932 goto cpu_dai_err; 1060 goto cpu_dai_err;
933 } 1061 }
1062 codec = card->codec;
934 1063
935 if (platform->probe) { 1064 if (platform->probe) {
936 ret = platform->probe(pdev); 1065 ret = platform->probe(pdev);
@@ -945,10 +1074,69 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
945 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); 1074 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
946#endif 1075#endif
947 1076
1077 for (i = 0; i < card->num_links; i++) {
1078 if (card->dai_link[i].init) {
1079 ret = card->dai_link[i].init(codec);
1080 if (ret < 0) {
1081 printk(KERN_ERR "asoc: failed to init %s\n",
1082 card->dai_link[i].stream_name);
1083 continue;
1084 }
1085 }
1086 if (card->dai_link[i].codec_dai->ac97_control)
1087 ac97 = 1;
1088 }
1089
1090 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1091 "%s", card->name);
1092 snprintf(codec->card->longname, sizeof(codec->card->longname),
1093 "%s (%s)", card->name, codec->name);
1094
1095 /* Make sure all DAPM widgets are instantiated */
1096 snd_soc_dapm_new_widgets(codec);
1097
1098 ret = snd_card_register(codec->card);
1099 if (ret < 0) {
1100 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1101 codec->name);
1102 goto card_err;
1103 }
1104
1105 mutex_lock(&codec->mutex);
1106#ifdef CONFIG_SND_SOC_AC97_BUS
1107 /* Only instantiate AC97 if not already done by the adaptor
1108 * for the generic AC97 subsystem.
1109 */
1110 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1111 ret = soc_ac97_dev_register(codec);
1112 if (ret < 0) {
1113 printk(KERN_ERR "asoc: AC97 device register failed\n");
1114 snd_card_free(codec->card);
1115 mutex_unlock(&codec->mutex);
1116 goto card_err;
1117 }
1118 }
1119#endif
1120
1121 ret = snd_soc_dapm_sys_add(card->socdev->dev);
1122 if (ret < 0)
1123 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1124
1125 ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg);
1126 if (ret < 0)
1127 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1128
1129 soc_init_codec_debugfs(codec);
1130 mutex_unlock(&codec->mutex);
1131
948 card->instantiated = 1; 1132 card->instantiated = 1;
949 1133
950 return; 1134 return;
951 1135
1136card_err:
1137 if (platform->remove)
1138 platform->remove(pdev);
1139
952platform_err: 1140platform_err:
953 if (codec_dev->remove) 1141 if (codec_dev->remove)
954 codec_dev->remove(pdev); 1142 codec_dev->remove(pdev);
@@ -1151,157 +1339,6 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1151} 1339}
1152EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); 1340EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1153 1341
1154/* codec register dump */
1155static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1156{
1157 int i, step = 1, count = 0;
1158
1159 if (!codec->reg_cache_size)
1160 return 0;
1161
1162 if (codec->reg_cache_step)
1163 step = codec->reg_cache_step;
1164
1165 count += sprintf(buf, "%s registers\n", codec->name);
1166 for (i = 0; i < codec->reg_cache_size; i += step) {
1167 if (codec->readable_register && !codec->readable_register(i))
1168 continue;
1169
1170 count += sprintf(buf + count, "%2x: ", i);
1171 if (count >= PAGE_SIZE - 1)
1172 break;
1173
1174 if (codec->display_register)
1175 count += codec->display_register(codec, buf + count,
1176 PAGE_SIZE - count, i);
1177 else
1178 count += snprintf(buf + count, PAGE_SIZE - count,
1179 "%4x", codec->read(codec, i));
1180
1181 if (count >= PAGE_SIZE - 1)
1182 break;
1183
1184 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1185 if (count >= PAGE_SIZE - 1)
1186 break;
1187 }
1188
1189 /* Truncate count; min() would cause a warning */
1190 if (count >= PAGE_SIZE)
1191 count = PAGE_SIZE - 1;
1192
1193 return count;
1194}
1195static ssize_t codec_reg_show(struct device *dev,
1196 struct device_attribute *attr, char *buf)
1197{
1198 struct snd_soc_device *devdata = dev_get_drvdata(dev);
1199 return soc_codec_reg_show(devdata->card->codec, buf);
1200}
1201
1202static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
1203
1204#ifdef CONFIG_DEBUG_FS
1205static int codec_reg_open_file(struct inode *inode, struct file *file)
1206{
1207 file->private_data = inode->i_private;
1208 return 0;
1209}
1210
1211static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
1212 size_t count, loff_t *ppos)
1213{
1214 ssize_t ret;
1215 struct snd_soc_codec *codec = file->private_data;
1216 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1217 if (!buf)
1218 return -ENOMEM;
1219 ret = soc_codec_reg_show(codec, buf);
1220 if (ret >= 0)
1221 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1222 kfree(buf);
1223 return ret;
1224}
1225
1226static ssize_t codec_reg_write_file(struct file *file,
1227 const char __user *user_buf, size_t count, loff_t *ppos)
1228{
1229 char buf[32];
1230 int buf_size;
1231 char *start = buf;
1232 unsigned long reg, value;
1233 int step = 1;
1234 struct snd_soc_codec *codec = file->private_data;
1235
1236 buf_size = min(count, (sizeof(buf)-1));
1237 if (copy_from_user(buf, user_buf, buf_size))
1238 return -EFAULT;
1239 buf[buf_size] = 0;
1240
1241 if (codec->reg_cache_step)
1242 step = codec->reg_cache_step;
1243
1244 while (*start == ' ')
1245 start++;
1246 reg = simple_strtoul(start, &start, 16);
1247 if ((reg >= codec->reg_cache_size) || (reg % step))
1248 return -EINVAL;
1249 while (*start == ' ')
1250 start++;
1251 if (strict_strtoul(start, 16, &value))
1252 return -EINVAL;
1253 codec->write(codec, reg, value);
1254 return buf_size;
1255}
1256
1257static const struct file_operations codec_reg_fops = {
1258 .open = codec_reg_open_file,
1259 .read = codec_reg_read_file,
1260 .write = codec_reg_write_file,
1261};
1262
1263static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1264{
1265 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
1266 debugfs_root, codec,
1267 &codec_reg_fops);
1268 if (!codec->debugfs_reg)
1269 printk(KERN_WARNING
1270 "ASoC: Failed to create codec register debugfs file\n");
1271
1272 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
1273 debugfs_root,
1274 &codec->pop_time);
1275 if (!codec->debugfs_pop_time)
1276 printk(KERN_WARNING
1277 "Failed to create pop time debugfs file\n");
1278
1279 codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root);
1280 if (!codec->debugfs_dapm)
1281 printk(KERN_WARNING
1282 "Failed to create DAPM debugfs directory\n");
1283
1284 snd_soc_dapm_debugfs_init(codec);
1285}
1286
1287static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1288{
1289 debugfs_remove_recursive(codec->debugfs_dapm);
1290 debugfs_remove(codec->debugfs_pop_time);
1291 debugfs_remove(codec->debugfs_reg);
1292}
1293
1294#else
1295
1296static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1297{
1298}
1299
1300static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1301{
1302}
1303#endif
1304
1305/** 1342/**
1306 * snd_soc_new_ac97_codec - initailise AC97 device 1343 * snd_soc_new_ac97_codec - initailise AC97 device
1307 * @codec: audio codec 1344 * @codec: audio codec
@@ -1369,19 +1406,41 @@ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
1369 int change; 1406 int change;
1370 unsigned int old, new; 1407 unsigned int old, new;
1371 1408
1372 mutex_lock(&io_mutex);
1373 old = snd_soc_read(codec, reg); 1409 old = snd_soc_read(codec, reg);
1374 new = (old & ~mask) | value; 1410 new = (old & ~mask) | value;
1375 change = old != new; 1411 change = old != new;
1376 if (change) 1412 if (change)
1377 snd_soc_write(codec, reg, new); 1413 snd_soc_write(codec, reg, new);
1378 1414
1379 mutex_unlock(&io_mutex);
1380 return change; 1415 return change;
1381} 1416}
1382EXPORT_SYMBOL_GPL(snd_soc_update_bits); 1417EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1383 1418
1384/** 1419/**
1420 * snd_soc_update_bits_locked - update codec register bits
1421 * @codec: audio codec
1422 * @reg: codec register
1423 * @mask: register mask
1424 * @value: new value
1425 *
1426 * Writes new register value, and takes the codec mutex.
1427 *
1428 * Returns 1 for change else 0.
1429 */
1430static int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
1431 unsigned short reg, unsigned int mask,
1432 unsigned int value)
1433{
1434 int change;
1435
1436 mutex_lock(&codec->mutex);
1437 change = snd_soc_update_bits(codec, reg, mask, value);
1438 mutex_unlock(&codec->mutex);
1439
1440 return change;
1441}
1442
1443/**
1385 * snd_soc_test_bits - test register for change 1444 * snd_soc_test_bits - test register for change
1386 * @codec: audio codec 1445 * @codec: audio codec
1387 * @reg: codec register 1446 * @reg: codec register
@@ -1399,11 +1458,9 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1399 int change; 1458 int change;
1400 unsigned int old, new; 1459 unsigned int old, new;
1401 1460
1402 mutex_lock(&io_mutex);
1403 old = snd_soc_read(codec, reg); 1461 old = snd_soc_read(codec, reg);
1404 new = (old & ~mask) | value; 1462 new = (old & ~mask) | value;
1405 change = old != new; 1463 change = old != new;
1406 mutex_unlock(&io_mutex);
1407 1464
1408 return change; 1465 return change;
1409} 1466}
@@ -1450,89 +1507,16 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1450 mutex_unlock(&codec->mutex); 1507 mutex_unlock(&codec->mutex);
1451 return ret; 1508 return ret;
1452 } 1509 }
1453 }
1454
1455 mutex_unlock(&codec->mutex);
1456 return ret;
1457}
1458EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1459
1460/**
1461 * snd_soc_init_card - register sound card
1462 * @socdev: the SoC audio device
1463 *
1464 * Register a SoC sound card. Also registers an AC97 device if the
1465 * codec is AC97 for ad hoc devices.
1466 *
1467 * Returns 0 for success, else error.
1468 */
1469int snd_soc_init_card(struct snd_soc_device *socdev)
1470{
1471 struct snd_soc_card *card = socdev->card;
1472 struct snd_soc_codec *codec = card->codec;
1473 int ret = 0, i, ac97 = 0, err = 0;
1474
1475 for (i = 0; i < card->num_links; i++) {
1476 if (card->dai_link[i].init) {
1477 err = card->dai_link[i].init(codec);
1478 if (err < 0) {
1479 printk(KERN_ERR "asoc: failed to init %s\n",
1480 card->dai_link[i].stream_name);
1481 continue;
1482 }
1483 }
1484 if (card->dai_link[i].codec_dai->ac97_control) { 1510 if (card->dai_link[i].codec_dai->ac97_control) {
1485 ac97 = 1;
1486 snd_ac97_dev_add_pdata(codec->ac97, 1511 snd_ac97_dev_add_pdata(codec->ac97,
1487 card->dai_link[i].cpu_dai->ac97_pdata); 1512 card->dai_link[i].cpu_dai->ac97_pdata);
1488 } 1513 }
1489 } 1514 }
1490 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1491 "%s", card->name);
1492 snprintf(codec->card->longname, sizeof(codec->card->longname),
1493 "%s (%s)", card->name, codec->name);
1494
1495 /* Make sure all DAPM widgets are instantiated */
1496 snd_soc_dapm_new_widgets(codec);
1497
1498 ret = snd_card_register(codec->card);
1499 if (ret < 0) {
1500 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1501 codec->name);
1502 goto out;
1503 }
1504
1505 mutex_lock(&codec->mutex);
1506#ifdef CONFIG_SND_SOC_AC97_BUS
1507 /* Only instantiate AC97 if not already done by the adaptor
1508 * for the generic AC97 subsystem.
1509 */
1510 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1511 ret = soc_ac97_dev_register(codec);
1512 if (ret < 0) {
1513 printk(KERN_ERR "asoc: AC97 device register failed\n");
1514 snd_card_free(codec->card);
1515 mutex_unlock(&codec->mutex);
1516 goto out;
1517 }
1518 }
1519#endif
1520
1521 err = snd_soc_dapm_sys_add(socdev->dev);
1522 if (err < 0)
1523 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1524
1525 err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1526 if (err < 0)
1527 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1528 1515
1529 soc_init_codec_debugfs(codec);
1530 mutex_unlock(&codec->mutex); 1516 mutex_unlock(&codec->mutex);
1531
1532out:
1533 return ret; 1517 return ret;
1534} 1518}
1535EXPORT_SYMBOL_GPL(snd_soc_init_card); 1519EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1536 1520
1537/** 1521/**
1538 * snd_soc_free_pcms - free sound card and pcms 1522 * snd_soc_free_pcms - free sound card and pcms
@@ -1734,7 +1718,7 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1734 mask |= (bitmask - 1) << e->shift_r; 1718 mask |= (bitmask - 1) << e->shift_r;
1735 } 1719 }
1736 1720
1737 return snd_soc_update_bits(codec, e->reg, mask, val); 1721 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1738} 1722}
1739EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 1723EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1740 1724
@@ -1808,7 +1792,7 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
1808 mask |= e->mask << e->shift_r; 1792 mask |= e->mask << e->shift_r;
1809 } 1793 }
1810 1794
1811 return snd_soc_update_bits(codec, e->reg, mask, val); 1795 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1812} 1796}
1813EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); 1797EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
1814 1798
@@ -1969,7 +1953,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1969 val_mask |= mask << rshift; 1953 val_mask |= mask << rshift;
1970 val |= val2 << rshift; 1954 val |= val2 << rshift;
1971 } 1955 }
1972 return snd_soc_update_bits(codec, reg, val_mask, val); 1956 return snd_soc_update_bits_locked(codec, reg, val_mask, val);
1973} 1957}
1974EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 1958EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1975 1959
@@ -2075,11 +2059,11 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
2075 val = val << shift; 2059 val = val << shift;
2076 val2 = val2 << shift; 2060 val2 = val2 << shift;
2077 2061
2078 err = snd_soc_update_bits(codec, reg, val_mask, val); 2062 err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
2079 if (err < 0) 2063 if (err < 0)
2080 return err; 2064 return err;
2081 2065
2082 err = snd_soc_update_bits(codec, reg2, val_mask, val2); 2066 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
2083 return err; 2067 return err;
2084} 2068}
2085EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); 2069EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
@@ -2158,7 +2142,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2158 val = (ucontrol->value.integer.value[0]+min) & 0xff; 2142 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2159 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; 2143 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
2160 2144
2161 return snd_soc_update_bits(codec, reg, 0xffff, val); 2145 return snd_soc_update_bits_locked(codec, reg, 0xffff, val);
2162} 2146}
2163EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); 2147EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2164 2148
@@ -2205,16 +2189,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2205 * snd_soc_dai_set_pll - configure DAI PLL. 2189 * snd_soc_dai_set_pll - configure DAI PLL.
2206 * @dai: DAI 2190 * @dai: DAI
2207 * @pll_id: DAI specific PLL ID 2191 * @pll_id: DAI specific PLL ID
2192 * @source: DAI specific source for the PLL
2208 * @freq_in: PLL input clock frequency in Hz 2193 * @freq_in: PLL input clock frequency in Hz
2209 * @freq_out: requested PLL output clock frequency in Hz 2194 * @freq_out: requested PLL output clock frequency in Hz
2210 * 2195 *
2211 * Configures and enables PLL to generate output clock based on input clock. 2196 * Configures and enables PLL to generate output clock based on input clock.
2212 */ 2197 */
2213int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2198int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2214 int pll_id, unsigned int freq_in, unsigned int freq_out) 2199 unsigned int freq_in, unsigned int freq_out)
2215{ 2200{
2216 if (dai->ops && dai->ops->set_pll) 2201 if (dai->ops && dai->ops->set_pll)
2217 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2202 return dai->ops->set_pll(dai, pll_id, source,
2203 freq_in, freq_out);
2218 else 2204 else
2219 return -EINVAL; 2205 return -EINVAL;
2220} 2206}
@@ -2259,6 +2245,30 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2259EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 2245EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2260 2246
2261/** 2247/**
2248 * snd_soc_dai_set_channel_map - configure DAI audio channel map
2249 * @dai: DAI
2250 * @tx_num: how many TX channels
2251 * @tx_slot: pointer to an array which imply the TX slot number channel
2252 * 0~num-1 uses
2253 * @rx_num: how many RX channels
2254 * @rx_slot: pointer to an array which imply the RX slot number channel
2255 * 0~num-1 uses
2256 *
2257 * configure the relationship between channel number and TDM slot number.
2258 */
2259int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2260 unsigned int tx_num, unsigned int *tx_slot,
2261 unsigned int rx_num, unsigned int *rx_slot)
2262{
2263 if (dai->ops && dai->ops->set_channel_map)
2264 return dai->ops->set_channel_map(dai, tx_num, tx_slot,
2265 rx_num, rx_slot);
2266 else
2267 return -EINVAL;
2268}
2269EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2270
2271/**
2262 * snd_soc_dai_set_tristate - configure DAI system or master clock. 2272 * snd_soc_dai_set_tristate - configure DAI system or master clock.
2263 * @dai: DAI 2273 * @dai: DAI
2264 * @tristate: tristate enable 2274 * @tristate: tristate enable
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 66d4c165f99b..0d294ef72590 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -719,6 +719,10 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
719 719
720 /* Check if one of our outputs is connected */ 720 /* Check if one of our outputs is connected */
721 list_for_each_entry(path, &w->sinks, list_source) { 721 list_for_each_entry(path, &w->sinks, list_source) {
722 if (path->connected &&
723 !path->connected(path->source, path->sink))
724 continue;
725
722 if (path->sink && path->sink->power_check && 726 if (path->sink && path->sink->power_check &&
723 path->sink->power_check(path->sink)) { 727 path->sink->power_check(path->sink)) {
724 power = 1; 728 power = 1;
@@ -1152,6 +1156,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1152 w->active ? "active" : "inactive"); 1156 w->active ? "active" : "inactive");
1153 1157
1154 list_for_each_entry(p, &w->sources, list_sink) { 1158 list_for_each_entry(p, &w->sources, list_sink) {
1159 if (p->connected && !p->connected(w, p->sink))
1160 continue;
1161
1155 if (p->connect) 1162 if (p->connect)
1156 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1163 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1157 " in %s %s\n", 1164 " in %s %s\n",
@@ -1159,6 +1166,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1159 p->source->name); 1166 p->source->name);
1160 } 1167 }
1161 list_for_each_entry(p, &w->sinks, list_source) { 1168 list_for_each_entry(p, &w->sinks, list_source) {
1169 if (p->connected && !p->connected(w, p->sink))
1170 continue;
1171
1162 if (p->connect) 1172 if (p->connect)
1163 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1173 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1164 " out %s %s\n", 1174 " out %s %s\n",
@@ -1206,8 +1216,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1206 1216
1207/* test and update the power status of a mux widget */ 1217/* test and update the power status of a mux widget */
1208static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1218static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1209 struct snd_kcontrol *kcontrol, int mask, 1219 struct snd_kcontrol *kcontrol, int change,
1210 int mux, int val, struct soc_enum *e) 1220 int mux, struct soc_enum *e)
1211{ 1221{
1212 struct snd_soc_dapm_path *path; 1222 struct snd_soc_dapm_path *path;
1213 int found = 0; 1223 int found = 0;
@@ -1216,7 +1226,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1216 widget->id != snd_soc_dapm_value_mux) 1226 widget->id != snd_soc_dapm_value_mux)
1217 return -ENODEV; 1227 return -ENODEV;
1218 1228
1219 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val)) 1229 if (!change)
1220 return 0; 1230 return 0;
1221 1231
1222 /* find dapm widget path assoc with kcontrol */ 1232 /* find dapm widget path assoc with kcontrol */
@@ -1401,10 +1411,13 @@ int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1401EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 1411EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1402 1412
1403static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 1413static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1404 const char *sink, const char *control, const char *source) 1414 const struct snd_soc_dapm_route *route)
1405{ 1415{
1406 struct snd_soc_dapm_path *path; 1416 struct snd_soc_dapm_path *path;
1407 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1417 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1418 const char *sink = route->sink;
1419 const char *control = route->control;
1420 const char *source = route->source;
1408 int ret = 0; 1421 int ret = 0;
1409 1422
1410 /* find src and dest widgets */ 1423 /* find src and dest widgets */
@@ -1428,6 +1441,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1428 1441
1429 path->source = wsource; 1442 path->source = wsource;
1430 path->sink = wsink; 1443 path->sink = wsink;
1444 path->connected = route->connected;
1431 INIT_LIST_HEAD(&path->list); 1445 INIT_LIST_HEAD(&path->list);
1432 INIT_LIST_HEAD(&path->list_source); 1446 INIT_LIST_HEAD(&path->list_source);
1433 INIT_LIST_HEAD(&path->list_sink); 1447 INIT_LIST_HEAD(&path->list_sink);
@@ -1528,8 +1542,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1528 int i, ret; 1542 int i, ret;
1529 1543
1530 for (i = 0; i < num; i++) { 1544 for (i = 0; i < num; i++) {
1531 ret = snd_soc_dapm_add_route(codec, route->sink, 1545 ret = snd_soc_dapm_add_route(codec, route);
1532 route->control, route->source);
1533 if (ret < 0) { 1546 if (ret < 0) {
1534 printk(KERN_ERR "Failed to add route %s->%s\n", 1547 printk(KERN_ERR "Failed to add route %s->%s\n",
1535 route->source, 1548 route->source,
@@ -1766,7 +1779,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1766{ 1779{
1767 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1780 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1768 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1781 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1769 unsigned int val, mux; 1782 unsigned int val, mux, change;
1770 unsigned int mask, bitmask; 1783 unsigned int mask, bitmask;
1771 int ret = 0; 1784 int ret = 0;
1772 1785
@@ -1786,20 +1799,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1786 1799
1787 mutex_lock(&widget->codec->mutex); 1800 mutex_lock(&widget->codec->mutex);
1788 widget->value = val; 1801 widget->value = val;
1789 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1802 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1790 if (widget->event) { 1803 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1791 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1804
1792 ret = widget->event(widget, 1805 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1793 kcontrol, SND_SOC_DAPM_PRE_REG); 1806 ret = widget->event(widget,
1794 if (ret < 0) 1807 kcontrol, SND_SOC_DAPM_PRE_REG);
1795 goto out; 1808 if (ret < 0)
1796 } 1809 goto out;
1797 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1810 }
1798 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1811
1799 ret = widget->event(widget, 1812 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1800 kcontrol, SND_SOC_DAPM_POST_REG); 1813
1801 } else 1814 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1802 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1815 ret = widget->event(widget,
1816 kcontrol, SND_SOC_DAPM_POST_REG);
1803 1817
1804out: 1818out:
1805 mutex_unlock(&widget->codec->mutex); 1819 mutex_unlock(&widget->codec->mutex);
@@ -1808,6 +1822,54 @@ out:
1808EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1822EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1809 1823
1810/** 1824/**
1825 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
1826 * @kcontrol: mixer control
1827 * @ucontrol: control element information
1828 *
1829 * Returns 0 for success.
1830 */
1831int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
1832 struct snd_ctl_elem_value *ucontrol)
1833{
1834 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1835
1836 ucontrol->value.enumerated.item[0] = widget->value;
1837
1838 return 0;
1839}
1840EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
1841
1842/**
1843 * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
1844 * @kcontrol: mixer control
1845 * @ucontrol: control element information
1846 *
1847 * Returns 0 for success.
1848 */
1849int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
1850 struct snd_ctl_elem_value *ucontrol)
1851{
1852 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1853 struct soc_enum *e =
1854 (struct soc_enum *)kcontrol->private_value;
1855 int change;
1856 int ret = 0;
1857
1858 if (ucontrol->value.enumerated.item[0] >= e->max)
1859 return -EINVAL;
1860
1861 mutex_lock(&widget->codec->mutex);
1862
1863 change = widget->value != ucontrol->value.enumerated.item[0];
1864 widget->value = ucontrol->value.enumerated.item[0];
1865 dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
1866
1867 mutex_unlock(&widget->codec->mutex);
1868 return ret;
1869}
1870EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
1871
1872/**
1811 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get 1873 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1812 * callback 1874 * callback
1813 * @kcontrol: mixer control 1875 * @kcontrol: mixer control
@@ -1865,7 +1927,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1865{ 1927{
1866 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1928 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1867 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1929 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1868 unsigned int val, mux; 1930 unsigned int val, mux, change;
1869 unsigned int mask; 1931 unsigned int mask;
1870 int ret = 0; 1932 int ret = 0;
1871 1933
@@ -1883,20 +1945,21 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1883 1945
1884 mutex_lock(&widget->codec->mutex); 1946 mutex_lock(&widget->codec->mutex);
1885 widget->value = val; 1947 widget->value = val;
1886 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1948 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1887 if (widget->event) { 1949 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1888 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1950
1889 ret = widget->event(widget, 1951 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1890 kcontrol, SND_SOC_DAPM_PRE_REG); 1952 ret = widget->event(widget,
1891 if (ret < 0) 1953 kcontrol, SND_SOC_DAPM_PRE_REG);
1892 goto out; 1954 if (ret < 0)
1893 } 1955 goto out;
1894 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1956 }
1895 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1957
1896 ret = widget->event(widget, 1958 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1897 kcontrol, SND_SOC_DAPM_POST_REG); 1959
1898 } else 1960 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1899 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1961 ret = widget->event(widget,
1962 kcontrol, SND_SOC_DAPM_POST_REG);
1900 1963
1901out: 1964out:
1902 mutex_unlock(&widget->codec->mutex); 1965 mutex_unlock(&widget->codec->mutex);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 1d455ab79490..3c07a94c2e30 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new);
58 */ 58 */
59void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) 59void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
60{ 60{
61 struct snd_soc_codec *codec = jack->card->codec; 61 struct snd_soc_codec *codec;
62 struct snd_soc_jack_pin *pin; 62 struct snd_soc_jack_pin *pin;
63 int enable; 63 int enable;
64 int oldstatus; 64 int oldstatus;
@@ -67,6 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
67 WARN_ON_ONCE(!jack); 67 WARN_ON_ONCE(!jack);
68 return; 68 return;
69 } 69 }
70 codec = jack->card->codec;
70 71
71 mutex_lock(&codec->mutex); 72 mutex_lock(&codec->mutex);
72 73
@@ -162,6 +163,9 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
162 else 163 else
163 report = 0; 164 report = 0;
164 165
166 if (gpio->jack_status_check)
167 report = gpio->jack_status_check();
168
165 snd_soc_jack_report(jack, report, gpio->report); 169 snd_soc_jack_report(jack, report, gpio->report);
166} 170}
167 171
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
new file mode 100644
index 000000000000..1d07b931f3d8
--- /dev/null
+++ b/sound/soc/soc-utils.c
@@ -0,0 +1,74 @@
1/*
2 * soc-util.c -- ALSA SoC Audio Layer utility functions
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * Liam Girdwood <lrg@slimlogic.co.uk>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20
21int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots)
22{
23 return sample_size * channels * tdm_slots;
24}
25EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size);
26
27int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
28{
29 int sample_size;
30
31 switch (params_format(params)) {
32 case SNDRV_PCM_FORMAT_S16_LE:
33 case SNDRV_PCM_FORMAT_S16_BE:
34 sample_size = 16;
35 break;
36 case SNDRV_PCM_FORMAT_S20_3LE:
37 case SNDRV_PCM_FORMAT_S20_3BE:
38 sample_size = 20;
39 break;
40 case SNDRV_PCM_FORMAT_S24_LE:
41 case SNDRV_PCM_FORMAT_S24_BE:
42 sample_size = 24;
43 break;
44 case SNDRV_PCM_FORMAT_S32_LE:
45 case SNDRV_PCM_FORMAT_S32_BE:
46 sample_size = 32;
47 break;
48 default:
49 return -ENOTSUPP;
50 }
51
52 return snd_soc_calc_frame_size(sample_size, params_channels(params),
53 1);
54}
55EXPORT_SYMBOL_GPL(snd_soc_params_to_frame_size);
56
57int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots)
58{
59 return fs * snd_soc_calc_frame_size(sample_size, channels, tdm_slots);
60}
61EXPORT_SYMBOL_GPL(snd_soc_calc_bclk);
62
63int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
64{
65 int ret;
66
67 ret = snd_soc_params_to_frame_size(params);
68
69 if (ret > 0)
70 return ret * params_rate(params);
71 else
72 return ret;
73}
74EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 8db0374e10d5..b074a594c595 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2893,7 +2893,9 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
2893 if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || 2893 if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
2894 altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && 2894 altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
2895 altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) { 2895 altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
2896 if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) { 2896 int err = snd_usbmidi_create(chip->card, iface,
2897 &chip->midi_list, NULL);
2898 if (err < 0) {
2897 snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j); 2899 snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j);
2898 continue; 2900 continue;
2899 } 2901 }
@@ -3038,12 +3040,11 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
3038 .type = QUIRK_MIDI_FIXED_ENDPOINT, 3040 .type = QUIRK_MIDI_FIXED_ENDPOINT,
3039 .data = &uaxx_ep 3041 .data = &uaxx_ep
3040 }; 3042 };
3041 if (chip->usb_id == USB_ID(0x0582, 0x002b)) 3043 const struct snd_usb_audio_quirk *quirk =
3042 return snd_usb_create_midi_interface(chip, iface, 3044 chip->usb_id == USB_ID(0x0582, 0x002b)
3043 &ua700_quirk); 3045 ? &ua700_quirk : &uaxx_quirk;
3044 else 3046 return snd_usbmidi_create(chip->card, iface,
3045 return snd_usb_create_midi_interface(chip, iface, 3047 &chip->midi_list, quirk);
3046 &uaxx_quirk);
3047 } 3048 }
3048 3049
3049 if (altsd->bNumEndpoints != 1) 3050 if (altsd->bNumEndpoints != 1)
@@ -3370,6 +3371,13 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
3370 return 0; /* keep this altsetting */ 3371 return 0; /* keep this altsetting */
3371} 3372}
3372 3373
3374static int create_any_midi_quirk(struct snd_usb_audio *chip,
3375 struct usb_interface *intf,
3376 const struct snd_usb_audio_quirk *quirk)
3377{
3378 return snd_usbmidi_create(chip->card, intf, &chip->midi_list, quirk);
3379}
3380
3373/* 3381/*
3374 * audio-interface quirks 3382 * audio-interface quirks
3375 * 3383 *
@@ -3387,14 +3395,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
3387 static const quirk_func_t quirk_funcs[] = { 3395 static const quirk_func_t quirk_funcs[] = {
3388 [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, 3396 [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
3389 [QUIRK_COMPOSITE] = create_composite_quirk, 3397 [QUIRK_COMPOSITE] = create_composite_quirk,
3390 [QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface, 3398 [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
3391 [QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface, 3399 [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
3392 [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface, 3400 [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
3393 [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface, 3401 [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
3394 [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, 3402 [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
3395 [QUIRK_MIDI_FASTLANE] = snd_usb_create_midi_interface, 3403 [QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
3396 [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, 3404 [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
3397 [QUIRK_MIDI_CME] = snd_usb_create_midi_interface, 3405 [QUIRK_MIDI_CME] = create_any_midi_quirk,
3398 [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, 3406 [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
3399 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, 3407 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
3400 [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, 3408 [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index e9a3a9dca15c..40ba8115fb81 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -132,7 +132,6 @@ struct snd_usb_audio {
132 int pcm_devs; 132 int pcm_devs;
133 133
134 struct list_head midi_list; /* list of midi interfaces */ 134 struct list_head midi_list; /* list of midi interfaces */
135 int next_midi_device;
136 135
137 struct list_head mixer_list; /* list of mixer interfaces */ 136 struct list_head mixer_list; /* list of mixer interfaces */
138}; 137};
@@ -227,8 +226,10 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
227 int ignore_error); 226 int ignore_error);
228void snd_usb_mixer_disconnect(struct list_head *p); 227void snd_usb_mixer_disconnect(struct list_head *p);
229 228
230int snd_usb_create_midi_interface(struct snd_usb_audio *chip, struct usb_interface *iface, 229int snd_usbmidi_create(struct snd_card *card,
231 const struct snd_usb_audio_quirk *quirk); 230 struct usb_interface *iface,
231 struct list_head *midi_list,
232 const struct snd_usb_audio_quirk *quirk);
232void snd_usbmidi_input_stop(struct list_head* p); 233void snd_usbmidi_input_stop(struct list_head* p);
233void snd_usbmidi_input_start(struct list_head* p); 234void snd_usbmidi_input_start(struct list_head* p);
234void snd_usbmidi_disconnect(struct list_head *p); 235void snd_usbmidi_disconnect(struct list_head *p);
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 0eff19ceb7e1..6e89b8368d9a 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * usbmidi.c - ALSA USB MIDI driver 2 * usbmidi.c - ALSA USB MIDI driver
3 * 3 *
4 * Copyright (c) 2002-2007 Clemens Ladisch 4 * Copyright (c) 2002-2009 Clemens Ladisch
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Based on the OSS usb-midi driver by NAGANO Daisuke, 7 * Based on the OSS usb-midi driver by NAGANO Daisuke,
@@ -47,6 +47,7 @@
47#include <linux/usb.h> 47#include <linux/usb.h>
48#include <linux/wait.h> 48#include <linux/wait.h>
49#include <sound/core.h> 49#include <sound/core.h>
50#include <sound/control.h>
50#include <sound/rawmidi.h> 51#include <sound/rawmidi.h>
51#include <sound/asequencer.h> 52#include <sound/asequencer.h>
52#include "usbaudio.h" 53#include "usbaudio.h"
@@ -101,7 +102,8 @@ struct usb_protocol_ops {
101}; 102};
102 103
103struct snd_usb_midi { 104struct snd_usb_midi {
104 struct snd_usb_audio *chip; 105 struct usb_device *dev;
106 struct snd_card *card;
105 struct usb_interface *iface; 107 struct usb_interface *iface;
106 const struct snd_usb_audio_quirk *quirk; 108 const struct snd_usb_audio_quirk *quirk;
107 struct snd_rawmidi *rmidi; 109 struct snd_rawmidi *rmidi;
@@ -109,13 +111,19 @@ struct snd_usb_midi {
109 struct list_head list; 111 struct list_head list;
110 struct timer_list error_timer; 112 struct timer_list error_timer;
111 spinlock_t disc_lock; 113 spinlock_t disc_lock;
114 struct mutex mutex;
115 u32 usb_id;
116 int next_midi_device;
112 117
113 struct snd_usb_midi_endpoint { 118 struct snd_usb_midi_endpoint {
114 struct snd_usb_midi_out_endpoint *out; 119 struct snd_usb_midi_out_endpoint *out;
115 struct snd_usb_midi_in_endpoint *in; 120 struct snd_usb_midi_in_endpoint *in;
116 } endpoints[MIDI_MAX_ENDPOINTS]; 121 } endpoints[MIDI_MAX_ENDPOINTS];
117 unsigned long input_triggered; 122 unsigned long input_triggered;
123 unsigned int opened;
118 unsigned char disconnected; 124 unsigned char disconnected;
125
126 struct snd_kcontrol *roland_load_ctl;
119}; 127};
120 128
121struct snd_usb_midi_out_endpoint { 129struct snd_usb_midi_out_endpoint {
@@ -255,7 +263,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb)
255 } 263 }
256 } 264 }
257 265
258 urb->dev = ep->umidi->chip->dev; 266 urb->dev = ep->umidi->dev;
259 snd_usbmidi_submit_urb(urb, GFP_ATOMIC); 267 snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
260} 268}
261 269
@@ -296,7 +304,7 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
296 unsigned long flags; 304 unsigned long flags;
297 305
298 spin_lock_irqsave(&ep->buffer_lock, flags); 306 spin_lock_irqsave(&ep->buffer_lock, flags);
299 if (ep->umidi->chip->shutdown) { 307 if (ep->umidi->disconnected) {
300 spin_unlock_irqrestore(&ep->buffer_lock, flags); 308 spin_unlock_irqrestore(&ep->buffer_lock, flags);
301 return; 309 return;
302 } 310 }
@@ -312,7 +320,7 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
312 320
313 dump_urb("sending", urb->transfer_buffer, 321 dump_urb("sending", urb->transfer_buffer,
314 urb->transfer_buffer_length); 322 urb->transfer_buffer_length);
315 urb->dev = ep->umidi->chip->dev; 323 urb->dev = ep->umidi->dev;
316 if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0) 324 if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0)
317 break; 325 break;
318 ep->active_urbs |= 1 << urb_index; 326 ep->active_urbs |= 1 << urb_index;
@@ -349,7 +357,7 @@ static void snd_usbmidi_error_timer(unsigned long data)
349 if (in && in->error_resubmit) { 357 if (in && in->error_resubmit) {
350 in->error_resubmit = 0; 358 in->error_resubmit = 0;
351 for (j = 0; j < INPUT_URBS; ++j) { 359 for (j = 0; j < INPUT_URBS; ++j) {
352 in->urbs[j]->dev = umidi->chip->dev; 360 in->urbs[j]->dev = umidi->dev;
353 snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); 361 snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
354 } 362 }
355 } 363 }
@@ -369,7 +377,7 @@ static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
369 return -ENOMEM; 377 return -ENOMEM;
370 dump_urb("sending", buf, len); 378 dump_urb("sending", buf, len);
371 if (ep->urbs[0].urb) 379 if (ep->urbs[0].urb)
372 err = usb_bulk_msg(ep->umidi->chip->dev, ep->urbs[0].urb->pipe, 380 err = usb_bulk_msg(ep->umidi->dev, ep->urbs[0].urb->pipe,
373 buf, len, NULL, 250); 381 buf, len, NULL, 250);
374 kfree(buf); 382 kfree(buf);
375 return err; 383 return err;
@@ -724,8 +732,7 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
724 732
725 if (!ep->ports[0].active) 733 if (!ep->ports[0].active)
726 return; 734 return;
727 count = snd_usb_get_speed(ep->umidi->chip->dev) == USB_SPEED_HIGH 735 count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2;
728 ? 1 : 2;
729 count = snd_rawmidi_transmit(ep->ports[0].substream, 736 count = snd_rawmidi_transmit(ep->ports[0].substream,
730 urb->transfer_buffer, 737 urb->transfer_buffer,
731 count); 738 count);
@@ -879,6 +886,50 @@ static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
879}; 886};
880 887
881 888
889static void update_roland_altsetting(struct snd_usb_midi* umidi)
890{
891 struct usb_interface *intf;
892 struct usb_host_interface *hostif;
893 struct usb_interface_descriptor *intfd;
894 int is_light_load;
895
896 intf = umidi->iface;
897 is_light_load = intf->cur_altsetting != intf->altsetting;
898 if (umidi->roland_load_ctl->private_value == is_light_load)
899 return;
900 hostif = &intf->altsetting[umidi->roland_load_ctl->private_value];
901 intfd = get_iface_desc(hostif);
902 snd_usbmidi_input_stop(&umidi->list);
903 usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
904 intfd->bAlternateSetting);
905 snd_usbmidi_input_start(&umidi->list);
906}
907
908static void substream_open(struct snd_rawmidi_substream *substream, int open)
909{
910 struct snd_usb_midi* umidi = substream->rmidi->private_data;
911 struct snd_kcontrol *ctl;
912
913 mutex_lock(&umidi->mutex);
914 if (open) {
915 if (umidi->opened++ == 0 && umidi->roland_load_ctl) {
916 ctl = umidi->roland_load_ctl;
917 ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
918 snd_ctl_notify(umidi->card,
919 SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
920 update_roland_altsetting(umidi);
921 }
922 } else {
923 if (--umidi->opened == 0 && umidi->roland_load_ctl) {
924 ctl = umidi->roland_load_ctl;
925 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
926 snd_ctl_notify(umidi->card,
927 SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
928 }
929 }
930 mutex_unlock(&umidi->mutex);
931}
932
882static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) 933static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
883{ 934{
884 struct snd_usb_midi* umidi = substream->rmidi->private_data; 935 struct snd_usb_midi* umidi = substream->rmidi->private_data;
@@ -898,11 +949,13 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
898 } 949 }
899 substream->runtime->private_data = port; 950 substream->runtime->private_data = port;
900 port->state = STATE_UNKNOWN; 951 port->state = STATE_UNKNOWN;
952 substream_open(substream, 1);
901 return 0; 953 return 0;
902} 954}
903 955
904static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) 956static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
905{ 957{
958 substream_open(substream, 0);
906 return 0; 959 return 0;
907} 960}
908 961
@@ -912,7 +965,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
912 965
913 port->active = up; 966 port->active = up;
914 if (up) { 967 if (up) {
915 if (port->ep->umidi->chip->shutdown) { 968 if (port->ep->umidi->disconnected) {
916 /* gobble up remaining bytes to prevent wait in 969 /* gobble up remaining bytes to prevent wait in
917 * snd_rawmidi_drain_output */ 970 * snd_rawmidi_drain_output */
918 while (!snd_rawmidi_transmit_empty(substream)) 971 while (!snd_rawmidi_transmit_empty(substream))
@@ -954,11 +1007,13 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
954 1007
955static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) 1008static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
956{ 1009{
1010 substream_open(substream, 1);
957 return 0; 1011 return 0;
958} 1012}
959 1013
960static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) 1014static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
961{ 1015{
1016 substream_open(substream, 0);
962 return 0; 1017 return 0;
963} 1018}
964 1019
@@ -988,7 +1043,7 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
988static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb, 1043static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb,
989 unsigned int buffer_length) 1044 unsigned int buffer_length)
990{ 1045{
991 usb_buffer_free(umidi->chip->dev, buffer_length, 1046 usb_buffer_free(umidi->dev, buffer_length,
992 urb->transfer_buffer, urb->transfer_dma); 1047 urb->transfer_buffer, urb->transfer_dma);
993 usb_free_urb(urb); 1048 usb_free_urb(urb);
994} 1049}
@@ -1035,24 +1090,24 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
1035 } 1090 }
1036 } 1091 }
1037 if (ep_info->in_interval) 1092 if (ep_info->in_interval)
1038 pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); 1093 pipe = usb_rcvintpipe(umidi->dev, ep_info->in_ep);
1039 else 1094 else
1040 pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); 1095 pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep);
1041 length = usb_maxpacket(umidi->chip->dev, pipe, 0); 1096 length = usb_maxpacket(umidi->dev, pipe, 0);
1042 for (i = 0; i < INPUT_URBS; ++i) { 1097 for (i = 0; i < INPUT_URBS; ++i) {
1043 buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, 1098 buffer = usb_buffer_alloc(umidi->dev, length, GFP_KERNEL,
1044 &ep->urbs[i]->transfer_dma); 1099 &ep->urbs[i]->transfer_dma);
1045 if (!buffer) { 1100 if (!buffer) {
1046 snd_usbmidi_in_endpoint_delete(ep); 1101 snd_usbmidi_in_endpoint_delete(ep);
1047 return -ENOMEM; 1102 return -ENOMEM;
1048 } 1103 }
1049 if (ep_info->in_interval) 1104 if (ep_info->in_interval)
1050 usb_fill_int_urb(ep->urbs[i], umidi->chip->dev, 1105 usb_fill_int_urb(ep->urbs[i], umidi->dev,
1051 pipe, buffer, length, 1106 pipe, buffer, length,
1052 snd_usbmidi_in_urb_complete, 1107 snd_usbmidi_in_urb_complete,
1053 ep, ep_info->in_interval); 1108 ep, ep_info->in_interval);
1054 else 1109 else
1055 usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev, 1110 usb_fill_bulk_urb(ep->urbs[i], umidi->dev,
1056 pipe, buffer, length, 1111 pipe, buffer, length,
1057 snd_usbmidi_in_urb_complete, ep); 1112 snd_usbmidi_in_urb_complete, ep);
1058 ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 1113 ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
@@ -1062,15 +1117,6 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
1062 return 0; 1117 return 0;
1063} 1118}
1064 1119
1065static unsigned int snd_usbmidi_count_bits(unsigned int x)
1066{
1067 unsigned int bits;
1068
1069 for (bits = 0; x; ++bits)
1070 x &= x - 1;
1071 return bits;
1072}
1073
1074/* 1120/*
1075 * Frees an output endpoint. 1121 * Frees an output endpoint.
1076 * May be called when ep hasn't been initialized completely. 1122 * May be called when ep hasn't been initialized completely.
@@ -1113,15 +1159,15 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
1113 ep->urbs[i].ep = ep; 1159 ep->urbs[i].ep = ep;
1114 } 1160 }
1115 if (ep_info->out_interval) 1161 if (ep_info->out_interval)
1116 pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep); 1162 pipe = usb_sndintpipe(umidi->dev, ep_info->out_ep);
1117 else 1163 else
1118 pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); 1164 pipe = usb_sndbulkpipe(umidi->dev, ep_info->out_ep);
1119 if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ 1165 if (umidi->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
1120 ep->max_transfer = 4; 1166 ep->max_transfer = 4;
1121 else 1167 else
1122 ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); 1168 ep->max_transfer = usb_maxpacket(umidi->dev, pipe, 1);
1123 for (i = 0; i < OUTPUT_URBS; ++i) { 1169 for (i = 0; i < OUTPUT_URBS; ++i) {
1124 buffer = usb_buffer_alloc(umidi->chip->dev, 1170 buffer = usb_buffer_alloc(umidi->dev,
1125 ep->max_transfer, GFP_KERNEL, 1171 ep->max_transfer, GFP_KERNEL,
1126 &ep->urbs[i].urb->transfer_dma); 1172 &ep->urbs[i].urb->transfer_dma);
1127 if (!buffer) { 1173 if (!buffer) {
@@ -1129,12 +1175,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
1129 return -ENOMEM; 1175 return -ENOMEM;
1130 } 1176 }
1131 if (ep_info->out_interval) 1177 if (ep_info->out_interval)
1132 usb_fill_int_urb(ep->urbs[i].urb, umidi->chip->dev, 1178 usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
1133 pipe, buffer, ep->max_transfer, 1179 pipe, buffer, ep->max_transfer,
1134 snd_usbmidi_out_urb_complete, 1180 snd_usbmidi_out_urb_complete,
1135 &ep->urbs[i], ep_info->out_interval); 1181 &ep->urbs[i], ep_info->out_interval);
1136 else 1182 else
1137 usb_fill_bulk_urb(ep->urbs[i].urb, umidi->chip->dev, 1183 usb_fill_bulk_urb(ep->urbs[i].urb, umidi->dev,
1138 pipe, buffer, ep->max_transfer, 1184 pipe, buffer, ep->max_transfer,
1139 snd_usbmidi_out_urb_complete, 1185 snd_usbmidi_out_urb_complete,
1140 &ep->urbs[i]); 1186 &ep->urbs[i]);
@@ -1172,6 +1218,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi)
1172 if (ep->in) 1218 if (ep->in)
1173 snd_usbmidi_in_endpoint_delete(ep->in); 1219 snd_usbmidi_in_endpoint_delete(ep->in);
1174 } 1220 }
1221 mutex_destroy(&umidi->mutex);
1175 kfree(umidi); 1222 kfree(umidi);
1176} 1223}
1177 1224
@@ -1367,7 +1414,7 @@ static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
1367 int i; 1414 int i;
1368 1415
1369 for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) { 1416 for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) {
1370 if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id && 1417 if (snd_usbmidi_port_info[i].id == umidi->usb_id &&
1371 snd_usbmidi_port_info[i].port == number) 1418 snd_usbmidi_port_info[i].port == number)
1372 return &snd_usbmidi_port_info[i]; 1419 return &snd_usbmidi_port_info[i];
1373 } 1420 }
@@ -1405,7 +1452,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
1405 port_info = find_port_info(umidi, number); 1452 port_info = find_port_info(umidi, number);
1406 name_format = port_info ? port_info->name : "%s MIDI %d"; 1453 name_format = port_info ? port_info->name : "%s MIDI %d";
1407 snprintf(substream->name, sizeof(substream->name), 1454 snprintf(substream->name, sizeof(substream->name),
1408 name_format, umidi->chip->card->shortname, number + 1); 1455 name_format, umidi->card->shortname, number + 1);
1409 1456
1410 *rsubstream = substream; 1457 *rsubstream = substream;
1411} 1458}
@@ -1503,7 +1550,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
1503 endpoints[epidx].out_ep = usb_endpoint_num(ep); 1550 endpoints[epidx].out_ep = usb_endpoint_num(ep);
1504 if (usb_endpoint_xfer_int(ep)) 1551 if (usb_endpoint_xfer_int(ep))
1505 endpoints[epidx].out_interval = ep->bInterval; 1552 endpoints[epidx].out_interval = ep->bInterval;
1506 else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW) 1553 else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
1507 /* 1554 /*
1508 * Low speed bulk transfers don't exist, so 1555 * Low speed bulk transfers don't exist, so
1509 * force interrupt transfers for devices like 1556 * force interrupt transfers for devices like
@@ -1523,7 +1570,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
1523 endpoints[epidx].in_ep = usb_endpoint_num(ep); 1570 endpoints[epidx].in_ep = usb_endpoint_num(ep);
1524 if (usb_endpoint_xfer_int(ep)) 1571 if (usb_endpoint_xfer_int(ep))
1525 endpoints[epidx].in_interval = ep->bInterval; 1572 endpoints[epidx].in_interval = ep->bInterval;
1526 else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW) 1573 else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
1527 endpoints[epidx].in_interval = 1; 1574 endpoints[epidx].in_interval = 1;
1528 endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; 1575 endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
1529 snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", 1576 snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
@@ -1533,6 +1580,52 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
1533 return 0; 1580 return 0;
1534} 1581}
1535 1582
1583static int roland_load_info(struct snd_kcontrol *kcontrol,
1584 struct snd_ctl_elem_info *info)
1585{
1586 static const char *const names[] = { "High Load", "Light Load" };
1587
1588 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1589 info->count = 1;
1590 info->value.enumerated.items = 2;
1591 if (info->value.enumerated.item > 1)
1592 info->value.enumerated.item = 1;
1593 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
1594 return 0;
1595}
1596
1597static int roland_load_get(struct snd_kcontrol *kcontrol,
1598 struct snd_ctl_elem_value *value)
1599{
1600 value->value.enumerated.item[0] = kcontrol->private_value;
1601 return 0;
1602}
1603
1604static int roland_load_put(struct snd_kcontrol *kcontrol,
1605 struct snd_ctl_elem_value *value)
1606{
1607 struct snd_usb_midi* umidi = kcontrol->private_data;
1608 int changed;
1609
1610 if (value->value.enumerated.item[0] > 1)
1611 return -EINVAL;
1612 mutex_lock(&umidi->mutex);
1613 changed = value->value.enumerated.item[0] != kcontrol->private_value;
1614 if (changed)
1615 kcontrol->private_value = value->value.enumerated.item[0];
1616 mutex_unlock(&umidi->mutex);
1617 return changed;
1618}
1619
1620static struct snd_kcontrol_new roland_load_ctl = {
1621 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622 .name = "MIDI Input Mode",
1623 .info = roland_load_info,
1624 .get = roland_load_get,
1625 .put = roland_load_put,
1626 .private_value = 1,
1627};
1628
1536/* 1629/*
1537 * On Roland devices, use the second alternate setting to be able to use 1630 * On Roland devices, use the second alternate setting to be able to use
1538 * the interrupt input endpoint. 1631 * the interrupt input endpoint.
@@ -1556,8 +1649,12 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
1556 1649
1557 snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n", 1650 snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
1558 intfd->bAlternateSetting); 1651 intfd->bAlternateSetting);
1559 usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber, 1652 usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
1560 intfd->bAlternateSetting); 1653 intfd->bAlternateSetting);
1654
1655 umidi->roland_load_ctl = snd_ctl_new1(&roland_load_ctl, umidi);
1656 if (snd_ctl_add(umidi->card, umidi->roland_load_ctl) < 0)
1657 umidi->roland_load_ctl = NULL;
1561} 1658}
1562 1659
1563/* 1660/*
@@ -1573,7 +1670,7 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
1573 struct usb_endpoint_descriptor* epd; 1670 struct usb_endpoint_descriptor* epd;
1574 int i, out_eps = 0, in_eps = 0; 1671 int i, out_eps = 0, in_eps = 0;
1575 1672
1576 if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582) 1673 if (USB_ID_VENDOR(umidi->usb_id) == 0x0582)
1577 snd_usbmidi_switch_roland_altsetting(umidi); 1674 snd_usbmidi_switch_roland_altsetting(umidi);
1578 1675
1579 if (endpoint[0].out_ep || endpoint[0].in_ep) 1676 if (endpoint[0].out_ep || endpoint[0].in_ep)
@@ -1760,12 +1857,12 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
1760 struct snd_rawmidi *rmidi; 1857 struct snd_rawmidi *rmidi;
1761 int err; 1858 int err;
1762 1859
1763 err = snd_rawmidi_new(umidi->chip->card, "USB MIDI", 1860 err = snd_rawmidi_new(umidi->card, "USB MIDI",
1764 umidi->chip->next_midi_device++, 1861 umidi->next_midi_device++,
1765 out_ports, in_ports, &rmidi); 1862 out_ports, in_ports, &rmidi);
1766 if (err < 0) 1863 if (err < 0)
1767 return err; 1864 return err;
1768 strcpy(rmidi->name, umidi->chip->card->shortname); 1865 strcpy(rmidi->name, umidi->card->shortname);
1769 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | 1866 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
1770 SNDRV_RAWMIDI_INFO_INPUT | 1867 SNDRV_RAWMIDI_INFO_INPUT |
1771 SNDRV_RAWMIDI_INFO_DUPLEX; 1868 SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -1804,7 +1901,7 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
1804 return; 1901 return;
1805 for (i = 0; i < INPUT_URBS; ++i) { 1902 for (i = 0; i < INPUT_URBS; ++i) {
1806 struct urb* urb = ep->urbs[i]; 1903 struct urb* urb = ep->urbs[i];
1807 urb->dev = ep->umidi->chip->dev; 1904 urb->dev = ep->umidi->dev;
1808 snd_usbmidi_submit_urb(urb, GFP_KERNEL); 1905 snd_usbmidi_submit_urb(urb, GFP_KERNEL);
1809 } 1906 }
1810} 1907}
@@ -1825,9 +1922,10 @@ void snd_usbmidi_input_start(struct list_head* p)
1825/* 1922/*
1826 * Creates and registers everything needed for a MIDI streaming interface. 1923 * Creates and registers everything needed for a MIDI streaming interface.
1827 */ 1924 */
1828int snd_usb_create_midi_interface(struct snd_usb_audio* chip, 1925int snd_usbmidi_create(struct snd_card *card,
1829 struct usb_interface* iface, 1926 struct usb_interface* iface,
1830 const struct snd_usb_audio_quirk* quirk) 1927 struct list_head *midi_list,
1928 const struct snd_usb_audio_quirk* quirk)
1831{ 1929{
1832 struct snd_usb_midi* umidi; 1930 struct snd_usb_midi* umidi;
1833 struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; 1931 struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
@@ -1837,12 +1935,16 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
1837 umidi = kzalloc(sizeof(*umidi), GFP_KERNEL); 1935 umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
1838 if (!umidi) 1936 if (!umidi)
1839 return -ENOMEM; 1937 return -ENOMEM;
1840 umidi->chip = chip; 1938 umidi->dev = interface_to_usbdev(iface);
1939 umidi->card = card;
1841 umidi->iface = iface; 1940 umidi->iface = iface;
1842 umidi->quirk = quirk; 1941 umidi->quirk = quirk;
1843 umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; 1942 umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
1844 init_timer(&umidi->error_timer); 1943 init_timer(&umidi->error_timer);
1845 spin_lock_init(&umidi->disc_lock); 1944 spin_lock_init(&umidi->disc_lock);
1945 mutex_init(&umidi->mutex);
1946 umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
1947 le16_to_cpu(umidi->dev->descriptor.idProduct));
1846 umidi->error_timer.function = snd_usbmidi_error_timer; 1948 umidi->error_timer.function = snd_usbmidi_error_timer;
1847 umidi->error_timer.data = (unsigned long)umidi; 1949 umidi->error_timer.data = (unsigned long)umidi;
1848 1950
@@ -1851,7 +1953,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
1851 switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) { 1953 switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) {
1852 case QUIRK_MIDI_STANDARD_INTERFACE: 1954 case QUIRK_MIDI_STANDARD_INTERFACE:
1853 err = snd_usbmidi_get_ms_info(umidi, endpoints); 1955 err = snd_usbmidi_get_ms_info(umidi, endpoints);
1854 if (chip->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */ 1956 if (umidi->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */
1855 umidi->usb_protocol_ops = 1957 umidi->usb_protocol_ops =
1856 &snd_usbmidi_maudio_broken_running_status_ops; 1958 &snd_usbmidi_maudio_broken_running_status_ops;
1857 break; 1959 break;
@@ -1887,7 +1989,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
1887 * interface 0, so we have to make sure that the USB core looks 1989 * interface 0, so we have to make sure that the USB core looks
1888 * again at interface 0 by calling usb_set_interface() on it. 1990 * again at interface 0 by calling usb_set_interface() on it.
1889 */ 1991 */
1890 usb_set_interface(umidi->chip->dev, 0, 0); 1992 usb_set_interface(umidi->dev, 0, 0);
1891 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 1993 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
1892 break; 1994 break;
1893 case QUIRK_MIDI_EMAGIC: 1995 case QUIRK_MIDI_EMAGIC:
@@ -1914,8 +2016,8 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
1914 out_ports = 0; 2016 out_ports = 0;
1915 in_ports = 0; 2017 in_ports = 0;
1916 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { 2018 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
1917 out_ports += snd_usbmidi_count_bits(endpoints[i].out_cables); 2019 out_ports += hweight16(endpoints[i].out_cables);
1918 in_ports += snd_usbmidi_count_bits(endpoints[i].in_cables); 2020 in_ports += hweight16(endpoints[i].in_cables);
1919 } 2021 }
1920 err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports); 2022 err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
1921 if (err < 0) { 2023 if (err < 0) {
@@ -1933,14 +2035,14 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
1933 return err; 2035 return err;
1934 } 2036 }
1935 2037
1936 list_add(&umidi->list, &umidi->chip->midi_list); 2038 list_add_tail(&umidi->list, midi_list);
1937 2039
1938 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) 2040 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
1939 snd_usbmidi_input_start_ep(umidi->endpoints[i].in); 2041 snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
1940 return 0; 2042 return 0;
1941} 2043}
1942 2044
1943EXPORT_SYMBOL(snd_usb_create_midi_interface); 2045EXPORT_SYMBOL(snd_usbmidi_create);
1944EXPORT_SYMBOL(snd_usbmidi_input_stop); 2046EXPORT_SYMBOL(snd_usbmidi_input_stop);
1945EXPORT_SYMBOL(snd_usbmidi_input_start); 2047EXPORT_SYMBOL(snd_usbmidi_input_start);
1946EXPORT_SYMBOL(snd_usbmidi_disconnect); 2048EXPORT_SYMBOL(snd_usbmidi_disconnect);
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index 3e5d66cf1f5a..77c35885e21c 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -277,6 +277,22 @@ static struct usbmix_name_map scratch_live_map[] = {
277 { 0 } /* terminator */ 277 { 0 } /* terminator */
278}; 278};
279 279
280/* "Gamesurround Muse Pocket LT" looks same like "Sound Blaster MP3+"
281 * most importand difference is SU[8], it should be set to "Capture Source"
282 * to make alsamixer and PA working properly.
283 * FIXME: or mp3plus_map should use "Capture Source" too,
284 * so this maps can be merget
285 */
286static struct usbmix_name_map hercules_usb51_map[] = {
287 { 8, "Capture Source" }, /* SU, default "PCM Capture Source" */
288 { 9, "Master Playback" }, /* FU, default "Speaker Playback" */
289 { 10, "Mic Boost", 7 }, /* FU, default "Auto Gain Input" */
290 { 11, "Line Capture" }, /* FU, default "PCM Capture" */
291 { 13, "Mic Bypass Playback" }, /* FU, default "Mic Playback" */
292 { 14, "Line Bypass Playback" }, /* FU, default "Line Playback" */
293 { 0 } /* terminator */
294};
295
280/* 296/*
281 * Control map entries 297 * Control map entries
282 */ 298 */
@@ -316,6 +332,13 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
316 .ignore_ctl_error = 1, 332 .ignore_ctl_error = 1,
317 }, 333 },
318 { 334 {
335 /* Hercules Gamesurround Muse Pocket LT
336 * (USB 5.1 Channel Audio Adapter)
337 */
338 .id = USB_ID(0x06f8, 0xc000),
339 .map = hercules_usb51_map,
340 },
341 {
319 .id = USB_ID(0x08bb, 0x2702), 342 .id = USB_ID(0x08bb, 0x2702),
320 .map = linex_map, 343 .map = linex_map,
321 .ignore_ctl_error = 1, 344 .ignore_ctl_error = 1,
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index f6f201eb24ce..a892bda03df9 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1563,6 +1563,29 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1563 } 1563 }
1564 } 1564 }
1565}, 1565},
1566{
1567 /* has ID 0x00ea when not in Advanced Driver mode */
1568 USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e9),
1569 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1570 /* .vendor_name = "Roland", */
1571 /* .product_name = "UA-1G", */
1572 .ifnum = QUIRK_ANY_INTERFACE,
1573 .type = QUIRK_COMPOSITE,
1574 .data = (const struct snd_usb_audio_quirk[]) {
1575 {
1576 .ifnum = 0,
1577 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1578 },
1579 {
1580 .ifnum = 1,
1581 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1582 },
1583 {
1584 .ifnum = -1
1585 }
1586 }
1587 }
1588},
1566 1589
1567/* Guillemot devices */ 1590/* Guillemot devices */
1568{ 1591{
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 99f33766cd51..f71cd28eca6b 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -59,11 +59,33 @@ static int us122l_create_usbmidi(struct snd_card *card)
59 .type = QUIRK_MIDI_US122L, 59 .type = QUIRK_MIDI_US122L,
60 .data = &quirk_data 60 .data = &quirk_data
61 }; 61 };
62 struct usb_device *dev = US122L(card)->chip.dev; 62 struct usb_device *dev = US122L(card)->dev;
63 struct usb_interface *iface = usb_ifnum_to_if(dev, 1); 63 struct usb_interface *iface = usb_ifnum_to_if(dev, 1);
64 64
65 return snd_usb_create_midi_interface(&US122L(card)->chip, 65 return snd_usbmidi_create(card, iface,
66 iface, &quirk); 66 &US122L(card)->midi_list, &quirk);
67}
68
69static int us144_create_usbmidi(struct snd_card *card)
70{
71 static struct snd_usb_midi_endpoint_info quirk_data = {
72 .out_ep = 4,
73 .in_ep = 3,
74 .out_cables = 0x001,
75 .in_cables = 0x001
76 };
77 static struct snd_usb_audio_quirk quirk = {
78 .vendor_name = "US144",
79 .product_name = NAME_ALLCAPS,
80 .ifnum = 0,
81 .type = QUIRK_MIDI_US122L,
82 .data = &quirk_data
83 };
84 struct usb_device *dev = US122L(card)->dev;
85 struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
86
87 return snd_usbmidi_create(card, iface,
88 &US122L(card)->midi_list, &quirk);
67} 89}
68 90
69/* 91/*
@@ -171,7 +193,12 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
171 193
172 if (!us122l->first) 194 if (!us122l->first)
173 us122l->first = file; 195 us122l->first = file;
174 iface = usb_ifnum_to_if(us122l->chip.dev, 1); 196
197 if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
198 iface = usb_ifnum_to_if(us122l->dev, 0);
199 usb_autopm_get_interface(iface);
200 }
201 iface = usb_ifnum_to_if(us122l->dev, 1);
175 usb_autopm_get_interface(iface); 202 usb_autopm_get_interface(iface);
176 return 0; 203 return 0;
177} 204}
@@ -179,8 +206,14 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
179static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) 206static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
180{ 207{
181 struct us122l *us122l = hw->private_data; 208 struct us122l *us122l = hw->private_data;
182 struct usb_interface *iface = usb_ifnum_to_if(us122l->chip.dev, 1); 209 struct usb_interface *iface;
183 snd_printdd(KERN_DEBUG "%p %p\n", hw, file); 210 snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
211
212 if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
213 iface = usb_ifnum_to_if(us122l->dev, 0);
214 usb_autopm_put_interface(iface);
215 }
216 iface = usb_ifnum_to_if(us122l->dev, 1);
184 usb_autopm_put_interface(iface); 217 usb_autopm_put_interface(iface);
185 if (us122l->first == file) 218 if (us122l->first == file)
186 us122l->first = NULL; 219 us122l->first = NULL;
@@ -264,7 +297,7 @@ static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw,
264static void us122l_stop(struct us122l *us122l) 297static void us122l_stop(struct us122l *us122l)
265{ 298{
266 struct list_head *p; 299 struct list_head *p;
267 list_for_each(p, &us122l->chip.midi_list) 300 list_for_each(p, &us122l->midi_list)
268 snd_usbmidi_input_stop(p); 301 snd_usbmidi_input_stop(p);
269 302
270 usb_stream_stop(&us122l->sk); 303 usb_stream_stop(&us122l->sk);
@@ -297,7 +330,7 @@ static bool us122l_start(struct us122l *us122l,
297 unsigned use_packsize = 0; 330 unsigned use_packsize = 0;
298 bool success = false; 331 bool success = false;
299 332
300 if (us122l->chip.dev->speed == USB_SPEED_HIGH) { 333 if (us122l->dev->speed == USB_SPEED_HIGH) {
301 /* The us-122l's descriptor defaults to iso max_packsize 78, 334 /* The us-122l's descriptor defaults to iso max_packsize 78,
302 which isn't needed for samplerates <= 48000. 335 which isn't needed for samplerates <= 48000.
303 Lets save some memory: 336 Lets save some memory:
@@ -314,11 +347,11 @@ static bool us122l_start(struct us122l *us122l,
314 break; 347 break;
315 } 348 }
316 } 349 }
317 if (!usb_stream_new(&us122l->sk, us122l->chip.dev, 1, 2, 350 if (!usb_stream_new(&us122l->sk, us122l->dev, 1, 2,
318 rate, use_packsize, period_frames, 6)) 351 rate, use_packsize, period_frames, 6))
319 goto out; 352 goto out;
320 353
321 err = us122l_set_sample_rate(us122l->chip.dev, rate); 354 err = us122l_set_sample_rate(us122l->dev, rate);
322 if (err < 0) { 355 if (err < 0) {
323 us122l_stop(us122l); 356 us122l_stop(us122l);
324 snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); 357 snd_printk(KERN_ERR "us122l_set_sample_rate error \n");
@@ -330,7 +363,7 @@ static bool us122l_start(struct us122l *us122l,
330 snd_printk(KERN_ERR "us122l_start error %i \n", err); 363 snd_printk(KERN_ERR "us122l_start error %i \n", err);
331 goto out; 364 goto out;
332 } 365 }
333 list_for_each(p, &us122l->chip.midi_list) 366 list_for_each(p, &us122l->midi_list)
334 snd_usbmidi_input_start(p); 367 snd_usbmidi_input_start(p);
335 success = true; 368 success = true;
336out: 369out:
@@ -357,7 +390,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
357 err = -ENXIO; 390 err = -ENXIO;
358 goto free; 391 goto free;
359 } 392 }
360 high_speed = us122l->chip.dev->speed == USB_SPEED_HIGH; 393 high_speed = us122l->dev->speed == USB_SPEED_HIGH;
361 if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000 && 394 if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000 &&
362 (!high_speed || 395 (!high_speed ||
363 (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) || 396 (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) ||
@@ -417,7 +450,7 @@ static int usb_stream_hwdep_new(struct snd_card *card)
417{ 450{
418 int err; 451 int err;
419 struct snd_hwdep *hw; 452 struct snd_hwdep *hw;
420 struct usb_device *dev = US122L(card)->chip.dev; 453 struct usb_device *dev = US122L(card)->dev;
421 454
422 err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw); 455 err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw);
423 if (err < 0) 456 if (err < 0)
@@ -443,19 +476,29 @@ static bool us122l_create_card(struct snd_card *card)
443 int err; 476 int err;
444 struct us122l *us122l = US122L(card); 477 struct us122l *us122l = US122L(card);
445 478
446 err = usb_set_interface(us122l->chip.dev, 1, 1); 479 if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
480 err = usb_set_interface(us122l->dev, 0, 1);
481 if (err) {
482 snd_printk(KERN_ERR "usb_set_interface error \n");
483 return false;
484 }
485 }
486 err = usb_set_interface(us122l->dev, 1, 1);
447 if (err) { 487 if (err) {
448 snd_printk(KERN_ERR "usb_set_interface error \n"); 488 snd_printk(KERN_ERR "usb_set_interface error \n");
449 return false; 489 return false;
450 } 490 }
451 491
452 pt_info_set(us122l->chip.dev, 0x11); 492 pt_info_set(us122l->dev, 0x11);
453 pt_info_set(us122l->chip.dev, 0x10); 493 pt_info_set(us122l->dev, 0x10);
454 494
455 if (!us122l_start(us122l, 44100, 256)) 495 if (!us122l_start(us122l, 44100, 256))
456 return false; 496 return false;
457 497
458 err = us122l_create_usbmidi(card); 498 if (us122l->dev->descriptor.idProduct == USB_ID_US144)
499 err = us144_create_usbmidi(card);
500 else
501 err = us122l_create_usbmidi(card);
459 if (err < 0) { 502 if (err < 0) {
460 snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); 503 snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err);
461 us122l_stop(us122l); 504 us122l_stop(us122l);
@@ -465,7 +508,7 @@ static bool us122l_create_card(struct snd_card *card)
465 if (err < 0) { 508 if (err < 0) {
466/* release the midi resources */ 509/* release the midi resources */
467 struct list_head *p; 510 struct list_head *p;
468 list_for_each(p, &us122l->chip.midi_list) 511 list_for_each(p, &us122l->midi_list)
469 snd_usbmidi_disconnect(p); 512 snd_usbmidi_disconnect(p);
470 513
471 us122l_stop(us122l); 514 us122l_stop(us122l);
@@ -477,7 +520,7 @@ static bool us122l_create_card(struct snd_card *card)
477static void snd_us122l_free(struct snd_card *card) 520static void snd_us122l_free(struct snd_card *card)
478{ 521{
479 struct us122l *us122l = US122L(card); 522 struct us122l *us122l = US122L(card);
480 int index = us122l->chip.index; 523 int index = us122l->card_index;
481 if (index >= 0 && index < SNDRV_CARDS) 524 if (index >= 0 && index < SNDRV_CARDS)
482 snd_us122l_card_used[index] = 0; 525 snd_us122l_card_used[index] = 0;
483} 526}
@@ -497,13 +540,12 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
497 sizeof(struct us122l), &card); 540 sizeof(struct us122l), &card);
498 if (err < 0) 541 if (err < 0)
499 return err; 542 return err;
500 snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; 543 snd_us122l_card_used[US122L(card)->card_index = dev] = 1;
501 card->private_free = snd_us122l_free; 544 card->private_free = snd_us122l_free;
502 US122L(card)->chip.dev = device; 545 US122L(card)->dev = device;
503 US122L(card)->chip.card = card;
504 mutex_init(&US122L(card)->mutex); 546 mutex_init(&US122L(card)->mutex);
505 init_waitqueue_head(&US122L(card)->sk.sleep); 547 init_waitqueue_head(&US122L(card)->sk.sleep);
506 INIT_LIST_HEAD(&US122L(card)->chip.midi_list); 548 INIT_LIST_HEAD(&US122L(card)->midi_list);
507 strcpy(card->driver, "USB "NAME_ALLCAPS""); 549 strcpy(card->driver, "USB "NAME_ALLCAPS"");
508 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); 550 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
509 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", 551 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
@@ -511,8 +553,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
511 le16_to_cpu(device->descriptor.idVendor), 553 le16_to_cpu(device->descriptor.idVendor),
512 le16_to_cpu(device->descriptor.idProduct), 554 le16_to_cpu(device->descriptor.idProduct),
513 0, 555 0,
514 US122L(card)->chip.dev->bus->busnum, 556 US122L(card)->dev->bus->busnum,
515 US122L(card)->chip.dev->devnum 557 US122L(card)->dev->devnum
516 ); 558 );
517 *cardp = card; 559 *cardp = card;
518 return 0; 560 return 0;
@@ -542,6 +584,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
542 return err; 584 return err;
543 } 585 }
544 586
587 usb_get_intf(usb_ifnum_to_if(device, 0));
545 usb_get_dev(device); 588 usb_get_dev(device);
546 *cardp = card; 589 *cardp = card;
547 return 0; 590 return 0;
@@ -550,9 +593,16 @@ static int us122l_usb_probe(struct usb_interface *intf,
550static int snd_us122l_probe(struct usb_interface *intf, 593static int snd_us122l_probe(struct usb_interface *intf,
551 const struct usb_device_id *id) 594 const struct usb_device_id *id)
552{ 595{
596 struct usb_device *device = interface_to_usbdev(intf);
553 struct snd_card *card; 597 struct snd_card *card;
554 int err; 598 int err;
555 599
600 if (device->descriptor.idProduct == USB_ID_US144
601 && device->speed == USB_SPEED_HIGH) {
602 snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
603 return -ENODEV;
604 }
605
556 snd_printdd(KERN_DEBUG"%p:%i\n", 606 snd_printdd(KERN_DEBUG"%p:%i\n",
557 intf, intf->cur_altsetting->desc.bInterfaceNumber); 607 intf, intf->cur_altsetting->desc.bInterfaceNumber);
558 if (intf->cur_altsetting->desc.bInterfaceNumber != 1) 608 if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
@@ -584,15 +634,15 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
584 mutex_lock(&us122l->mutex); 634 mutex_lock(&us122l->mutex);
585 us122l_stop(us122l); 635 us122l_stop(us122l);
586 mutex_unlock(&us122l->mutex); 636 mutex_unlock(&us122l->mutex);
587 us122l->chip.shutdown = 1;
588 637
589/* release the midi resources */ 638/* release the midi resources */
590 list_for_each(p, &us122l->chip.midi_list) { 639 list_for_each(p, &us122l->midi_list) {
591 snd_usbmidi_disconnect(p); 640 snd_usbmidi_disconnect(p);
592 } 641 }
593 642
594 usb_put_intf(intf); 643 usb_put_intf(usb_ifnum_to_if(us122l->dev, 0));
595 usb_put_dev(us122l->chip.dev); 644 usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
645 usb_put_dev(us122l->dev);
596 646
597 while (atomic_read(&us122l->mmap_count)) 647 while (atomic_read(&us122l->mmap_count))
598 msleep(500); 648 msleep(500);
@@ -615,7 +665,7 @@ static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
615 if (!us122l) 665 if (!us122l)
616 return 0; 666 return 0;
617 667
618 list_for_each(p, &us122l->chip.midi_list) 668 list_for_each(p, &us122l->midi_list)
619 snd_usbmidi_input_stop(p); 669 snd_usbmidi_input_stop(p);
620 670
621 mutex_lock(&us122l->mutex); 671 mutex_lock(&us122l->mutex);
@@ -642,16 +692,23 @@ static int snd_us122l_resume(struct usb_interface *intf)
642 692
643 mutex_lock(&us122l->mutex); 693 mutex_lock(&us122l->mutex);
644 /* needed, doesn't restart without: */ 694 /* needed, doesn't restart without: */
645 err = usb_set_interface(us122l->chip.dev, 1, 1); 695 if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
696 err = usb_set_interface(us122l->dev, 0, 1);
697 if (err) {
698 snd_printk(KERN_ERR "usb_set_interface error \n");
699 goto unlock;
700 }
701 }
702 err = usb_set_interface(us122l->dev, 1, 1);
646 if (err) { 703 if (err) {
647 snd_printk(KERN_ERR "usb_set_interface error \n"); 704 snd_printk(KERN_ERR "usb_set_interface error \n");
648 goto unlock; 705 goto unlock;
649 } 706 }
650 707
651 pt_info_set(us122l->chip.dev, 0x11); 708 pt_info_set(us122l->dev, 0x11);
652 pt_info_set(us122l->chip.dev, 0x10); 709 pt_info_set(us122l->dev, 0x10);
653 710
654 err = us122l_set_sample_rate(us122l->chip.dev, 711 err = us122l_set_sample_rate(us122l->dev,
655 us122l->sk.s->cfg.sample_rate); 712 us122l->sk.s->cfg.sample_rate);
656 if (err < 0) { 713 if (err < 0) {
657 snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); 714 snd_printk(KERN_ERR "us122l_set_sample_rate error \n");
@@ -661,7 +718,7 @@ static int snd_us122l_resume(struct usb_interface *intf)
661 if (err) 718 if (err)
662 goto unlock; 719 goto unlock;
663 720
664 list_for_each(p, &us122l->chip.midi_list) 721 list_for_each(p, &us122l->midi_list)
665 snd_usbmidi_input_start(p); 722 snd_usbmidi_input_start(p);
666unlock: 723unlock:
667 mutex_unlock(&us122l->mutex); 724 mutex_unlock(&us122l->mutex);
@@ -675,11 +732,11 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
675 .idVendor = 0x0644, 732 .idVendor = 0x0644,
676 .idProduct = USB_ID_US122L 733 .idProduct = USB_ID_US122L
677 }, 734 },
678/* { */ /* US-144 maybe works when @USB1.1. Untested. */ 735 { /* US-144 only works at USB1.1! Disable module ehci-hcd. */
679/* .match_flags = USB_DEVICE_ID_MATCH_DEVICE, */ 736 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
680/* .idVendor = 0x0644, */ 737 .idVendor = 0x0644,
681/* .idProduct = USB_ID_US144 */ 738 .idProduct = USB_ID_US144
682/* }, */ 739 },
683 { /* terminator */ } 740 { /* terminator */ }
684}; 741};
685 742
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index 3d10c4b2a0f5..4daf1982e821 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -3,7 +3,8 @@
3 3
4 4
5struct us122l { 5struct us122l {
6 struct snd_usb_audio chip; 6 struct usb_device *dev;
7 int card_index;
7 int stride; 8 int stride;
8 struct usb_stream_kernel sk; 9 struct usb_stream_kernel sk;
9 10
@@ -12,6 +13,7 @@ struct us122l {
12 unsigned second_periods_polled; 13 unsigned second_periods_polled;
13 struct file *master; 14 struct file *master;
14 struct file *slave; 15 struct file *slave;
16 struct list_head midi_list;
15 17
16 atomic_t mmap_count; 18 atomic_t mmap_count;
17}; 19};
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 52e04b2f35d3..1879b72c40f8 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -114,7 +114,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
114 struct usX2Ydev *us428 = hw->private_data; 114 struct usX2Ydev *us428 = hw->private_data;
115 int id = -1; 115 int id = -1;
116 116
117 switch (le16_to_cpu(us428->chip.dev->descriptor.idProduct)) { 117 switch (le16_to_cpu(us428->dev->descriptor.idProduct)) {
118 case USB_ID_US122: 118 case USB_ID_US122:
119 id = USX2Y_TYPE_122; 119 id = USX2Y_TYPE_122;
120 break; 120 break;
@@ -164,14 +164,14 @@ static int usX2Y_create_usbmidi(struct snd_card *card)
164 .type = QUIRK_MIDI_FIXED_ENDPOINT, 164 .type = QUIRK_MIDI_FIXED_ENDPOINT,
165 .data = &quirk_data_2 165 .data = &quirk_data_2
166 }; 166 };
167 struct usb_device *dev = usX2Y(card)->chip.dev; 167 struct usb_device *dev = usX2Y(card)->dev;
168 struct usb_interface *iface = usb_ifnum_to_if(dev, 0); 168 struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
169 struct snd_usb_audio_quirk *quirk = 169 struct snd_usb_audio_quirk *quirk =
170 le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? 170 le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ?
171 &quirk_2 : &quirk_1; 171 &quirk_2 : &quirk_1;
172 172
173 snd_printdd("usX2Y_create_usbmidi \n"); 173 snd_printdd("usX2Y_create_usbmidi \n");
174 return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk); 174 return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk);
175} 175}
176 176
177static int usX2Y_create_alsa_devices(struct snd_card *card) 177static int usX2Y_create_alsa_devices(struct snd_card *card)
@@ -202,7 +202,7 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw,
202 snd_printdd( "dsp_load %s\n", dsp->name); 202 snd_printdd( "dsp_load %s\n", dsp->name);
203 203
204 if (access_ok(VERIFY_READ, dsp->image, dsp->length)) { 204 if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
205 struct usb_device* dev = priv->chip.dev; 205 struct usb_device* dev = priv->dev;
206 char *buf; 206 char *buf;
207 207
208 buf = memdup_user(dsp->image, dsp->length); 208 buf = memdup_user(dsp->image, dsp->length);
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cb4bb8373ca2..c42350eed2eb 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -239,8 +239,8 @@ static void i_usX2Y_In04Int(struct urb *urb)
239 for (j = 0; j < URBS_AsyncSeq && !err; ++j) 239 for (j = 0; j < URBS_AsyncSeq && !err; ++j)
240 if (0 == usX2Y->AS04.urb[j]->status) { 240 if (0 == usX2Y->AS04.urb[j]->status) {
241 struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. 241 struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost.
242 usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev, 242 usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev,
243 usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, 243 usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol,
244 p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, 244 p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5,
245 i_usX2Y_Out04Int, usX2Y); 245 i_usX2Y_Out04Int, usX2Y);
246 err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC); 246 err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
@@ -253,7 +253,7 @@ static void i_usX2Y_In04Int(struct urb *urb)
253 if (err) 253 if (err)
254 snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); 254 snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err);
255 255
256 urb->dev = usX2Y->chip.dev; 256 urb->dev = usX2Y->dev;
257 usb_submit_urb(urb, GFP_ATOMIC); 257 usb_submit_urb(urb, GFP_ATOMIC);
258} 258}
259 259
@@ -273,8 +273,8 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
273 err = -ENOMEM; 273 err = -ENOMEM;
274 break; 274 break;
275 } 275 }
276 usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->chip.dev, 276 usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->dev,
277 usb_sndbulkpipe(usX2Y->chip.dev, 0x04), 277 usb_sndbulkpipe(usX2Y->dev, 0x04),
278 usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0, 278 usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
279 i_usX2Y_Out04Int, usX2Y 279 i_usX2Y_Out04Int, usX2Y
280 ); 280 );
@@ -293,7 +293,7 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
293 } 293 }
294 294
295 init_waitqueue_head(&usX2Y->In04WaitQueue); 295 init_waitqueue_head(&usX2Y->In04WaitQueue);
296 usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4), 296 usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4),
297 usX2Y->In04Buf, 21, 297 usX2Y->In04Buf, 21,
298 i_usX2Y_In04Int, usX2Y, 298 i_usX2Y_In04Int, usX2Y,
299 10); 299 10);
@@ -348,13 +348,12 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
348 sizeof(struct usX2Ydev), &card); 348 sizeof(struct usX2Ydev), &card);
349 if (err < 0) 349 if (err < 0)
350 return err; 350 return err;
351 snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; 351 snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1;
352 card->private_free = snd_usX2Y_card_private_free; 352 card->private_free = snd_usX2Y_card_private_free;
353 usX2Y(card)->chip.dev = device; 353 usX2Y(card)->dev = device;
354 usX2Y(card)->chip.card = card;
355 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); 354 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
356 mutex_init(&usX2Y(card)->prepare_mutex); 355 mutex_init(&usX2Y(card)->prepare_mutex);
357 INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list); 356 INIT_LIST_HEAD(&usX2Y(card)->midi_list);
358 strcpy(card->driver, "USB "NAME_ALLCAPS""); 357 strcpy(card->driver, "USB "NAME_ALLCAPS"");
359 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); 358 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
360 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", 359 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
@@ -362,7 +361,7 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
362 le16_to_cpu(device->descriptor.idVendor), 361 le16_to_cpu(device->descriptor.idVendor),
363 le16_to_cpu(device->descriptor.idProduct), 362 le16_to_cpu(device->descriptor.idProduct),
364 0,//us428(card)->usbmidi.ifnum, 363 0,//us428(card)->usbmidi.ifnum,
365 usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum 364 usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum
366 ); 365 );
367 *cardp = card; 366 *cardp = card;
368 return 0; 367 return 0;
@@ -432,8 +431,8 @@ static void snd_usX2Y_card_private_free(struct snd_card *card)
432 usb_free_urb(usX2Y(card)->In04urb); 431 usb_free_urb(usX2Y(card)->In04urb);
433 if (usX2Y(card)->us428ctls_sharedmem) 432 if (usX2Y(card)->us428ctls_sharedmem)
434 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem)); 433 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
435 if (usX2Y(card)->chip.index >= 0 && usX2Y(card)->chip.index < SNDRV_CARDS) 434 if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS)
436 snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0; 435 snd_usX2Y_card_used[usX2Y(card)->card_index] = 0;
437} 436}
438 437
439/* 438/*
@@ -445,13 +444,12 @@ static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
445 struct snd_card *card = ptr; 444 struct snd_card *card = ptr;
446 struct usX2Ydev *usX2Y = usX2Y(card); 445 struct usX2Ydev *usX2Y = usX2Y(card);
447 struct list_head *p; 446 struct list_head *p;
448 usX2Y->chip.shutdown = 1;
449 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; 447 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
450 usX2Y_unlinkSeq(&usX2Y->AS04); 448 usX2Y_unlinkSeq(&usX2Y->AS04);
451 usb_kill_urb(usX2Y->In04urb); 449 usb_kill_urb(usX2Y->In04urb);
452 snd_card_disconnect(card); 450 snd_card_disconnect(card);
453 /* release the midi resources */ 451 /* release the midi resources */
454 list_for_each(p, &usX2Y->chip.midi_list) { 452 list_for_each(p, &usX2Y->midi_list) {
455 snd_usbmidi_disconnect(p); 453 snd_usbmidi_disconnect(p);
456 } 454 }
457 if (usX2Y->us428ctls_sharedmem) 455 if (usX2Y->us428ctls_sharedmem)
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
index 456b5fdbc339..1d174cea352b 100644
--- a/sound/usb/usx2y/usbusx2y.h
+++ b/sound/usb/usx2y/usbusx2y.h
@@ -22,7 +22,8 @@ struct snd_usX2Y_urbSeq {
22#include "usx2yhwdeppcm.h" 22#include "usx2yhwdeppcm.h"
23 23
24struct usX2Ydev { 24struct usX2Ydev {
25 struct snd_usb_audio chip; 25 struct usb_device *dev;
26 int card_index;
26 int stride; 27 int stride;
27 struct urb *In04urb; 28 struct urb *In04urb;
28 void *In04Buf; 29 void *In04Buf;
@@ -42,6 +43,9 @@ struct usX2Ydev {
42 struct snd_usX2Y_substream *subs[4]; 43 struct snd_usX2Y_substream *subs[4];
43 struct snd_usX2Y_substream * volatile prepare_subs; 44 struct snd_usX2Y_substream * volatile prepare_subs;
44 wait_queue_head_t prepare_wait_queue; 45 wait_queue_head_t prepare_wait_queue;
46 struct list_head midi_list;
47 struct list_head pcm_list;
48 int pcm_devs;
45}; 49};
46 50
47 51
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 9efd27f6b52f..74a67a85aa81 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -199,7 +199,7 @@ static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, i
199 return -ENODEV; 199 return -ENODEV;
200 urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks 200 urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks
201 urb->hcpriv = NULL; 201 urb->hcpriv = NULL;
202 urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */ 202 urb->dev = subs->usX2Y->dev; /* we need to set this at each time */
203 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { 203 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
204 snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); 204 snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err);
205 return err; 205 return err;
@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
300"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" 300"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
301"Most propably some urb of usb-frame %i is still missing.\n" 301"Most propably some urb of usb-frame %i is still missing.\n"
302"Cause could be too long delays in usb-hcd interrupt handling.\n", 302"Cause could be too long delays in usb-hcd interrupt handling.\n",
303 usb_get_current_frame_number(usX2Y->chip.dev), 303 usb_get_current_frame_number(usX2Y->dev),
304 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", 304 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
305 usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); 305 usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
306 usX2Y_clients_stop(usX2Y); 306 usX2Y_clients_stop(usX2Y);
@@ -313,7 +313,7 @@ static void i_usX2Y_urb_complete(struct urb *urb)
313 313
314 if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { 314 if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
315 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", 315 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
316 usb_get_current_frame_number(usX2Y->chip.dev), 316 usb_get_current_frame_number(usX2Y->dev),
317 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", 317 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
318 urb->status, urb->start_frame); 318 urb->status, urb->start_frame);
319 return; 319 return;
@@ -424,7 +424,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs)
424 int i; 424 int i;
425 unsigned int pipe; 425 unsigned int pipe;
426 int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; 426 int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
427 struct usb_device *dev = subs->usX2Y->chip.dev; 427 struct usb_device *dev = subs->usX2Y->dev;
428 428
429 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : 429 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
430 usb_rcvisocpipe(dev, subs->endpoint); 430 usb_rcvisocpipe(dev, subs->endpoint);
@@ -500,7 +500,7 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
500 unsigned long pack; 500 unsigned long pack;
501 if (0 == i) 501 if (0 == i)
502 atomic_set(&subs->state, state_STARTING3); 502 atomic_set(&subs->state, state_STARTING3);
503 urb->dev = usX2Y->chip.dev; 503 urb->dev = usX2Y->dev;
504 urb->transfer_flags = URB_ISO_ASAP; 504 urb->transfer_flags = URB_ISO_ASAP;
505 for (pack = 0; pack < nr_of_packs(); pack++) { 505 for (pack = 0; pack < nr_of_packs(); pack++) {
506 urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack; 506 urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
@@ -692,7 +692,7 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
692 } 692 }
693 ((char*)(usbdata + i))[0] = ra[i].c1; 693 ((char*)(usbdata + i))[0] = ra[i].c1;
694 ((char*)(usbdata + i))[1] = ra[i].c2; 694 ((char*)(usbdata + i))[1] = ra[i].c2;
695 usb_fill_bulk_urb(us->urb[i], usX2Y->chip.dev, usb_sndbulkpipe(usX2Y->chip.dev, 4), 695 usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4),
696 usbdata + i, 2, i_usX2Y_04Int, usX2Y); 696 usbdata + i, 2, i_usX2Y_04Int, usX2Y);
697#ifdef OLD_USB 697#ifdef OLD_USB
698 us->urb[i]->transfer_flags = USB_QUEUE_BULK; 698 us->urb[i]->transfer_flags = USB_QUEUE_BULK;
@@ -740,17 +740,17 @@ static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format)
740 alternate = 1; 740 alternate = 1;
741 usX2Y->stride = 4; 741 usX2Y->stride = 4;
742 } 742 }
743 list_for_each(p, &usX2Y->chip.midi_list) { 743 list_for_each(p, &usX2Y->midi_list) {
744 snd_usbmidi_input_stop(p); 744 snd_usbmidi_input_stop(p);
745 } 745 }
746 usb_kill_urb(usX2Y->In04urb); 746 usb_kill_urb(usX2Y->In04urb);
747 if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) { 747 if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) {
748 snd_printk(KERN_ERR "usb_set_interface error \n"); 748 snd_printk(KERN_ERR "usb_set_interface error \n");
749 return err; 749 return err;
750 } 750 }
751 usX2Y->In04urb->dev = usX2Y->chip.dev; 751 usX2Y->In04urb->dev = usX2Y->dev;
752 err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); 752 err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
753 list_for_each(p, &usX2Y->chip.midi_list) { 753 list_for_each(p, &usX2Y->midi_list) {
754 snd_usbmidi_input_start(p); 754 snd_usbmidi_input_start(p);
755 } 755 }
756 usX2Y->format = format; 756 usX2Y->format = format;
@@ -955,7 +955,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
955 struct snd_pcm *pcm; 955 struct snd_pcm *pcm;
956 int err, i; 956 int err, i;
957 struct snd_usX2Y_substream **usX2Y_substream = 957 struct snd_usX2Y_substream **usX2Y_substream =
958 usX2Y(card)->subs + 2 * usX2Y(card)->chip.pcm_devs; 958 usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs;
959 959
960 for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; 960 for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
961 i <= SNDRV_PCM_STREAM_CAPTURE; ++i) { 961 i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
@@ -971,7 +971,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
971 usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; 971 usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
972 usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; 972 usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
973 973
974 err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->chip.pcm_devs, 974 err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs,
975 playback_endpoint ? 1 : 0, 1, 975 playback_endpoint ? 1 : 0, 1,
976 &pcm); 976 &pcm);
977 if (err < 0) { 977 if (err < 0) {
@@ -987,7 +987,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
987 pcm->private_free = snd_usX2Y_pcm_private_free; 987 pcm->private_free = snd_usX2Y_pcm_private_free;
988 pcm->info_flags = 0; 988 pcm->info_flags = 0;
989 989
990 sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->chip.pcm_devs); 990 sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs);
991 991
992 if ((playback_endpoint && 992 if ((playback_endpoint &&
993 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, 993 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
@@ -1001,7 +1001,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
1001 snd_usX2Y_pcm_private_free(pcm); 1001 snd_usX2Y_pcm_private_free(pcm);
1002 return err; 1002 return err;
1003 } 1003 }
1004 usX2Y(card)->chip.pcm_devs++; 1004 usX2Y(card)->pcm_devs++;
1005 1005
1006 return 0; 1006 return 0;
1007} 1007}
@@ -1013,14 +1013,14 @@ int usX2Y_audio_create(struct snd_card *card)
1013{ 1013{
1014 int err = 0; 1014 int err = 0;
1015 1015
1016 INIT_LIST_HEAD(&usX2Y(card)->chip.pcm_list); 1016 INIT_LIST_HEAD(&usX2Y(card)->pcm_list);
1017 1017
1018 if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8))) 1018 if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8)))
1019 return err; 1019 return err;
1020 if (le16_to_cpu(usX2Y(card)->chip.dev->descriptor.idProduct) == USB_ID_US428) 1020 if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428)
1021 if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA))) 1021 if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA)))
1022 return err; 1022 return err;
1023 if (le16_to_cpu(usX2Y(card)->chip.dev->descriptor.idProduct) != USB_ID_US122) 1023 if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122)
1024 err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. 1024 err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122.
1025 return err; 1025 return err;
1026} 1026}
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 4b2304c2e02d..9ed6c3956ca7 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -234,7 +234,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
234 234
235 if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { 235 if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
236 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", 236 snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
237 usb_get_current_frame_number(usX2Y->chip.dev), 237 usb_get_current_frame_number(usX2Y->dev),
238 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", 238 subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
239 urb->status, urb->start_frame); 239 urb->status, urb->start_frame);
240 return; 240 return;
@@ -318,7 +318,7 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs)
318 int i; 318 int i;
319 unsigned int pipe; 319 unsigned int pipe;
320 int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; 320 int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
321 struct usb_device *dev = subs->usX2Y->chip.dev; 321 struct usb_device *dev = subs->usX2Y->dev;
322 322
323 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : 323 pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
324 usb_rcvisocpipe(dev, subs->endpoint); 324 usb_rcvisocpipe(dev, subs->endpoint);
@@ -441,7 +441,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
441 unsigned long pack; 441 unsigned long pack;
442 if (0 == u) 442 if (0 == u)
443 atomic_set(&subs->state, state_STARTING3); 443 atomic_set(&subs->state, state_STARTING3);
444 urb->dev = usX2Y->chip.dev; 444 urb->dev = usX2Y->dev;
445 urb->transfer_flags = URB_ISO_ASAP; 445 urb->transfer_flags = URB_ISO_ASAP;
446 for (pack = 0; pack < nr_of_packs(); pack++) { 446 for (pack = 0; pack < nr_of_packs(); pack++) {
447 urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); 447 urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());
@@ -741,7 +741,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
741 int err; 741 int err;
742 struct snd_hwdep *hw; 742 struct snd_hwdep *hw;
743 struct snd_pcm *pcm; 743 struct snd_pcm *pcm;
744 struct usb_device *dev = usX2Y(card)->chip.dev; 744 struct usb_device *dev = usX2Y(card)->dev;
745 if (1 != nr_of_packs()) 745 if (1 != nr_of_packs())
746 return 0; 746 return 0;
747 747
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 0854f110bf7f..fe08660ce0bd 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -12,6 +12,7 @@ perf*.1
12perf*.xml 12perf*.xml
13perf*.html 13perf*.html
14common-cmds.h 14common-cmds.h
15perf.data
15tags 16tags
16TAGS 17TAGS
17cscope* 18cscope*
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
new file mode 100644
index 000000000000..ae525ac5a2ce
--- /dev/null
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -0,0 +1,120 @@
1perf-bench(1)
2============
3
4NAME
5----
6perf-bench - General framework for benchmark suites
7
8SYNOPSIS
9--------
10[verse]
11'perf bench' [<common options>] <subsystem> <suite> [<options>]
12
13DESCRIPTION
14-----------
15This 'perf bench' command is general framework for benchmark suites.
16
17COMMON OPTIONS
18--------------
19-f::
20--format=::
21Specify format style.
22Current available format styles are,
23
24'default'::
25Default style. This is mainly for human reading.
26---------------------
27% perf bench sched pipe # with no style specify
28(executing 1000000 pipe operations between two tasks)
29 Total time:5.855 sec
30 5.855061 usecs/op
31 170792 ops/sec
32---------------------
33
34'simple'::
35This simple style is friendly for automated
36processing by scripts.
37---------------------
38% perf bench --format=simple sched pipe # specified simple
395.988
40---------------------
41
42SUBSYSTEM
43---------
44
45'sched'::
46 Scheduler and IPC mechanisms.
47
48SUITES FOR 'sched'
49~~~~~~~~~~~~~~~~~~
50*messaging*::
51Suite for evaluating performance of scheduler and IPC mechanisms.
52Based on hackbench by Rusty Russell.
53
54Options of *pipe*
55^^^^^^^^^^^^^^^^^
56-p::
57--pipe::
58Use pipe() instead of socketpair()
59
60-t::
61--thread::
62Be multi thread instead of multi process
63
64-g::
65--group=::
66Specify number of groups
67
68-l::
69--loop=::
70Specify number of loops
71
72Example of *messaging*
73^^^^^^^^^^^^^^^^^^^^^^
74
75---------------------
76% perf bench sched messaging # run with default
77options (20 sender and receiver processes per group)
78(10 groups == 400 processes run)
79
80 Total time:0.308 sec
81
82% perf bench sched messaging -t -g 20 # be multi-thread,with 20 groups
83(20 sender and receiver threads per group)
84(20 groups == 800 threads run)
85
86 Total time:0.582 sec
87---------------------
88
89*pipe*::
90Suite for pipe() system call.
91Based on pipe-test-1m.c by Ingo Molnar.
92
93Options of *pipe*
94^^^^^^^^^^^^^^^^^
95-l::
96--loop=::
97Specify number of loops.
98
99Example of *pipe*
100^^^^^^^^^^^^^^^^^
101
102---------------------
103% perf bench sched pipe
104(executing 1000000 pipe operations between two tasks)
105
106 Total time:8.091 sec
107 8.091833 usecs/op
108 123581 ops/sec
109
110% perf bench sched pipe -l 1000 # loop 1000
111(executing 1000 pipe operations between two tasks)
112
113 Total time:0.016 sec
114 16.948000 usecs/op
115 59004 ops/sec
116---------------------
117
118SEE ALSO
119--------
120linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
new file mode 100644
index 000000000000..01b642c0bf8f
--- /dev/null
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -0,0 +1,34 @@
1perf-buildid-list(1)
2====================
3
4NAME
5----
6perf-buildid-list - List the buildids in a perf.data file
7
8SYNOPSIS
9--------
10[verse]
11'perf buildid-list <options>'
12
13DESCRIPTION
14-----------
15This command displays the buildids found in a perf.data file, so that other
16tools can be used to fetch packages with matching symbol tables for use by
17perf report.
18
19OPTIONS
20-------
21-i::
22--input=::
23 Input file name. (default: perf.data)
24-f::
25--force::
26 Don't do ownership validation.
27-v::
28--verbose::
29 Be more verbose.
30
31SEE ALSO
32--------
33linkperf:perf-record[1], linkperf:perf-top[1],
34linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
new file mode 100644
index 000000000000..44b0ce35c28a
--- /dev/null
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -0,0 +1,44 @@
1perf-kmem(1)
2==============
3
4NAME
5----
6perf-kmem - Tool to trace/measure kernel memory(slab) properties
7
8SYNOPSIS
9--------
10[verse]
11'perf kmem' {record} [<options>]
12
13DESCRIPTION
14-----------
15There's two variants of perf kmem:
16
17 'perf kmem record <command>' to record the kmem events
18 of an arbitrary workload.
19
20 'perf kmem' to report kernel memory statistics.
21
22OPTIONS
23-------
24-i <file>::
25--input=<file>::
26 Select the input file (default: perf.data)
27
28--stat=<caller|alloc>::
29 Select per callsite or per allocation statistics
30
31-s <key[,key2...]>::
32--sort=<key[,key2...]>::
33 Sort the output (default: frag,hit,bytes)
34
35-l <num>::
36--line=<num>::
37 Print n lines only
38
39--raw-ip::
40 Print raw ip instead of symbol
41
42SEE ALSO
43--------
44linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
new file mode 100644
index 000000000000..9270594e6dfd
--- /dev/null
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -0,0 +1,49 @@
1perf-probe(1)
2=============
3
4NAME
5----
6perf-probe - Define new dynamic tracepoints
7
8SYNOPSIS
9--------
10[verse]
11'perf probe' [options] --add 'PROBE' [--add 'PROBE' ...]
12or
13'perf probe' [options] 'PROBE' ['PROBE' ...]
14
15
16DESCRIPTION
17-----------
18This command defines dynamic tracepoint events, by symbol and registers
19without debuginfo, or by C expressions (C line numbers, C function names,
20and C local variables) with debuginfo.
21
22
23OPTIONS
24-------
25-k::
26--vmlinux=PATH::
27 Specify vmlinux path which has debuginfo (Dwarf binary).
28
29-v::
30--verbose::
31 Be more verbose (show parsed arguments, etc).
32
33-a::
34--add::
35 Define a probe point (see PROBE SYNTAX for detail)
36
37PROBE SYNTAX
38------------
39Probe points are defined by following syntax.
40
41 "FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
42
43'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function.
44It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number.
45'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
46
47SEE ALSO
48--------
49linkperf:perf-trace[1], linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 0ff23de9e453..fc46c0b40f6e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -26,11 +26,19 @@ OPTIONS
26 26
27-e:: 27-e::
28--event=:: 28--event=::
29 Select the PMU event. Selection can be a symbolic event name 29 Select the PMU event. Selection can be:
30 (use 'perf list' to list all events) or a raw PMU
31 event (eventsel+umask) in the form of rNNN where NNN is a
32 hexadecimal event descriptor.
33 30
31 - a symbolic event name (use 'perf list' to list all events)
32
33 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
34 hexadecimal event descriptor.
35
36 - a hardware breakpoint event in the form of '\mem:addr[:access]'
37 where addr is the address in memory you want to break in.
38 Access is the memory access type (read, write, execute) it can
39 be passed as follows: '\mem:addr[:[r][w][x]]'.
40 If you want to profile read-write accesses in 0x1000, just set
41 'mem:0x1000:rw'.
34-a:: 42-a::
35 System-wide collection. 43 System-wide collection.
36 44
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 59f0b846cd71..9dccb180b7af 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -24,11 +24,11 @@ OPTIONS
24--dsos=:: 24--dsos=::
25 Only consider symbols in these dsos. CSV that understands 25 Only consider symbols in these dsos. CSV that understands
26 file://filename entries. 26 file://filename entries.
27-n 27-n::
28--show-nr-samples 28--show-nr-samples::
29 Show the number of samples for each symbol 29 Show the number of samples for each symbol
30-T 30-T::
31--threads 31--threads::
32 Show per-thread event counters 32 Show per-thread event counters
33-C:: 33-C::
34--comms=:: 34--comms=::
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index a7910099d6fd..4b1788355eca 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -31,9 +31,12 @@ OPTIONS
31-w:: 31-w::
32--width=:: 32--width=::
33 Select the width of the SVG file (default: 1000) 33 Select the width of the SVG file (default: 1000)
34-p:: 34-P::
35--power-only:: 35--power-only::
36 Only output the CPU power section of the diagram 36 Only output the CPU power section of the diagram
37-p::
38--process::
39 Select the processes to display, by name or PID
37 40
38 41
39SEE ALSO 42SEE ALSO
diff --git a/tools/perf/Documentation/perf-trace-perl.txt b/tools/perf/Documentation/perf-trace-perl.txt
new file mode 100644
index 000000000000..c5f55f439091
--- /dev/null
+++ b/tools/perf/Documentation/perf-trace-perl.txt
@@ -0,0 +1,219 @@
1perf-trace-perl(1)
2==================
3
4NAME
5----
6perf-trace-perl - Process trace data with a Perl script
7
8SYNOPSIS
9--------
10[verse]
11'perf trace' [-s [lang]:script[.ext] ]
12
13DESCRIPTION
14-----------
15
16This perf trace option is used to process perf trace data using perf's
17built-in Perl interpreter. It reads and processes the input file and
18displays the results of the trace analysis implemented in the given
19Perl script, if any.
20
21STARTER SCRIPTS
22---------------
23
24You can avoid reading the rest of this document by running 'perf trace
25-g perl' in the same directory as an existing perf.data trace file.
26That will generate a starter script containing a handler for each of
27the event types in the trace file; it simply prints every available
28field for each event in the trace file.
29
30You can also look at the existing scripts in
31~/libexec/perf-core/scripts/perl for typical examples showing how to
32do basic things like aggregate event data, print results, etc. Also,
33the check-perf-trace.pl script, while not interesting for its results,
34attempts to exercise all of the main scripting features.
35
36EVENT HANDLERS
37--------------
38
39When perf trace is invoked using a trace script, a user-defined
40'handler function' is called for each event in the trace. If there's
41no handler function defined for a given event type, the event is
42ignored (or passed to a 'trace_handled' function, see below) and the
43next event is processed.
44
45Most of the event's field values are passed as arguments to the
46handler function; some of the less common ones aren't - those are
47available as calls back into the perf executable (see below).
48
49As an example, the following perf record command can be used to record
50all sched_wakeup events in the system:
51
52 # perf record -c 1 -f -a -M -R -e sched:sched_wakeup
53
54Traces meant to be processed using a script should be recorded with
55the above options: -c 1 says to sample every event, -a to enable
56system-wide collection, -M to multiplex the output, and -R to collect
57raw samples.
58
59The format file for the sched_wakep event defines the following fields
60(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
61
62----
63 format:
64 field:unsigned short common_type;
65 field:unsigned char common_flags;
66 field:unsigned char common_preempt_count;
67 field:int common_pid;
68 field:int common_lock_depth;
69
70 field:char comm[TASK_COMM_LEN];
71 field:pid_t pid;
72 field:int prio;
73 field:int success;
74 field:int target_cpu;
75----
76
77The handler function for this event would be defined as:
78
79----
80sub sched::sched_wakeup
81{
82 my ($event_name, $context, $common_cpu, $common_secs,
83 $common_nsecs, $common_pid, $common_comm,
84 $comm, $pid, $prio, $success, $target_cpu) = @_;
85}
86----
87
88The handler function takes the form subsystem::event_name.
89
90The $common_* arguments in the handler's argument list are the set of
91arguments passed to all event handlers; some of the fields correspond
92to the common_* fields in the format file, but some are synthesized,
93and some of the common_* fields aren't common enough to to be passed
94to every event as arguments but are available as library functions.
95
96Here's a brief description of each of the invariant event args:
97
98 $event_name the name of the event as text
99 $context an opaque 'cookie' used in calls back into perf
100 $common_cpu the cpu the event occurred on
101 $common_secs the secs portion of the event timestamp
102 $common_nsecs the nsecs portion of the event timestamp
103 $common_pid the pid of the current task
104 $common_comm the name of the current process
105
106All of the remaining fields in the event's format file have
107counterparts as handler function arguments of the same name, as can be
108seen in the example above.
109
110The above provides the basics needed to directly access every field of
111every event in a trace, which covers 90% of what you need to know to
112write a useful trace script. The sections below cover the rest.
113
114SCRIPT LAYOUT
115-------------
116
117Every perf trace Perl script should start by setting up a Perl module
118search path and 'use'ing a few support modules (see module
119descriptions below):
120
121----
122 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
123 use lib "./Perf-Trace-Util/lib";
124 use Perf::Trace::Core;
125 use Perf::Trace::Context;
126 use Perf::Trace::Util;
127----
128
129The rest of the script can contain handler functions and support
130functions in any order.
131
132Aside from the event handler functions discussed above, every script
133can implement a set of optional functions:
134
135*trace_begin*, if defined, is called before any event is processed and
136gives scripts a chance to do setup tasks:
137
138----
139 sub trace_begin
140 {
141 }
142----
143
144*trace_end*, if defined, is called after all events have been
145 processed and gives scripts a chance to do end-of-script tasks, such
146 as display results:
147
148----
149sub trace_end
150{
151}
152----
153
154*trace_unhandled*, if defined, is called after for any event that
155 doesn't have a handler explicitly defined for it. The standard set
156 of common arguments are passed into it:
157
158----
159sub trace_unhandled
160{
161 my ($event_name, $context, $common_cpu, $common_secs,
162 $common_nsecs, $common_pid, $common_comm) = @_;
163}
164----
165
166The remaining sections provide descriptions of each of the available
167built-in perf trace Perl modules and their associated functions.
168
169AVAILABLE MODULES AND FUNCTIONS
170-------------------------------
171
172The following sections describe the functions and variables available
173via the various Perf::Trace::* Perl modules. To use the functions and
174variables from the given module, add the corresponding 'use
175Perf::Trace::XXX' line to your perf trace script.
176
177Perf::Trace::Core Module
178~~~~~~~~~~~~~~~~~~~~~~~~
179
180These functions provide some essential functions to user scripts.
181
182The *flag_str* and *symbol_str* functions provide human-readable
183strings for flag and symbolic fields. These correspond to the strings
184and values parsed from the 'print fmt' fields of the event format
185files:
186
187 flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name
188 symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name
189
190Perf::Trace::Context Module
191~~~~~~~~~~~~~~~~~~~~~~~~~~~
192
193Some of the 'common' fields in the event format file aren't all that
194common, but need to be made accessible to user scripts nonetheless.
195
196Perf::Trace::Context defines a set of functions that can be used to
197access this data in the context of the current event. Each of these
198functions expects a $context variable, which is the same as the
199$context variable passed into every event handler as the second
200argument.
201
202 common_pc($context) - returns common_preempt count for the current event
203 common_flags($context) - returns common_flags for the current event
204 common_lock_depth($context) - returns common_lock_depth for the current event
205
206Perf::Trace::Util Module
207~~~~~~~~~~~~~~~~~~~~~~~~
208
209Various utility functions for use with perf trace:
210
211 nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair
212 nsecs_secs($nsecs) - returns whole secs portion given nsecs
213 nsecs_nsecs($nsecs) - returns nsecs remainder given nsecs
214 nsecs_str($nsecs) - returns printable string in the form secs.nsecs
215 avg($total, $n) - returns average given a sum and a total number of values
216
217SEE ALSO
218--------
219linkperf:perf-trace[1]
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 41ed75398ca9..07065efa60e0 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -20,6 +20,15 @@ OPTIONS
20--dump-raw-trace=:: 20--dump-raw-trace=::
21 Display verbose dump of the trace data. 21 Display verbose dump of the trace data.
22 22
23-s::
24--script=::
25 Process trace data with the given script ([lang]:script[.ext]).
26
27-g::
28--gen-script=::
29 Generate perf-trace.[ext] starter script for given language,
30 using current perf.data.
31
23SEE ALSO 32SEE ALSO
24-------- 33--------
25linkperf:perf-record[1] 34linkperf:perf-record[1], linkperf:perf-trace-perl[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7e190d522cd5..23ec66098bdc 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -2,6 +2,7 @@
2all:: 2all::
3 3
4# Define V=1 to have a more verbose compile. 4# Define V=1 to have a more verbose compile.
5# Define V=2 to have an even more verbose compile.
5# 6#
6# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf() 7# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
7# or vsnprintf() return -1 instead of number of characters which would 8# or vsnprintf() return -1 instead of number of characters which would
@@ -145,6 +146,10 @@ all::
145# Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call 146# Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call
146# your external grep (e.g., if your system lacks grep, if its grep is 147# your external grep (e.g., if your system lacks grep, if its grep is
147# broken, or spawning external process is slower than built-in grep perf has). 148# broken, or spawning external process is slower than built-in grep perf has).
149#
150# Define LDFLAGS=-static to build a static binary.
151#
152# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
148 153
149PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 154PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
150 @$(SHELL_PATH) util/PERF-VERSION-GEN 155 @$(SHELL_PATH) util/PERF-VERSION-GEN
@@ -157,20 +162,6 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
157uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') 162uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 163uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
159 164
160#
161# Add -m32 for cross-builds:
162#
163ifdef NO_64BIT
164 MBITS := -m32
165else
166 #
167 # If we're on a 64-bit kernel, use -m64:
168 #
169 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
170 MBITS := -m64
171 endif
172endif
173
174# CFLAGS and LDFLAGS are for the users to override from the command line. 165# CFLAGS and LDFLAGS are for the users to override from the command line.
175 166
176# 167#
@@ -200,8 +191,15 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
200EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes 191EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement 192EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
202 193
203CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) 194ifeq ("$(origin DEBUG)", "command line")
204LDFLAGS = -lpthread -lrt -lelf -lm 195 PERF_DEBUG = $(DEBUG)
196endif
197ifndef PERF_DEBUG
198 CFLAGS_OPTIMIZE = -O6
199endif
200
201CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
202EXTLIBS = -lpthread -lrt -lelf -lm
205ALL_CFLAGS = $(CFLAGS) 203ALL_CFLAGS = $(CFLAGS)
206ALL_LDFLAGS = $(LDFLAGS) 204ALL_LDFLAGS = $(LDFLAGS)
207STRIP ?= strip 205STRIP ?= strip
@@ -252,6 +250,9 @@ PTHREAD_LIBS = -lpthread
252# explicitly what architecture to check for. Fix this up for yours.. 250# explicitly what architecture to check for. Fix this up for yours..
253SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 251SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
254 252
253ifeq ($(shell sh -c "echo 'int foo(void) {char X[2]; return 3;}' | $(CC) -x c -c -Werror -fstack-protector-all - -o /dev/null "$(QUIET_STDERR)" && echo y"), y)
254 CFLAGS := $(CFLAGS) -fstack-protector-all
255endif
255 256
256 257
257### --- END CONFIGURATION SECTION --- 258### --- END CONFIGURATION SECTION ---
@@ -327,8 +328,28 @@ LIB_FILE=libperf.a
327LIB_H += ../../include/linux/perf_event.h 328LIB_H += ../../include/linux/perf_event.h
328LIB_H += ../../include/linux/rbtree.h 329LIB_H += ../../include/linux/rbtree.h
329LIB_H += ../../include/linux/list.h 330LIB_H += ../../include/linux/list.h
331LIB_H += ../../include/linux/stringify.h
332LIB_H += util/include/linux/bitmap.h
333LIB_H += util/include/linux/bitops.h
334LIB_H += util/include/linux/compiler.h
335LIB_H += util/include/linux/ctype.h
336LIB_H += util/include/linux/kernel.h
330LIB_H += util/include/linux/list.h 337LIB_H += util/include/linux/list.h
338LIB_H += util/include/linux/module.h
339LIB_H += util/include/linux/poison.h
340LIB_H += util/include/linux/prefetch.h
341LIB_H += util/include/linux/rbtree.h
342LIB_H += util/include/linux/string.h
343LIB_H += util/include/linux/types.h
344LIB_H += util/include/asm/asm-offsets.h
345LIB_H += util/include/asm/bitops.h
346LIB_H += util/include/asm/byteorder.h
347LIB_H += util/include/asm/swab.h
348LIB_H += util/include/asm/system.h
349LIB_H += util/include/asm/uaccess.h
331LIB_H += perf.h 350LIB_H += perf.h
351LIB_H += util/debugfs.h
352LIB_H += util/event.h
332LIB_H += util/types.h 353LIB_H += util/types.h
333LIB_H += util/levenshtein.h 354LIB_H += util/levenshtein.h
334LIB_H += util/parse-options.h 355LIB_H += util/parse-options.h
@@ -342,15 +363,22 @@ LIB_H += util/strlist.h
342LIB_H += util/run-command.h 363LIB_H += util/run-command.h
343LIB_H += util/sigchain.h 364LIB_H += util/sigchain.h
344LIB_H += util/symbol.h 365LIB_H += util/symbol.h
345LIB_H += util/module.h
346LIB_H += util/color.h 366LIB_H += util/color.h
347LIB_H += util/values.h 367LIB_H += util/values.h
368LIB_H += util/sort.h
369LIB_H += util/hist.h
370LIB_H += util/thread.h
371LIB_H += util/data_map.h
372LIB_H += util/probe-finder.h
373LIB_H += util/probe-event.h
348 374
349LIB_OBJS += util/abspath.o 375LIB_OBJS += util/abspath.o
350LIB_OBJS += util/alias.o 376LIB_OBJS += util/alias.o
351LIB_OBJS += util/config.o 377LIB_OBJS += util/config.o
352LIB_OBJS += util/ctype.o 378LIB_OBJS += util/ctype.o
379LIB_OBJS += util/debugfs.o
353LIB_OBJS += util/environment.o 380LIB_OBJS += util/environment.o
381LIB_OBJS += util/event.o
354LIB_OBJS += util/exec_cmd.o 382LIB_OBJS += util/exec_cmd.o
355LIB_OBJS += util/help.o 383LIB_OBJS += util/help.o
356LIB_OBJS += util/levenshtein.o 384LIB_OBJS += util/levenshtein.o
@@ -358,6 +386,9 @@ LIB_OBJS += util/parse-options.o
358LIB_OBJS += util/parse-events.o 386LIB_OBJS += util/parse-events.o
359LIB_OBJS += util/path.o 387LIB_OBJS += util/path.o
360LIB_OBJS += util/rbtree.o 388LIB_OBJS += util/rbtree.o
389LIB_OBJS += util/bitmap.o
390LIB_OBJS += util/hweight.o
391LIB_OBJS += util/find_next_bit.o
361LIB_OBJS += util/run-command.o 392LIB_OBJS += util/run-command.o
362LIB_OBJS += util/quote.o 393LIB_OBJS += util/quote.o
363LIB_OBJS += util/strbuf.o 394LIB_OBJS += util/strbuf.o
@@ -367,7 +398,6 @@ LIB_OBJS += util/usage.o
367LIB_OBJS += util/wrapper.o 398LIB_OBJS += util/wrapper.o
368LIB_OBJS += util/sigchain.o 399LIB_OBJS += util/sigchain.o
369LIB_OBJS += util/symbol.o 400LIB_OBJS += util/symbol.o
370LIB_OBJS += util/module.o
371LIB_OBJS += util/color.o 401LIB_OBJS += util/color.o
372LIB_OBJS += util/pager.o 402LIB_OBJS += util/pager.o
373LIB_OBJS += util/header.o 403LIB_OBJS += util/header.o
@@ -379,11 +409,25 @@ LIB_OBJS += util/thread.o
379LIB_OBJS += util/trace-event-parse.o 409LIB_OBJS += util/trace-event-parse.o
380LIB_OBJS += util/trace-event-read.o 410LIB_OBJS += util/trace-event-read.o
381LIB_OBJS += util/trace-event-info.o 411LIB_OBJS += util/trace-event-info.o
412LIB_OBJS += util/trace-event-perl.o
382LIB_OBJS += util/svghelper.o 413LIB_OBJS += util/svghelper.o
414LIB_OBJS += util/sort.o
415LIB_OBJS += util/hist.o
416LIB_OBJS += util/data_map.o
417LIB_OBJS += util/probe-event.o
383 418
384BUILTIN_OBJS += builtin-annotate.o 419BUILTIN_OBJS += builtin-annotate.o
420
421BUILTIN_OBJS += builtin-bench.o
422
423# Benchmark modules
424BUILTIN_OBJS += bench/sched-messaging.o
425BUILTIN_OBJS += bench/sched-pipe.o
426BUILTIN_OBJS += bench/mem-memcpy.o
427
385BUILTIN_OBJS += builtin-help.o 428BUILTIN_OBJS += builtin-help.o
386BUILTIN_OBJS += builtin-sched.o 429BUILTIN_OBJS += builtin-sched.o
430BUILTIN_OBJS += builtin-buildid-list.o
387BUILTIN_OBJS += builtin-list.o 431BUILTIN_OBJS += builtin-list.o
388BUILTIN_OBJS += builtin-record.o 432BUILTIN_OBJS += builtin-record.o
389BUILTIN_OBJS += builtin-report.o 433BUILTIN_OBJS += builtin-report.o
@@ -391,9 +435,16 @@ BUILTIN_OBJS += builtin-stat.o
391BUILTIN_OBJS += builtin-timechart.o 435BUILTIN_OBJS += builtin-timechart.o
392BUILTIN_OBJS += builtin-top.o 436BUILTIN_OBJS += builtin-top.o
393BUILTIN_OBJS += builtin-trace.o 437BUILTIN_OBJS += builtin-trace.o
438BUILTIN_OBJS += builtin-probe.o
439BUILTIN_OBJS += builtin-kmem.o
394 440
395PERFLIBS = $(LIB_FILE) 441PERFLIBS = $(LIB_FILE)
396 442
443ifeq ($(V), 2)
444 QUIET_STDERR = ">/dev/null"
445else
446 QUIET_STDERR = ">/dev/null 2>&1"
447endif
397# 448#
398# Platform specific tweaks 449# Platform specific tweaks
399# 450#
@@ -421,36 +472,58 @@ ifeq ($(uname_S),Darwin)
421 PTHREAD_LIBS = 472 PTHREAD_LIBS =
422endif 473endif
423 474
424ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) 475ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
425 ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) 476ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
477 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
478endif
479
480 ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
426 BASIC_CFLAGS += -DLIBELF_NO_MMAP 481 BASIC_CFLAGS += -DLIBELF_NO_MMAP
427 endif 482 endif
428else 483else
429 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); 484 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
430endif 485endif
431 486
487ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
488 msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
489 BASIC_CFLAGS += -DNO_LIBDWARF
490else
491 EXTLIBS += -lelf -ldwarf
492 LIB_OBJS += util/probe-finder.o
493endif
494
495PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null`
496PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
497
498ifneq ($(shell sh -c "(echo '\#include <EXTERN.h>'; echo '\#include <perl.h>'; echo 'int main(void) { perl_alloc(); return 0; }') | $(CC) -x c - $(PERL_EMBED_CCOPTS) -o /dev/null $(PERL_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y)
499 BASIC_CFLAGS += -DNO_LIBPERL
500else
501 ALL_LDFLAGS += $(PERL_EMBED_LDOPTS)
502 LIB_OBJS += scripts/perl/Perf-Trace-Util/Context.o
503endif
504
432ifdef NO_DEMANGLE 505ifdef NO_DEMANGLE
433 BASIC_CFLAGS += -DNO_DEMANGLE 506 BASIC_CFLAGS += -DNO_DEMANGLE
434else 507else
435 has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y") 508 has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y")
436 509
437 ifeq ($(has_bfd),y) 510 ifeq ($(has_bfd),y)
438 EXTLIBS += -lbfd 511 EXTLIBS += -lbfd
439 else 512 else
440 has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y") 513 has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y")
441 ifeq ($(has_bfd_iberty),y) 514 ifeq ($(has_bfd_iberty),y)
442 EXTLIBS += -lbfd -liberty 515 EXTLIBS += -lbfd -liberty
443 else 516 else
444 has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y") 517 has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y")
445 ifeq ($(has_bfd_iberty_z),y) 518 ifeq ($(has_bfd_iberty_z),y)
446 EXTLIBS += -lbfd -liberty -lz 519 EXTLIBS += -lbfd -liberty -lz
447 else 520 else
448 has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -liberty > /dev/null 2>&1 && echo y") 521 has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y")
449 ifeq ($(has_cplus_demangle),y) 522 ifeq ($(has_cplus_demangle),y)
450 EXTLIBS += -liberty 523 EXTLIBS += -liberty
451 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE 524 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
452 else 525 else
453 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling) 526 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
454 BASIC_CFLAGS += -DNO_DEMANGLE 527 BASIC_CFLAGS += -DNO_DEMANGLE
455 endif 528 endif
456 endif 529 endif
@@ -787,6 +860,25 @@ util/config.o: util/config.c PERF-CFLAGS
787util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS 860util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
788 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 861 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
789 862
863# some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing
864# from <string.h> that comes from kernel headers wrapping.
865KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//`
866
867util/bitmap.o: ../../lib/bitmap.c PERF-CFLAGS
868 $(QUIET_CC)$(CC) -o util/bitmap.o -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
869
870util/hweight.o: ../../lib/hweight.c PERF-CFLAGS
871 $(QUIET_CC)$(CC) -o util/hweight.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
872
873util/find_next_bit.o: ../../lib/find_next_bit.c PERF-CFLAGS
874 $(QUIET_CC)$(CC) -o util/find_next_bit.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
875
876util/trace-event-perl.o: util/trace-event-perl.c PERF-CFLAGS
877 $(QUIET_CC)$(CC) -o util/trace-event-perl.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
878
879scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c PERF-CFLAGS
880 $(QUIET_CC)$(CC) -o scripts/perl/Perf-Trace-Util/Context.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
881
790perf-%$X: %.o $(PERFLIBS) 882perf-%$X: %.o $(PERFLIBS)
791 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 883 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
792 884
@@ -894,6 +986,13 @@ export perfexec_instdir
894install: all 986install: all
895 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 987 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
896 $(INSTALL) perf$X '$(DESTDIR_SQ)$(bindir_SQ)' 988 $(INSTALL) perf$X '$(DESTDIR_SQ)$(bindir_SQ)'
989 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
990 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
991 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
992 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
993 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
994 $(INSTALL) scripts/perl/Perf-Trace-Util/Makefile.PL -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util'
995 $(INSTALL) scripts/perl/Perf-Trace-Util/README -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util'
897ifdef BUILT_INS 996ifdef BUILT_INS
898 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 997 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
899 $(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 998 $(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
@@ -979,7 +1078,7 @@ distclean: clean
979# $(RM) configure 1078# $(RM) configure
980 1079
981clean: 1080clean:
982 $(RM) *.o */*.o $(LIB_FILE) 1081 $(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE)
983 $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X 1082 $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X
984 $(RM) $(TEST_PROGRAMS) 1083 $(RM) $(TEST_PROGRAMS)
985 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope* 1084 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
new file mode 100644
index 000000000000..f7781c6267c0
--- /dev/null
+++ b/tools/perf/bench/bench.h
@@ -0,0 +1,17 @@
1#ifndef BENCH_H
2#define BENCH_H
3
4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used);
7
8#define BENCH_FORMAT_DEFAULT_STR "default"
9#define BENCH_FORMAT_DEFAULT 0
10#define BENCH_FORMAT_SIMPLE_STR "simple"
11#define BENCH_FORMAT_SIMPLE 1
12
13#define BENCH_FORMAT_UNKNOWN -1
14
15extern int bench_format;
16
17#endif
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
new file mode 100644
index 000000000000..89773178e894
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy.c
@@ -0,0 +1,193 @@
1/*
2 * mem-memcpy.c
3 *
4 * memcpy: Simple memory copy in various ways
5 *
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */
8#include <ctype.h>
9
10#include "../perf.h"
11#include "../util/util.h"
12#include "../util/parse-options.h"
13#include "../util/string.h"
14#include "../util/header.h"
15#include "bench.h"
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/time.h>
21#include <errno.h>
22
23#define K 1024
24
25static const char *length_str = "1MB";
26static const char *routine = "default";
27static int use_clock = 0;
28static int clock_fd;
29
30static const struct option options[] = {
31 OPT_STRING('l', "length", &length_str, "1MB",
32 "Specify length of memory to copy. "
33 "available unit: B, MB, GB (upper and lower)"),
34 OPT_STRING('r', "routine", &routine, "default",
35 "Specify routine to copy"),
36 OPT_BOOLEAN('c', "clock", &use_clock,
37 "Use CPU clock for measuring"),
38 OPT_END()
39};
40
41struct routine {
42 const char *name;
43 const char *desc;
44 void * (*fn)(void *dst, const void *src, size_t len);
45};
46
47struct routine routines[] = {
48 { "default",
49 "Default memcpy() provided by glibc",
50 memcpy },
51 { NULL,
52 NULL,
53 NULL }
54};
55
56static const char * const bench_mem_memcpy_usage[] = {
57 "perf bench mem memcpy <options>",
58 NULL
59};
60
61static struct perf_event_attr clock_attr = {
62 .type = PERF_TYPE_HARDWARE,
63 .config = PERF_COUNT_HW_CPU_CYCLES
64};
65
66static void init_clock(void)
67{
68 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
69
70 if (clock_fd < 0 && errno == ENOSYS)
71 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
72 else
73 BUG_ON(clock_fd < 0);
74}
75
76static u64 get_clock(void)
77{
78 int ret;
79 u64 clk;
80
81 ret = read(clock_fd, &clk, sizeof(u64));
82 BUG_ON(ret != sizeof(u64));
83
84 return clk;
85}
86
87static double timeval2double(struct timeval *ts)
88{
89 return (double)ts->tv_sec +
90 (double)ts->tv_usec / (double)1000000;
91}
92
93int bench_mem_memcpy(int argc, const char **argv,
94 const char *prefix __used)
95{
96 int i;
97 void *dst, *src;
98 size_t length;
99 double bps = 0.0;
100 struct timeval tv_start, tv_end, tv_diff;
101 u64 clock_start, clock_end, clock_diff;
102
103 clock_start = clock_end = clock_diff = 0ULL;
104 argc = parse_options(argc, argv, options,
105 bench_mem_memcpy_usage, 0);
106
107 tv_diff.tv_sec = 0;
108 tv_diff.tv_usec = 0;
109 length = (size_t)perf_atoll((char *)length_str);
110
111 if ((s64)length <= 0) {
112 fprintf(stderr, "Invalid length:%s\n", length_str);
113 return 1;
114 }
115
116 for (i = 0; routines[i].name; i++) {
117 if (!strcmp(routines[i].name, routine))
118 break;
119 }
120 if (!routines[i].name) {
121 printf("Unknown routine:%s\n", routine);
122 printf("Available routines...\n");
123 for (i = 0; routines[i].name; i++) {
124 printf("\t%s ... %s\n",
125 routines[i].name, routines[i].desc);
126 }
127 return 1;
128 }
129
130 dst = zalloc(length);
131 if (!dst)
132 die("memory allocation failed - maybe length is too large?\n");
133
134 src = zalloc(length);
135 if (!src)
136 die("memory allocation failed - maybe length is too large?\n");
137
138 if (bench_format == BENCH_FORMAT_DEFAULT) {
139 printf("# Copying %s Bytes from %p to %p ...\n\n",
140 length_str, src, dst);
141 }
142
143 if (use_clock) {
144 init_clock();
145 clock_start = get_clock();
146 } else {
147 BUG_ON(gettimeofday(&tv_start, NULL));
148 }
149
150 routines[i].fn(dst, src, length);
151
152 if (use_clock) {
153 clock_end = get_clock();
154 clock_diff = clock_end - clock_start;
155 } else {
156 BUG_ON(gettimeofday(&tv_end, NULL));
157 timersub(&tv_end, &tv_start, &tv_diff);
158 bps = (double)((double)length / timeval2double(&tv_diff));
159 }
160
161 switch (bench_format) {
162 case BENCH_FORMAT_DEFAULT:
163 if (use_clock) {
164 printf(" %14lf Clock/Byte\n",
165 (double)clock_diff / (double)length);
166 } else {
167 if (bps < K)
168 printf(" %14lf B/Sec\n", bps);
169 else if (bps < K * K)
170 printf(" %14lfd KB/Sec\n", bps / 1024);
171 else if (bps < K * K * K)
172 printf(" %14lf MB/Sec\n", bps / 1024 / 1024);
173 else {
174 printf(" %14lf GB/Sec\n",
175 bps / 1024 / 1024 / 1024);
176 }
177 }
178 break;
179 case BENCH_FORMAT_SIMPLE:
180 if (use_clock) {
181 printf("%14lf\n",
182 (double)clock_diff / (double)length);
183 } else
184 printf("%lf\n", bps);
185 break;
186 default:
187 /* reaching this means there's some disaster: */
188 die("unknown format: %d\n", bench_format);
189 break;
190 }
191
192 return 0;
193}
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
new file mode 100644
index 000000000000..605a2a959aa8
--- /dev/null
+++ b/tools/perf/bench/sched-messaging.c
@@ -0,0 +1,336 @@
1/*
2 *
3 * builtin-bench-messaging.c
4 *
5 * messaging: Benchmark for scheduler and IPC mechanisms
6 *
7 * Based on hackbench by Rusty Russell <rusty@rustcorp.com.au>
8 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
9 *
10 */
11
12#include "../perf.h"
13#include "../util/util.h"
14#include "../util/parse-options.h"
15#include "../builtin.h"
16#include "bench.h"
17
18/* Test groups of 20 processes spraying to 20 receivers */
19#include <pthread.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <errno.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/wait.h>
28#include <sys/time.h>
29#include <sys/poll.h>
30#include <limits.h>
31
32#define DATASIZE 100
33
34static int use_pipes = 0;
35static unsigned int loops = 100;
36static unsigned int thread_mode = 0;
37static unsigned int num_groups = 10;
38
39struct sender_context {
40 unsigned int num_fds;
41 int ready_out;
42 int wakefd;
43 int out_fds[0];
44};
45
46struct receiver_context {
47 unsigned int num_packets;
48 int in_fds[2];
49 int ready_out;
50 int wakefd;
51};
52
53static void barf(const char *msg)
54{
55 fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
56 exit(1);
57}
58
59static void fdpair(int fds[2])
60{
61 if (use_pipes) {
62 if (pipe(fds) == 0)
63 return;
64 } else {
65 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
66 return;
67 }
68
69 barf(use_pipes ? "pipe()" : "socketpair()");
70}
71
72/* Block until we're ready to go */
73static void ready(int ready_out, int wakefd)
74{
75 char dummy;
76 struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
77
78 /* Tell them we're ready. */
79 if (write(ready_out, &dummy, 1) != 1)
80 barf("CLIENT: ready write");
81
82 /* Wait for "GO" signal */
83 if (poll(&pollfd, 1, -1) != 1)
84 barf("poll");
85}
86
87/* Sender sprays loops messages down each file descriptor */
88static void *sender(struct sender_context *ctx)
89{
90 char data[DATASIZE];
91 unsigned int i, j;
92
93 ready(ctx->ready_out, ctx->wakefd);
94
95 /* Now pump to every receiver. */
96 for (i = 0; i < loops; i++) {
97 for (j = 0; j < ctx->num_fds; j++) {
98 int ret, done = 0;
99
100again:
101 ret = write(ctx->out_fds[j], data + done,
102 sizeof(data)-done);
103 if (ret < 0)
104 barf("SENDER: write");
105 done += ret;
106 if (done < DATASIZE)
107 goto again;
108 }
109 }
110
111 return NULL;
112}
113
114
115/* One receiver per fd */
116static void *receiver(struct receiver_context* ctx)
117{
118 unsigned int i;
119
120 if (!thread_mode)
121 close(ctx->in_fds[1]);
122
123 /* Wait for start... */
124 ready(ctx->ready_out, ctx->wakefd);
125
126 /* Receive them all */
127 for (i = 0; i < ctx->num_packets; i++) {
128 char data[DATASIZE];
129 int ret, done = 0;
130
131again:
132 ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
133 if (ret < 0)
134 barf("SERVER: read");
135 done += ret;
136 if (done < DATASIZE)
137 goto again;
138 }
139
140 return NULL;
141}
142
143static pthread_t create_worker(void *ctx, void *(*func)(void *))
144{
145 pthread_attr_t attr;
146 pthread_t childid;
147 int err;
148
149 if (!thread_mode) {
150 /* process mode */
151 /* Fork the receiver. */
152 switch (fork()) {
153 case -1:
154 barf("fork()");
155 break;
156 case 0:
157 (*func) (ctx);
158 exit(0);
159 break;
160 default:
161 break;
162 }
163
164 return (pthread_t)0;
165 }
166
167 if (pthread_attr_init(&attr) != 0)
168 barf("pthread_attr_init:");
169
170#ifndef __ia64__
171 if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
172 barf("pthread_attr_setstacksize");
173#endif
174
175 err = pthread_create(&childid, &attr, func, ctx);
176 if (err != 0) {
177 fprintf(stderr, "pthread_create failed: %s (%d)\n",
178 strerror(err), err);
179 exit(-1);
180 }
181 return childid;
182}
183
184static void reap_worker(pthread_t id)
185{
186 int proc_status;
187 void *thread_status;
188
189 if (!thread_mode) {
190 /* process mode */
191 wait(&proc_status);
192 if (!WIFEXITED(proc_status))
193 exit(1);
194 } else {
195 pthread_join(id, &thread_status);
196 }
197}
198
199/* One group of senders and receivers */
200static unsigned int group(pthread_t *pth,
201 unsigned int num_fds,
202 int ready_out,
203 int wakefd)
204{
205 unsigned int i;
206 struct sender_context *snd_ctx = malloc(sizeof(struct sender_context)
207 + num_fds * sizeof(int));
208
209 if (!snd_ctx)
210 barf("malloc()");
211
212 for (i = 0; i < num_fds; i++) {
213 int fds[2];
214 struct receiver_context *ctx = malloc(sizeof(*ctx));
215
216 if (!ctx)
217 barf("malloc()");
218
219
220 /* Create the pipe between client and server */
221 fdpair(fds);
222
223 ctx->num_packets = num_fds * loops;
224 ctx->in_fds[0] = fds[0];
225 ctx->in_fds[1] = fds[1];
226 ctx->ready_out = ready_out;
227 ctx->wakefd = wakefd;
228
229 pth[i] = create_worker(ctx, (void *)receiver);
230
231 snd_ctx->out_fds[i] = fds[1];
232 if (!thread_mode)
233 close(fds[0]);
234 }
235
236 /* Now we have all the fds, fork the senders */
237 for (i = 0; i < num_fds; i++) {
238 snd_ctx->ready_out = ready_out;
239 snd_ctx->wakefd = wakefd;
240 snd_ctx->num_fds = num_fds;
241
242 pth[num_fds+i] = create_worker(snd_ctx, (void *)sender);
243 }
244
245 /* Close the fds we have left */
246 if (!thread_mode)
247 for (i = 0; i < num_fds; i++)
248 close(snd_ctx->out_fds[i]);
249
250 /* Return number of children to reap */
251 return num_fds * 2;
252}
253
254static const struct option options[] = {
255 OPT_BOOLEAN('p', "pipe", &use_pipes,
256 "Use pipe() instead of socketpair()"),
257 OPT_BOOLEAN('t', "thread", &thread_mode,
258 "Be multi thread instead of multi process"),
259 OPT_INTEGER('g', "group", &num_groups,
260 "Specify number of groups"),
261 OPT_INTEGER('l', "loop", &loops,
262 "Specify number of loops"),
263 OPT_END()
264};
265
266static const char * const bench_sched_message_usage[] = {
267 "perf bench sched messaging <options>",
268 NULL
269};
270
271int bench_sched_messaging(int argc, const char **argv,
272 const char *prefix __used)
273{
274 unsigned int i, total_children;
275 struct timeval start, stop, diff;
276 unsigned int num_fds = 20;
277 int readyfds[2], wakefds[2];
278 char dummy;
279 pthread_t *pth_tab;
280
281 argc = parse_options(argc, argv, options,
282 bench_sched_message_usage, 0);
283
284 pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
285 if (!pth_tab)
286 barf("main:malloc()");
287
288 fdpair(readyfds);
289 fdpair(wakefds);
290
291 total_children = 0;
292 for (i = 0; i < num_groups; i++)
293 total_children += group(pth_tab+total_children, num_fds,
294 readyfds[1], wakefds[0]);
295
296 /* Wait for everyone to be ready */
297 for (i = 0; i < total_children; i++)
298 if (read(readyfds[0], &dummy, 1) != 1)
299 barf("Reading for readyfds");
300
301 gettimeofday(&start, NULL);
302
303 /* Kick them off */
304 if (write(wakefds[1], &dummy, 1) != 1)
305 barf("Writing to start them");
306
307 /* Reap them all */
308 for (i = 0; i < total_children; i++)
309 reap_worker(pth_tab[i]);
310
311 gettimeofday(&stop, NULL);
312
313 timersub(&stop, &start, &diff);
314
315 switch (bench_format) {
316 case BENCH_FORMAT_DEFAULT:
317 printf("# %d sender and receiver %s per group\n",
318 num_fds, thread_mode ? "threads" : "processes");
319 printf("# %d groups == %d %s run\n\n",
320 num_groups, num_groups * 2 * num_fds,
321 thread_mode ? "threads" : "processes");
322 printf(" %14s: %lu.%03lu [sec]\n", "Total time",
323 diff.tv_sec, diff.tv_usec/1000);
324 break;
325 case BENCH_FORMAT_SIMPLE:
326 printf("%lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000);
327 break;
328 default:
329 /* reaching here is something disaster */
330 fprintf(stderr, "Unknown format:%d\n", bench_format);
331 exit(1);
332 break;
333 }
334
335 return 0;
336}
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
new file mode 100644
index 000000000000..238185f97977
--- /dev/null
+++ b/tools/perf/bench/sched-pipe.c
@@ -0,0 +1,124 @@
1/*
2 *
3 * builtin-bench-pipe.c
4 *
5 * pipe: Benchmark for pipe()
6 *
7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
10 *
11 */
12
13#include "../perf.h"
14#include "../util/util.h"
15#include "../util/parse-options.h"
16#include "../builtin.h"
17#include "bench.h"
18
19#include <unistd.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <signal.h>
23#include <sys/wait.h>
24#include <linux/unistd.h>
25#include <string.h>
26#include <errno.h>
27#include <assert.h>
28#include <sys/time.h>
29#include <sys/types.h>
30
31#define LOOPS_DEFAULT 1000000
32static int loops = LOOPS_DEFAULT;
33
34static const struct option options[] = {
35 OPT_INTEGER('l', "loop", &loops,
36 "Specify number of loops"),
37 OPT_END()
38};
39
40static const char * const bench_sched_pipe_usage[] = {
41 "perf bench sched pipe <options>",
42 NULL
43};
44
45int bench_sched_pipe(int argc, const char **argv,
46 const char *prefix __used)
47{
48 int pipe_1[2], pipe_2[2];
49 int m = 0, i;
50 struct timeval start, stop, diff;
51 unsigned long long result_usec = 0;
52
53 /*
54 * why does "ret" exist?
55 * discarding returned value of read(), write()
56 * causes error in building environment for perf
57 */
58 int ret, wait_stat;
59 pid_t pid, retpid;
60
61 argc = parse_options(argc, argv, options,
62 bench_sched_pipe_usage, 0);
63
64 assert(!pipe(pipe_1));
65 assert(!pipe(pipe_2));
66
67 pid = fork();
68 assert(pid >= 0);
69
70 gettimeofday(&start, NULL);
71
72 if (!pid) {
73 for (i = 0; i < loops; i++) {
74 ret = read(pipe_1[0], &m, sizeof(int));
75 ret = write(pipe_2[1], &m, sizeof(int));
76 }
77 } else {
78 for (i = 0; i < loops; i++) {
79 ret = write(pipe_1[1], &m, sizeof(int));
80 ret = read(pipe_2[0], &m, sizeof(int));
81 }
82 }
83
84 gettimeofday(&stop, NULL);
85 timersub(&stop, &start, &diff);
86
87 if (pid) {
88 retpid = waitpid(pid, &wait_stat, 0);
89 assert((retpid == pid) && WIFEXITED(wait_stat));
90 return 0;
91 }
92
93 switch (bench_format) {
94 case BENCH_FORMAT_DEFAULT:
95 printf("# Extecuted %d pipe operations between two tasks\n\n",
96 loops);
97
98 result_usec = diff.tv_sec * 1000000;
99 result_usec += diff.tv_usec;
100
101 printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
102 diff.tv_sec, diff.tv_usec/1000);
103
104 printf(" %14lf usecs/op\n",
105 (double)result_usec / (double)loops);
106 printf(" %14d ops/sec\n",
107 (int)((double)loops /
108 ((double)result_usec / (double)1000000)));
109 break;
110
111 case BENCH_FORMAT_SIMPLE:
112 printf("%lu.%03lu\n",
113 diff.tv_sec, diff.tv_usec / 1000);
114 break;
115
116 default:
117 /* reaching here is something disaster */
118 fprintf(stderr, "Unknown format:%d\n", bench_format);
119 exit(1);
120 break;
121 }
122
123 return 0;
124}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec741615814..0bf2e8f9af57 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -19,29 +19,26 @@
19#include "perf.h" 19#include "perf.h"
20#include "util/debug.h" 20#include "util/debug.h"
21 21
22#include "util/event.h"
22#include "util/parse-options.h" 23#include "util/parse-options.h"
23#include "util/parse-events.h" 24#include "util/parse-events.h"
24#include "util/thread.h" 25#include "util/thread.h"
26#include "util/sort.h"
27#include "util/hist.h"
28#include "util/data_map.h"
25 29
26static char const *input_name = "perf.data"; 30static char const *input_name = "perf.data";
27 31
28static char default_sort_order[] = "comm,symbol";
29static char *sort_order = default_sort_order;
30
31static int force; 32static int force;
32static int input;
33static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
34 33
35static int full_paths; 34static int full_paths;
36 35
37static int print_line; 36static int print_line;
38 37
39static unsigned long page_size; 38struct sym_hist {
40static unsigned long mmap_window = 32; 39 u64 sum;
41 40 u64 ip[0];
42static struct rb_root threads; 41};
43static struct thread *last_match;
44
45 42
46struct sym_ext { 43struct sym_ext {
47 struct rb_node node; 44 struct rb_node node;
@@ -49,247 +46,38 @@ struct sym_ext {
49 char *path; 46 char *path;
50}; 47};
51 48
52/* 49struct sym_priv {
53 * histogram, sorted on item, collects counts 50 struct sym_hist *hist;
54 */ 51 struct sym_ext *ext;
55
56static struct rb_root hist;
57
58struct hist_entry {
59 struct rb_node rb_node;
60
61 struct thread *thread;
62 struct map *map;
63 struct dso *dso;
64 struct symbol *sym;
65 u64 ip;
66 char level;
67
68 uint32_t count;
69};
70
71/*
72 * configurable sorting bits
73 */
74
75struct sort_entry {
76 struct list_head list;
77
78 const char *header;
79
80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
82 size_t (*print)(FILE *fp, struct hist_entry *);
83};
84
85/* --sort pid */
86
87static int64_t
88sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
89{
90 return right->thread->pid - left->thread->pid;
91}
92
93static size_t
94sort__thread_print(FILE *fp, struct hist_entry *self)
95{
96 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
97}
98
99static struct sort_entry sort_thread = {
100 .header = " Command: Pid",
101 .cmp = sort__thread_cmp,
102 .print = sort__thread_print,
103};
104
105/* --sort comm */
106
107static int64_t
108sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
109{
110 return right->thread->pid - left->thread->pid;
111}
112
113static int64_t
114sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
115{
116 char *comm_l = left->thread->comm;
117 char *comm_r = right->thread->comm;
118
119 if (!comm_l || !comm_r) {
120 if (!comm_l && !comm_r)
121 return 0;
122 else if (!comm_l)
123 return -1;
124 else
125 return 1;
126 }
127
128 return strcmp(comm_l, comm_r);
129}
130
131static size_t
132sort__comm_print(FILE *fp, struct hist_entry *self)
133{
134 return fprintf(fp, "%16s", self->thread->comm);
135}
136
137static struct sort_entry sort_comm = {
138 .header = " Command",
139 .cmp = sort__comm_cmp,
140 .collapse = sort__comm_collapse,
141 .print = sort__comm_print,
142};
143
144/* --sort dso */
145
146static int64_t
147sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
148{
149 struct dso *dso_l = left->dso;
150 struct dso *dso_r = right->dso;
151
152 if (!dso_l || !dso_r) {
153 if (!dso_l && !dso_r)
154 return 0;
155 else if (!dso_l)
156 return -1;
157 else
158 return 1;
159 }
160
161 return strcmp(dso_l->name, dso_r->name);
162}
163
164static size_t
165sort__dso_print(FILE *fp, struct hist_entry *self)
166{
167 if (self->dso)
168 return fprintf(fp, "%-25s", self->dso->name);
169
170 return fprintf(fp, "%016llx ", (u64)self->ip);
171}
172
173static struct sort_entry sort_dso = {
174 .header = "Shared Object ",
175 .cmp = sort__dso_cmp,
176 .print = sort__dso_print,
177};
178
179/* --sort symbol */
180
181static int64_t
182sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
183{
184 u64 ip_l, ip_r;
185
186 if (left->sym == right->sym)
187 return 0;
188
189 ip_l = left->sym ? left->sym->start : left->ip;
190 ip_r = right->sym ? right->sym->start : right->ip;
191
192 return (int64_t)(ip_r - ip_l);
193}
194
195static size_t
196sort__sym_print(FILE *fp, struct hist_entry *self)
197{
198 size_t ret = 0;
199
200 if (verbose)
201 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
202
203 if (self->sym) {
204 ret += fprintf(fp, "[%c] %s",
205 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
206 } else {
207 ret += fprintf(fp, "%#016llx", (u64)self->ip);
208 }
209
210 return ret;
211}
212
213static struct sort_entry sort_sym = {
214 .header = "Symbol",
215 .cmp = sort__sym_cmp,
216 .print = sort__sym_print,
217};
218
219static int sort__need_collapse = 0;
220
221struct sort_dimension {
222 const char *name;
223 struct sort_entry *entry;
224 int taken;
225}; 52};
226 53
227static struct sort_dimension sort_dimensions[] = { 54static struct symbol_conf symbol_conf = {
228 { .name = "pid", .entry = &sort_thread, }, 55 .priv_size = sizeof(struct sym_priv),
229 { .name = "comm", .entry = &sort_comm, }, 56 .try_vmlinux_path = true,
230 { .name = "dso", .entry = &sort_dso, },
231 { .name = "symbol", .entry = &sort_sym, },
232}; 57};
233 58
234static LIST_HEAD(hist_entry__sort_list); 59static const char *sym_hist_filter;
235 60
236static int sort_dimension__add(char *tok) 61static int symbol_filter(struct map *map __used, struct symbol *sym)
237{ 62{
238 unsigned int i; 63 if (sym_hist_filter == NULL ||
239 64 strcmp(sym->name, sym_hist_filter) == 0) {
240 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 65 struct sym_priv *priv = symbol__priv(sym);
241 struct sort_dimension *sd = &sort_dimensions[i]; 66 const int size = (sizeof(*priv->hist) +
242 67 (sym->end - sym->start) * sizeof(u64));
243 if (sd->taken)
244 continue;
245
246 if (strncasecmp(tok, sd->name, strlen(tok)))
247 continue;
248
249 if (sd->entry->collapse)
250 sort__need_collapse = 1;
251
252 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
253 sd->taken = 1;
254 68
69 priv->hist = malloc(size);
70 if (priv->hist)
71 memset(priv->hist, 0, size);
255 return 0; 72 return 0;
256 } 73 }
257 74 /*
258 return -ESRCH; 75 * FIXME: We should really filter it out, as we don't want to go thru symbols
259} 76 * we're not interested, and if a DSO ends up with no symbols, delete it too,
260 77 * but right now the kernel loading routines in symbol.c bail out if no symbols
261static int64_t 78 * are found, fix it later.
262hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 79 */
263{ 80 return 0;
264 struct sort_entry *se;
265 int64_t cmp = 0;
266
267 list_for_each_entry(se, &hist_entry__sort_list, list) {
268 cmp = se->cmp(left, right);
269 if (cmp)
270 break;
271 }
272
273 return cmp;
274}
275
276static int64_t
277hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
278{
279 struct sort_entry *se;
280 int64_t cmp = 0;
281
282 list_for_each_entry(se, &hist_entry__sort_list, list) {
283 int64_t (*f)(struct hist_entry *, struct hist_entry *);
284
285 f = se->collapse ?: se->cmp;
286
287 cmp = f(left, right);
288 if (cmp)
289 break;
290 }
291
292 return cmp;
293} 81}
294 82
295/* 83/*
@@ -299,380 +87,81 @@ static void hist_hit(struct hist_entry *he, u64 ip)
299{ 87{
300 unsigned int sym_size, offset; 88 unsigned int sym_size, offset;
301 struct symbol *sym = he->sym; 89 struct symbol *sym = he->sym;
90 struct sym_priv *priv;
91 struct sym_hist *h;
302 92
303 he->count++; 93 he->count++;
304 94
305 if (!sym || !sym->hist) 95 if (!sym || !he->map)
96 return;
97
98 priv = symbol__priv(sym);
99 if (!priv->hist)
306 return; 100 return;
307 101
308 sym_size = sym->end - sym->start; 102 sym_size = sym->end - sym->start;
309 offset = ip - sym->start; 103 offset = ip - sym->start;
310 104
105 if (verbose)
106 fprintf(stderr, "%s: ip=%Lx\n", __func__,
107 he->map->unmap_ip(he->map, ip));
108
311 if (offset >= sym_size) 109 if (offset >= sym_size)
312 return; 110 return;
313 111
314 sym->hist_sum++; 112 h = priv->hist;
315 sym->hist[offset]++; 113 h->sum++;
114 h->ip[offset]++;
316 115
317 if (verbose >= 3) 116 if (verbose >= 3)
318 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n", 117 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n",
319 (void *)(unsigned long)he->sym->start, 118 (void *)(unsigned long)he->sym->start,
320 he->sym->name, 119 he->sym->name,
321 (void *)(unsigned long)ip, ip - he->sym->start, 120 (void *)(unsigned long)ip, ip - he->sym->start,
322 sym->hist[offset]); 121 h->ip[offset]);
323} 122}
324 123
325static int 124static int hist_entry__add(struct addr_location *al, u64 count)
326hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
327 struct symbol *sym, u64 ip, char level)
328{ 125{
329 struct rb_node **p = &hist.rb_node; 126 bool hit;
330 struct rb_node *parent = NULL; 127 struct hist_entry *he = __hist_entry__add(al, NULL, count, &hit);
331 struct hist_entry *he; 128 if (he == NULL)
332 struct hist_entry entry = {
333 .thread = thread,
334 .map = map,
335 .dso = dso,
336 .sym = sym,
337 .ip = ip,
338 .level = level,
339 .count = 1,
340 };
341 int cmp;
342
343 while (*p != NULL) {
344 parent = *p;
345 he = rb_entry(parent, struct hist_entry, rb_node);
346
347 cmp = hist_entry__cmp(&entry, he);
348
349 if (!cmp) {
350 hist_hit(he, ip);
351
352 return 0;
353 }
354
355 if (cmp < 0)
356 p = &(*p)->rb_left;
357 else
358 p = &(*p)->rb_right;
359 }
360
361 he = malloc(sizeof(*he));
362 if (!he)
363 return -ENOMEM; 129 return -ENOMEM;
364 *he = entry; 130 hist_hit(he, al->addr);
365 rb_link_node(&he->rb_node, parent, p);
366 rb_insert_color(&he->rb_node, &hist);
367
368 return 0; 131 return 0;
369} 132}
370 133
371static void hist_entry__free(struct hist_entry *he) 134static int process_sample_event(event_t *event)
372{
373 free(he);
374}
375
376/*
377 * collapse the histogram
378 */
379
380static struct rb_root collapse_hists;
381
382static void collapse__insert_entry(struct hist_entry *he)
383{
384 struct rb_node **p = &collapse_hists.rb_node;
385 struct rb_node *parent = NULL;
386 struct hist_entry *iter;
387 int64_t cmp;
388
389 while (*p != NULL) {
390 parent = *p;
391 iter = rb_entry(parent, struct hist_entry, rb_node);
392
393 cmp = hist_entry__collapse(iter, he);
394
395 if (!cmp) {
396 iter->count += he->count;
397 hist_entry__free(he);
398 return;
399 }
400
401 if (cmp < 0)
402 p = &(*p)->rb_left;
403 else
404 p = &(*p)->rb_right;
405 }
406
407 rb_link_node(&he->rb_node, parent, p);
408 rb_insert_color(&he->rb_node, &collapse_hists);
409}
410
411static void collapse__resort(void)
412{
413 struct rb_node *next;
414 struct hist_entry *n;
415
416 if (!sort__need_collapse)
417 return;
418
419 next = rb_first(&hist);
420 while (next) {
421 n = rb_entry(next, struct hist_entry, rb_node);
422 next = rb_next(&n->rb_node);
423
424 rb_erase(&n->rb_node, &hist);
425 collapse__insert_entry(n);
426 }
427}
428
429/*
430 * reverse the map, sort on count.
431 */
432
433static struct rb_root output_hists;
434
435static void output__insert_entry(struct hist_entry *he)
436{ 135{
437 struct rb_node **p = &output_hists.rb_node; 136 struct addr_location al;
438 struct rb_node *parent = NULL;
439 struct hist_entry *iter;
440 137
441 while (*p != NULL) { 138 dump_printf("(IP, %d): %d: %p\n", event->header.misc,
442 parent = *p; 139 event->ip.pid, (void *)(long)event->ip.ip);
443 iter = rb_entry(parent, struct hist_entry, rb_node);
444 140
445 if (he->count > iter->count) 141 if (event__preprocess_sample(event, &al, symbol_filter) < 0) {
446 p = &(*p)->rb_left;
447 else
448 p = &(*p)->rb_right;
449 }
450
451 rb_link_node(&he->rb_node, parent, p);
452 rb_insert_color(&he->rb_node, &output_hists);
453}
454
455static void output__resort(void)
456{
457 struct rb_node *next;
458 struct hist_entry *n;
459 struct rb_root *tree = &hist;
460
461 if (sort__need_collapse)
462 tree = &collapse_hists;
463
464 next = rb_first(tree);
465
466 while (next) {
467 n = rb_entry(next, struct hist_entry, rb_node);
468 next = rb_next(&n->rb_node);
469
470 rb_erase(&n->rb_node, tree);
471 output__insert_entry(n);
472 }
473}
474
475static unsigned long total = 0,
476 total_mmap = 0,
477 total_comm = 0,
478 total_fork = 0,
479 total_unknown = 0;
480
481static int
482process_sample_event(event_t *event, unsigned long offset, unsigned long head)
483{
484 char level;
485 int show = 0;
486 struct dso *dso = NULL;
487 struct thread *thread;
488 u64 ip = event->ip.ip;
489 struct map *map = NULL;
490
491 thread = threads__findnew(event->ip.pid, &threads, &last_match);
492
493 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
494 (void *)(offset + head),
495 (void *)(long)(event->header.size),
496 event->header.misc,
497 event->ip.pid,
498 (void *)(long)ip);
499
500 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
501
502 if (thread == NULL) {
503 fprintf(stderr, "problem processing %d event, skipping it.\n", 142 fprintf(stderr, "problem processing %d event, skipping it.\n",
504 event->header.type); 143 event->header.type);
505 return -1; 144 return -1;
506 } 145 }
507 146
508 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 147 if (hist_entry__add(&al, 1)) {
509 show = SHOW_KERNEL; 148 fprintf(stderr, "problem incrementing symbol count, "
510 level = 'k'; 149 "skipping event\n");
511
512 dso = kernel_dso;
513
514 dump_printf(" ...... dso: %s\n", dso->name);
515
516 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
517
518 show = SHOW_USER;
519 level = '.';
520
521 map = thread__find_map(thread, ip);
522 if (map != NULL) {
523 ip = map->map_ip(map, ip);
524 dso = map->dso;
525 } else {
526 /*
527 * If this is outside of all known maps,
528 * and is a negative address, try to look it
529 * up in the kernel dso, as it might be a
530 * vsyscall (which executes in user-mode):
531 */
532 if ((long long)ip < 0)
533 dso = kernel_dso;
534 }
535 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
536
537 } else {
538 show = SHOW_HV;
539 level = 'H';
540 dump_printf(" ...... dso: [hypervisor]\n");
541 }
542
543 if (show & show_mask) {
544 struct symbol *sym = NULL;
545
546 if (dso)
547 sym = dso->find_symbol(dso, ip);
548
549 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
550 fprintf(stderr,
551 "problem incrementing symbol count, skipping event\n");
552 return -1;
553 }
554 }
555 total++;
556
557 return 0;
558}
559
560static int
561process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
562{
563 struct thread *thread;
564 struct map *map = map__new(&event->mmap, NULL, 0);
565
566 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
567
568 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
569 (void *)(offset + head),
570 (void *)(long)(event->header.size),
571 event->mmap.pid,
572 (void *)(long)event->mmap.start,
573 (void *)(long)event->mmap.len,
574 (void *)(long)event->mmap.pgoff,
575 event->mmap.filename);
576
577 if (thread == NULL || map == NULL) {
578 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
579 return 0;
580 }
581
582 thread__insert_map(thread, map);
583 total_mmap++;
584
585 return 0;
586}
587
588static int
589process_comm_event(event_t *event, unsigned long offset, unsigned long head)
590{
591 struct thread *thread;
592
593 thread = threads__findnew(event->comm.pid, &threads, &last_match);
594 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
595 (void *)(offset + head),
596 (void *)(long)(event->header.size),
597 event->comm.comm, event->comm.pid);
598
599 if (thread == NULL ||
600 thread__set_comm(thread, event->comm.comm)) {
601 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
602 return -1;
603 }
604 total_comm++;
605
606 return 0;
607}
608
609static int
610process_fork_event(event_t *event, unsigned long offset, unsigned long head)
611{
612 struct thread *thread;
613 struct thread *parent;
614
615 thread = threads__findnew(event->fork.pid, &threads, &last_match);
616 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
617 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n",
618 (void *)(offset + head),
619 (void *)(long)(event->header.size),
620 event->fork.pid, event->fork.ppid);
621
622 /*
623 * A thread clone will have the same PID for both
624 * parent and child.
625 */
626 if (thread == parent)
627 return 0;
628
629 if (!thread || !parent || thread__fork(thread, parent)) {
630 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
631 return -1;
632 }
633 total_fork++;
634
635 return 0;
636}
637
638static int
639process_event(event_t *event, unsigned long offset, unsigned long head)
640{
641 switch (event->header.type) {
642 case PERF_RECORD_SAMPLE:
643 return process_sample_event(event, offset, head);
644
645 case PERF_RECORD_MMAP:
646 return process_mmap_event(event, offset, head);
647
648 case PERF_RECORD_COMM:
649 return process_comm_event(event, offset, head);
650
651 case PERF_RECORD_FORK:
652 return process_fork_event(event, offset, head);
653 /*
654 * We dont process them right now but they are fine:
655 */
656
657 case PERF_RECORD_THROTTLE:
658 case PERF_RECORD_UNTHROTTLE:
659 return 0;
660
661 default:
662 return -1; 150 return -1;
663 } 151 }
664 152
665 return 0; 153 return 0;
666} 154}
667 155
668static int 156static int parse_line(FILE *file, struct hist_entry *he, u64 len)
669parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
670{ 157{
158 struct symbol *sym = he->sym;
671 char *line = NULL, *tmp, *tmp2; 159 char *line = NULL, *tmp, *tmp2;
672 static const char *prev_line; 160 static const char *prev_line;
673 static const char *prev_color; 161 static const char *prev_color;
674 unsigned int offset; 162 unsigned int offset;
675 size_t line_len; 163 size_t line_len;
164 u64 start;
676 s64 line_ip; 165 s64 line_ip;
677 int ret; 166 int ret;
678 char *c; 167 char *c;
@@ -709,22 +198,26 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
709 line_ip = -1; 198 line_ip = -1;
710 } 199 }
711 200
201 start = he->map->unmap_ip(he->map, sym->start);
202
712 if (line_ip != -1) { 203 if (line_ip != -1) {
713 const char *path = NULL; 204 const char *path = NULL;
714 unsigned int hits = 0; 205 unsigned int hits = 0;
715 double percent = 0.0; 206 double percent = 0.0;
716 const char *color; 207 const char *color;
717 struct sym_ext *sym_ext = sym->priv; 208 struct sym_priv *priv = symbol__priv(sym);
209 struct sym_ext *sym_ext = priv->ext;
210 struct sym_hist *h = priv->hist;
718 211
719 offset = line_ip - start; 212 offset = line_ip - start;
720 if (offset < len) 213 if (offset < len)
721 hits = sym->hist[offset]; 214 hits = h->ip[offset];
722 215
723 if (offset < len && sym_ext) { 216 if (offset < len && sym_ext) {
724 path = sym_ext[offset].path; 217 path = sym_ext[offset].path;
725 percent = sym_ext[offset].percent; 218 percent = sym_ext[offset].percent;
726 } else if (sym->hist_sum) 219 } else if (h->sum)
727 percent = 100.0 * hits / sym->hist_sum; 220 percent = 100.0 * hits / h->sum;
728 221
729 color = get_percent_color(percent); 222 color = get_percent_color(percent);
730 223
@@ -777,9 +270,10 @@ static void insert_source_line(struct sym_ext *sym_ext)
777 rb_insert_color(&sym_ext->node, &root_sym_ext); 270 rb_insert_color(&sym_ext->node, &root_sym_ext);
778} 271}
779 272
780static void free_source_line(struct symbol *sym, int len) 273static void free_source_line(struct hist_entry *he, int len)
781{ 274{
782 struct sym_ext *sym_ext = sym->priv; 275 struct sym_priv *priv = symbol__priv(he->sym);
276 struct sym_ext *sym_ext = priv->ext;
783 int i; 277 int i;
784 278
785 if (!sym_ext) 279 if (!sym_ext)
@@ -789,26 +283,30 @@ static void free_source_line(struct symbol *sym, int len)
789 free(sym_ext[i].path); 283 free(sym_ext[i].path);
790 free(sym_ext); 284 free(sym_ext);
791 285
792 sym->priv = NULL; 286 priv->ext = NULL;
793 root_sym_ext = RB_ROOT; 287 root_sym_ext = RB_ROOT;
794} 288}
795 289
796/* Get the filename:line for the colored entries */ 290/* Get the filename:line for the colored entries */
797static void 291static void
798get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 292get_source_line(struct hist_entry *he, int len, const char *filename)
799{ 293{
294 struct symbol *sym = he->sym;
295 u64 start;
800 int i; 296 int i;
801 char cmd[PATH_MAX * 2]; 297 char cmd[PATH_MAX * 2];
802 struct sym_ext *sym_ext; 298 struct sym_ext *sym_ext;
299 struct sym_priv *priv = symbol__priv(sym);
300 struct sym_hist *h = priv->hist;
803 301
804 if (!sym->hist_sum) 302 if (!h->sum)
805 return; 303 return;
806 304
807 sym->priv = calloc(len, sizeof(struct sym_ext)); 305 sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
808 if (!sym->priv) 306 if (!priv->ext)
809 return; 307 return;
810 308
811 sym_ext = sym->priv; 309 start = he->map->unmap_ip(he->map, sym->start);
812 310
813 for (i = 0; i < len; i++) { 311 for (i = 0; i < len; i++) {
814 char *path = NULL; 312 char *path = NULL;
@@ -816,7 +314,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
816 u64 offset; 314 u64 offset;
817 FILE *fp; 315 FILE *fp;
818 316
819 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 317 sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
820 if (sym_ext[i].percent <= 0.5) 318 if (sym_ext[i].percent <= 0.5)
821 continue; 319 continue;
822 320
@@ -870,33 +368,34 @@ static void print_summary(const char *filename)
870 } 368 }
871} 369}
872 370
873static void annotate_sym(struct dso *dso, struct symbol *sym) 371static void annotate_sym(struct hist_entry *he)
874{ 372{
875 const char *filename = dso->name, *d_filename; 373 struct map *map = he->map;
876 u64 start, end, len; 374 struct dso *dso = map->dso;
375 struct symbol *sym = he->sym;
376 const char *filename = dso->long_name, *d_filename;
377 u64 len;
877 char command[PATH_MAX*2]; 378 char command[PATH_MAX*2];
878 FILE *file; 379 FILE *file;
879 380
880 if (!filename) 381 if (!filename)
881 return; 382 return;
882 if (sym->module) 383
883 filename = sym->module->path; 384 if (verbose)
884 else if (dso == kernel_dso) 385 fprintf(stderr, "%s: filename=%s, sym=%s, start=%Lx, end=%Lx\n",
885 filename = vmlinux_name; 386 __func__, filename, sym->name,
886 387 map->unmap_ip(map, sym->start),
887 start = sym->obj_start; 388 map->unmap_ip(map, sym->end));
888 if (!start) 389
889 start = sym->start;
890 if (full_paths) 390 if (full_paths)
891 d_filename = filename; 391 d_filename = filename;
892 else 392 else
893 d_filename = basename(filename); 393 d_filename = basename(filename);
894 394
895 end = start + sym->end - sym->start + 1;
896 len = sym->end - sym->start; 395 len = sym->end - sym->start;
897 396
898 if (print_line) { 397 if (print_line) {
899 get_source_line(sym, start, len, filename); 398 get_source_line(he, len, filename);
900 print_summary(filename); 399 print_summary(filename);
901 } 400 }
902 401
@@ -905,10 +404,12 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
905 printf("------------------------------------------------\n"); 404 printf("------------------------------------------------\n");
906 405
907 if (verbose >= 2) 406 if (verbose >= 2)
908 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 407 printf("annotating [%p] %30s : [%p] %30s\n",
408 dso, dso->long_name, sym, sym->name);
909 409
910 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 410 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
911 (u64)start, (u64)end, filename, filename); 411 map->unmap_ip(map, sym->start), map->unmap_ip(map, sym->end),
412 filename, filename);
912 413
913 if (verbose >= 3) 414 if (verbose >= 3)
914 printf("doing: %s\n", command); 415 printf("doing: %s\n", command);
@@ -918,159 +419,78 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
918 return; 419 return;
919 420
920 while (!feof(file)) { 421 while (!feof(file)) {
921 if (parse_line(file, sym, start, len) < 0) 422 if (parse_line(file, he, len) < 0)
922 break; 423 break;
923 } 424 }
924 425
925 pclose(file); 426 pclose(file);
926 if (print_line) 427 if (print_line)
927 free_source_line(sym, len); 428 free_source_line(he, len);
928} 429}
929 430
930static void find_annotations(void) 431static void find_annotations(void)
931{ 432{
932 struct rb_node *nd; 433 struct rb_node *nd;
933 struct dso *dso;
934 int count = 0;
935
936 list_for_each_entry(dso, &dsos, node) {
937
938 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) {
939 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
940
941 if (sym->hist) {
942 annotate_sym(dso, sym);
943 count++;
944 }
945 }
946 }
947
948 if (!count)
949 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter);
950}
951
952static int __cmd_annotate(void)
953{
954 int ret, rc = EXIT_FAILURE;
955 unsigned long offset = 0;
956 unsigned long head = 0;
957 struct stat input_stat;
958 event_t *event;
959 uint32_t size;
960 char *buf;
961
962 register_idle_thread(&threads, &last_match);
963
964 input = open(input_name, O_RDONLY);
965 if (input < 0) {
966 perror("failed to open file");
967 exit(-1);
968 }
969
970 ret = fstat(input, &input_stat);
971 if (ret < 0) {
972 perror("failed to stat file");
973 exit(-1);
974 }
975
976 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
977 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
978 exit(-1);
979 }
980
981 if (!input_stat.st_size) {
982 fprintf(stderr, "zero-sized file, nothing to do!\n");
983 exit(0);
984 }
985
986 if (load_kernel() < 0) {
987 perror("failed to load kernel symbols");
988 return EXIT_FAILURE;
989 }
990
991remap:
992 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
993 MAP_SHARED, input, offset);
994 if (buf == MAP_FAILED) {
995 perror("failed to mmap file");
996 exit(-1);
997 }
998
999more:
1000 event = (event_t *)(buf + head);
1001 434
1002 size = event->header.size; 435 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1003 if (!size) 436 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
1004 size = 8; 437 struct sym_priv *priv;
1005 438
1006 if (head + event->header.size >= page_size * mmap_window) { 439 if (he->sym == NULL)
1007 unsigned long shift = page_size * (head / page_size); 440 continue;
1008 int munmap_ret;
1009
1010 munmap_ret = munmap(buf, page_size * mmap_window);
1011 assert(munmap_ret == 0);
1012
1013 offset += shift;
1014 head -= shift;
1015 goto remap;
1016 }
1017
1018 size = event->header.size;
1019
1020 dump_printf("%p [%p]: event: %d\n",
1021 (void *)(offset + head),
1022 (void *)(long)event->header.size,
1023 event->header.type);
1024
1025 if (!size || process_event(event, offset, head) < 0) {
1026
1027 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1028 (void *)(offset + head),
1029 (void *)(long)(event->header.size),
1030 event->header.type);
1031 441
1032 total_unknown++; 442 priv = symbol__priv(he->sym);
443 if (priv->hist == NULL)
444 continue;
1033 445
446 annotate_sym(he);
1034 /* 447 /*
1035 * assume we lost track of the stream, check alignment, and 448 * Since we have a hist_entry per IP for the same symbol, free
1036 * increment a single u64 in the hope to catch on again 'soon'. 449 * he->sym->hist to signal we already processed this symbol.
1037 */ 450 */
1038 451 free(priv->hist);
1039 if (unlikely(head & 7)) 452 priv->hist = NULL;
1040 head &= ~7ULL;
1041
1042 size = 8;
1043 } 453 }
454}
1044 455
1045 head += size; 456static struct perf_file_handler file_handler = {
457 .process_sample_event = process_sample_event,
458 .process_mmap_event = event__process_mmap,
459 .process_comm_event = event__process_comm,
460 .process_fork_event = event__process_task,
461};
1046 462
1047 if (offset + head < (unsigned long)input_stat.st_size) 463static int __cmd_annotate(void)
1048 goto more; 464{
465 struct perf_header *header;
466 struct thread *idle;
467 int ret;
1049 468
1050 rc = EXIT_SUCCESS; 469 idle = register_idle_thread();
1051 close(input); 470 register_perf_file_handler(&file_handler);
1052 471
1053 dump_printf(" IP events: %10ld\n", total); 472 ret = mmap_dispatch_perf_file(&header, input_name, 0, 0,
1054 dump_printf(" mmap events: %10ld\n", total_mmap); 473 &event__cwdlen, &event__cwd);
1055 dump_printf(" comm events: %10ld\n", total_comm); 474 if (ret)
1056 dump_printf(" fork events: %10ld\n", total_fork); 475 return ret;
1057 dump_printf(" unknown events: %10ld\n", total_unknown);
1058 476
1059 if (dump_trace) 477 if (dump_trace) {
478 event__print_totals();
1060 return 0; 479 return 0;
480 }
1061 481
1062 if (verbose >= 3) 482 if (verbose > 3)
1063 threads__fprintf(stdout, &threads); 483 threads__fprintf(stdout);
1064 484
1065 if (verbose >= 2) 485 if (verbose > 2)
1066 dsos__fprintf(stdout); 486 dsos__fprintf(stdout);
1067 487
1068 collapse__resort(); 488 collapse__resort();
1069 output__resort(); 489 output__resort(event__total[0]);
1070 490
1071 find_annotations(); 491 find_annotations();
1072 492
1073 return rc; 493 return ret;
1074} 494}
1075 495
1076static const char * const annotate_usage[] = { 496static const char * const annotate_usage[] = {
@@ -1088,8 +508,9 @@ static const struct option options[] = {
1088 "be more verbose (show symbol address, etc)"), 508 "be more verbose (show symbol address, etc)"),
1089 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 509 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1090 "dump raw trace in ASCII"), 510 "dump raw trace in ASCII"),
1091 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 511 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1092 OPT_BOOLEAN('m', "modules", &modules, 512 "file", "vmlinux pathname"),
513 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
1093 "load module symbols - WARNING: use only with -k and LIVE kernel"), 514 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1094 OPT_BOOLEAN('l', "print-line", &print_line, 515 OPT_BOOLEAN('l', "print-line", &print_line,
1095 "print matching source lines (may be slow)"), 516 "print matching source lines (may be slow)"),
@@ -1115,9 +536,8 @@ static void setup_sorting(void)
1115 536
1116int cmd_annotate(int argc, const char **argv, const char *prefix __used) 537int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1117{ 538{
1118 symbol__init(); 539 if (symbol__init(&symbol_conf) < 0)
1119 540 return -1;
1120 page_size = getpagesize();
1121 541
1122 argc = parse_options(argc, argv, options, annotate_usage, 0); 542 argc = parse_options(argc, argv, options, annotate_usage, 0);
1123 543
@@ -1134,10 +554,13 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1134 sym_hist_filter = argv[0]; 554 sym_hist_filter = argv[0];
1135 } 555 }
1136 556
1137 if (!sym_hist_filter)
1138 usage_with_options(annotate_usage, options);
1139
1140 setup_pager(); 557 setup_pager();
1141 558
559 if (field_sep && *field_sep == '.') {
560 fputs("'.' is the only non valid --field-separator argument\n",
561 stderr);
562 exit(129);
563 }
564
1142 return __cmd_annotate(); 565 return __cmd_annotate();
1143} 566}
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
new file mode 100644
index 000000000000..e043eb83092a
--- /dev/null
+++ b/tools/perf/builtin-bench.c
@@ -0,0 +1,196 @@
1/*
2 *
3 * builtin-bench.c
4 *
5 * General benchmarking subsystem provided by perf
6 *
7 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
8 *
9 */
10
11/*
12 *
13 * Available subsystem list:
14 * sched ... scheduler and IPC mechanism
15 * mem ... memory access performance
16 *
17 */
18
19#include "perf.h"
20#include "util/util.h"
21#include "util/parse-options.h"
22#include "builtin.h"
23#include "bench/bench.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29struct bench_suite {
30 const char *name;
31 const char *summary;
32 int (*fn)(int, const char **, const char *);
33};
34
35static struct bench_suite sched_suites[] = {
36 { "messaging",
37 "Benchmark for scheduler and IPC mechanisms",
38 bench_sched_messaging },
39 { "pipe",
40 "Flood of communication over pipe() between two processes",
41 bench_sched_pipe },
42 { NULL,
43 NULL,
44 NULL }
45};
46
47static struct bench_suite mem_suites[] = {
48 { "memcpy",
49 "Simple memory copy in various ways",
50 bench_mem_memcpy },
51 { NULL,
52 NULL,
53 NULL }
54};
55
56struct bench_subsys {
57 const char *name;
58 const char *summary;
59 struct bench_suite *suites;
60};
61
62static struct bench_subsys subsystems[] = {
63 { "sched",
64 "scheduler and IPC mechanism",
65 sched_suites },
66 { "mem",
67 "memory access performance",
68 mem_suites },
69 { NULL,
70 NULL,
71 NULL }
72};
73
74static void dump_suites(int subsys_index)
75{
76 int i;
77
78 printf("List of available suites for %s...\n\n",
79 subsystems[subsys_index].name);
80
81 for (i = 0; subsystems[subsys_index].suites[i].name; i++)
82 printf("\t%s: %s\n",
83 subsystems[subsys_index].suites[i].name,
84 subsystems[subsys_index].suites[i].summary);
85
86 printf("\n");
87 return;
88}
89
90static char *bench_format_str;
91int bench_format = BENCH_FORMAT_DEFAULT;
92
93static const struct option bench_options[] = {
94 OPT_STRING('f', "format", &bench_format_str, "default",
95 "Specify format style"),
96 OPT_END()
97};
98
99static const char * const bench_usage[] = {
100 "perf bench [<common options>] <subsystem> <suite> [<options>]",
101 NULL
102};
103
104static void print_usage(void)
105{
106 int i;
107
108 printf("Usage: \n");
109 for (i = 0; bench_usage[i]; i++)
110 printf("\t%s\n", bench_usage[i]);
111 printf("\n");
112
113 printf("List of available subsystems...\n\n");
114
115 for (i = 0; subsystems[i].name; i++)
116 printf("\t%s: %s\n",
117 subsystems[i].name, subsystems[i].summary);
118 printf("\n");
119}
120
121static int bench_str2int(char *str)
122{
123 if (!str)
124 return BENCH_FORMAT_DEFAULT;
125
126 if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR))
127 return BENCH_FORMAT_DEFAULT;
128 else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR))
129 return BENCH_FORMAT_SIMPLE;
130
131 return BENCH_FORMAT_UNKNOWN;
132}
133
134int cmd_bench(int argc, const char **argv, const char *prefix __used)
135{
136 int i, j, status = 0;
137
138 if (argc < 2) {
139 /* No subsystem specified. */
140 print_usage();
141 goto end;
142 }
143
144 argc = parse_options(argc, argv, bench_options, bench_usage,
145 PARSE_OPT_STOP_AT_NON_OPTION);
146
147 bench_format = bench_str2int(bench_format_str);
148 if (bench_format == BENCH_FORMAT_UNKNOWN) {
149 printf("Unknown format descriptor:%s\n", bench_format_str);
150 goto end;
151 }
152
153 if (argc < 1) {
154 print_usage();
155 goto end;
156 }
157
158 for (i = 0; subsystems[i].name; i++) {
159 if (strcmp(subsystems[i].name, argv[0]))
160 continue;
161
162 if (argc < 2) {
163 /* No suite specified. */
164 dump_suites(i);
165 goto end;
166 }
167
168 for (j = 0; subsystems[i].suites[j].name; j++) {
169 if (strcmp(subsystems[i].suites[j].name, argv[1]))
170 continue;
171
172 if (bench_format == BENCH_FORMAT_DEFAULT)
173 printf("# Running %s/%s benchmark...\n",
174 subsystems[i].name,
175 subsystems[i].suites[j].name);
176 status = subsystems[i].suites[j].fn(argc - 1,
177 argv + 1, prefix);
178 goto end;
179 }
180
181 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
182 dump_suites(i);
183 goto end;
184 }
185
186 printf("Unknown suite:%s for %s\n", argv[1], argv[0]);
187 status = 1;
188 goto end;
189 }
190
191 printf("Unknown subsystem:%s\n", argv[0]);
192 status = 1;
193
194end:
195 return status;
196}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
new file mode 100644
index 000000000000..7dee9d19ab7a
--- /dev/null
+++ b/tools/perf/builtin-buildid-list.c
@@ -0,0 +1,116 @@
1/*
2 * builtin-buildid-list.c
3 *
4 * Builtin buildid-list command: list buildids in perf.data
5 *
6 * Copyright (C) 2009, Red Hat Inc.
7 * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */
9#include "builtin.h"
10#include "perf.h"
11#include "util/cache.h"
12#include "util/data_map.h"
13#include "util/debug.h"
14#include "util/header.h"
15#include "util/parse-options.h"
16#include "util/symbol.h"
17
18static char const *input_name = "perf.data";
19static int force;
20
21static const char *const buildid_list_usage[] = {
22 "perf report [<options>]",
23 NULL
24};
25
26static const struct option options[] = {
27 OPT_STRING('i', "input", &input_name, "file",
28 "input file name"),
29 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
30 OPT_BOOLEAN('v', "verbose", &verbose,
31 "be more verbose"),
32 OPT_END()
33};
34
35static int perf_file_section__process_buildids(struct perf_file_section *self,
36 int feat, int fd)
37{
38 if (feat != HEADER_BUILD_ID)
39 return 0;
40
41 if (lseek(fd, self->offset, SEEK_SET) < 0) {
42 pr_warning("Failed to lseek to %Ld offset for buildids!\n",
43 self->offset);
44 return -1;
45 }
46
47 if (perf_header__read_build_ids(fd, self->offset, self->size)) {
48 pr_warning("Failed to read buildids!\n");
49 return -1;
50 }
51
52 return 0;
53}
54
55static int __cmd_buildid_list(void)
56{
57 int err = -1;
58 struct perf_header *header;
59 struct perf_file_header f_header;
60 struct stat input_stat;
61 int input = open(input_name, O_RDONLY);
62
63 if (input < 0) {
64 pr_err("failed to open file: %s", input_name);
65 if (!strcmp(input_name, "perf.data"))
66 pr_err(" (try 'perf record' first)");
67 pr_err("\n");
68 goto out;
69 }
70
71 err = fstat(input, &input_stat);
72 if (err < 0) {
73 perror("failed to stat file");
74 goto out_close;
75 }
76
77 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
78 pr_err("file %s not owned by current user or root\n",
79 input_name);
80 goto out_close;
81 }
82
83 if (!input_stat.st_size) {
84 pr_info("zero-sized file, nothing to do!\n");
85 goto out_close;
86 }
87
88 err = -1;
89 header = perf_header__new();
90 if (header == NULL)
91 goto out_close;
92
93 if (perf_file_header__read(&f_header, header, input) < 0) {
94 pr_warning("incompatible file format");
95 goto out_close;
96 }
97
98 err = perf_header__process_sections(header, input,
99 perf_file_section__process_buildids);
100
101 if (err < 0)
102 goto out_close;
103
104 dsos__fprintf_buildid(stdout);
105out_close:
106 close(input);
107out:
108 return err;
109}
110
111int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
112{
113 argc = parse_options(argc, argv, options, buildid_list_usage, 0);
114 setup_pager();
115 return __cmd_buildid_list();
116}
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 4fb8734a796e..9f810b17c25c 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -61,8 +61,7 @@ static const char *get_man_viewer_info(const char *name)
61{ 61{
62 struct man_viewer_info_list *viewer; 62 struct man_viewer_info_list *viewer;
63 63
64 for (viewer = man_viewer_info_list; viewer; viewer = viewer->next) 64 for (viewer = man_viewer_info_list; viewer; viewer = viewer->next) {
65 {
66 if (!strcasecmp(name, viewer->name)) 65 if (!strcasecmp(name, viewer->name))
67 return viewer->info; 66 return viewer->info;
68 } 67 }
@@ -115,7 +114,7 @@ static int check_emacsclient_version(void)
115 return 0; 114 return 0;
116} 115}
117 116
118static void exec_woman_emacs(const char* path, const char *page) 117static void exec_woman_emacs(const char *path, const char *page)
119{ 118{
120 if (!check_emacsclient_version()) { 119 if (!check_emacsclient_version()) {
121 /* This works only with emacsclient version >= 22. */ 120 /* This works only with emacsclient version >= 22. */
@@ -129,7 +128,7 @@ static void exec_woman_emacs(const char* path, const char *page)
129 } 128 }
130} 129}
131 130
132static void exec_man_konqueror(const char* path, const char *page) 131static void exec_man_konqueror(const char *path, const char *page)
133{ 132{
134 const char *display = getenv("DISPLAY"); 133 const char *display = getenv("DISPLAY");
135 if (display && *display) { 134 if (display && *display) {
@@ -157,7 +156,7 @@ static void exec_man_konqueror(const char* path, const char *page)
157 } 156 }
158} 157}
159 158
160static void exec_man_man(const char* path, const char *page) 159static void exec_man_man(const char *path, const char *page)
161{ 160{
162 if (!path) 161 if (!path)
163 path = "man"; 162 path = "man";
@@ -180,7 +179,7 @@ static void add_man_viewer(const char *name)
180 179
181 while (*p) 180 while (*p)
182 p = &((*p)->next); 181 p = &((*p)->next);
183 *p = calloc(1, (sizeof(**p) + len + 1)); 182 *p = zalloc(sizeof(**p) + len + 1);
184 strncpy((*p)->name, name, len); 183 strncpy((*p)->name, name, len);
185} 184}
186 185
@@ -195,7 +194,7 @@ static void do_add_man_viewer_info(const char *name,
195 size_t len, 194 size_t len,
196 const char *value) 195 const char *value)
197{ 196{
198 struct man_viewer_info_list *new = calloc(1, sizeof(*new) + len + 1); 197 struct man_viewer_info_list *new = zalloc(sizeof(*new) + len + 1);
199 198
200 strncpy(new->name, name, len); 199 strncpy(new->name, name, len);
201 new->info = strdup(value); 200 new->info = strdup(value);
@@ -364,9 +363,8 @@ static void show_man_page(const char *perf_cmd)
364 363
365 setup_man_path(); 364 setup_man_path();
366 for (viewer = man_viewer_list; viewer; viewer = viewer->next) 365 for (viewer = man_viewer_list; viewer; viewer = viewer->next)
367 {
368 exec_viewer(viewer->name, page); /* will return when unable */ 366 exec_viewer(viewer->name, page); /* will return when unable */
369 } 367
370 if (fallback) 368 if (fallback)
371 exec_viewer(fallback, page); 369 exec_viewer(fallback, page);
372 exec_viewer("man", page); 370 exec_viewer("man", page);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
new file mode 100644
index 000000000000..047fef74bd52
--- /dev/null
+++ b/tools/perf/builtin-kmem.c
@@ -0,0 +1,807 @@
1#include "builtin.h"
2#include "perf.h"
3
4#include "util/util.h"
5#include "util/cache.h"
6#include "util/symbol.h"
7#include "util/thread.h"
8#include "util/header.h"
9
10#include "util/parse-options.h"
11#include "util/trace-event.h"
12
13#include "util/debug.h"
14#include "util/data_map.h"
15
16#include <linux/rbtree.h>
17
18struct alloc_stat;
19typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
20
21static char const *input_name = "perf.data";
22
23static struct perf_header *header;
24static u64 sample_type;
25
26static int alloc_flag;
27static int caller_flag;
28
29static int alloc_lines = -1;
30static int caller_lines = -1;
31
32static bool raw_ip;
33
34static char default_sort_order[] = "frag,hit,bytes";
35
36static int *cpunode_map;
37static int max_cpu_num;
38
39struct alloc_stat {
40 u64 call_site;
41 u64 ptr;
42 u64 bytes_req;
43 u64 bytes_alloc;
44 u32 hit;
45 u32 pingpong;
46
47 short alloc_cpu;
48
49 struct rb_node node;
50};
51
52static struct rb_root root_alloc_stat;
53static struct rb_root root_alloc_sorted;
54static struct rb_root root_caller_stat;
55static struct rb_root root_caller_sorted;
56
57static unsigned long total_requested, total_allocated;
58static unsigned long nr_allocs, nr_cross_allocs;
59
60struct raw_event_sample {
61 u32 size;
62 char data[0];
63};
64
65#define PATH_SYS_NODE "/sys/devices/system/node"
66
67static void init_cpunode_map(void)
68{
69 FILE *fp;
70 int i;
71
72 fp = fopen("/sys/devices/system/cpu/kernel_max", "r");
73 if (!fp) {
74 max_cpu_num = 4096;
75 return;
76 }
77
78 if (fscanf(fp, "%d", &max_cpu_num) < 1)
79 die("Failed to read 'kernel_max' from sysfs");
80 max_cpu_num++;
81
82 cpunode_map = calloc(max_cpu_num, sizeof(int));
83 if (!cpunode_map)
84 die("calloc");
85 for (i = 0; i < max_cpu_num; i++)
86 cpunode_map[i] = -1;
87 fclose(fp);
88}
89
90static void setup_cpunode_map(void)
91{
92 struct dirent *dent1, *dent2;
93 DIR *dir1, *dir2;
94 unsigned int cpu, mem;
95 char buf[PATH_MAX];
96
97 init_cpunode_map();
98
99 dir1 = opendir(PATH_SYS_NODE);
100 if (!dir1)
101 return;
102
103 while (true) {
104 dent1 = readdir(dir1);
105 if (!dent1)
106 break;
107
108 if (sscanf(dent1->d_name, "node%u", &mem) < 1)
109 continue;
110
111 snprintf(buf, PATH_MAX, "%s/%s", PATH_SYS_NODE, dent1->d_name);
112 dir2 = opendir(buf);
113 if (!dir2)
114 continue;
115 while (true) {
116 dent2 = readdir(dir2);
117 if (!dent2)
118 break;
119 if (sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
120 continue;
121 cpunode_map[cpu] = mem;
122 }
123 }
124}
125
126static void insert_alloc_stat(unsigned long call_site, unsigned long ptr,
127 int bytes_req, int bytes_alloc, int cpu)
128{
129 struct rb_node **node = &root_alloc_stat.rb_node;
130 struct rb_node *parent = NULL;
131 struct alloc_stat *data = NULL;
132
133 while (*node) {
134 parent = *node;
135 data = rb_entry(*node, struct alloc_stat, node);
136
137 if (ptr > data->ptr)
138 node = &(*node)->rb_right;
139 else if (ptr < data->ptr)
140 node = &(*node)->rb_left;
141 else
142 break;
143 }
144
145 if (data && data->ptr == ptr) {
146 data->hit++;
147 data->bytes_req += bytes_req;
148 data->bytes_alloc += bytes_req;
149 } else {
150 data = malloc(sizeof(*data));
151 if (!data)
152 die("malloc");
153 data->ptr = ptr;
154 data->pingpong = 0;
155 data->hit = 1;
156 data->bytes_req = bytes_req;
157 data->bytes_alloc = bytes_alloc;
158
159 rb_link_node(&data->node, parent, node);
160 rb_insert_color(&data->node, &root_alloc_stat);
161 }
162 data->call_site = call_site;
163 data->alloc_cpu = cpu;
164}
165
166static void insert_caller_stat(unsigned long call_site,
167 int bytes_req, int bytes_alloc)
168{
169 struct rb_node **node = &root_caller_stat.rb_node;
170 struct rb_node *parent = NULL;
171 struct alloc_stat *data = NULL;
172
173 while (*node) {
174 parent = *node;
175 data = rb_entry(*node, struct alloc_stat, node);
176
177 if (call_site > data->call_site)
178 node = &(*node)->rb_right;
179 else if (call_site < data->call_site)
180 node = &(*node)->rb_left;
181 else
182 break;
183 }
184
185 if (data && data->call_site == call_site) {
186 data->hit++;
187 data->bytes_req += bytes_req;
188 data->bytes_alloc += bytes_req;
189 } else {
190 data = malloc(sizeof(*data));
191 if (!data)
192 die("malloc");
193 data->call_site = call_site;
194 data->pingpong = 0;
195 data->hit = 1;
196 data->bytes_req = bytes_req;
197 data->bytes_alloc = bytes_alloc;
198
199 rb_link_node(&data->node, parent, node);
200 rb_insert_color(&data->node, &root_caller_stat);
201 }
202}
203
204static void process_alloc_event(struct raw_event_sample *raw,
205 struct event *event,
206 int cpu,
207 u64 timestamp __used,
208 struct thread *thread __used,
209 int node)
210{
211 unsigned long call_site;
212 unsigned long ptr;
213 int bytes_req;
214 int bytes_alloc;
215 int node1, node2;
216
217 ptr = raw_field_value(event, "ptr", raw->data);
218 call_site = raw_field_value(event, "call_site", raw->data);
219 bytes_req = raw_field_value(event, "bytes_req", raw->data);
220 bytes_alloc = raw_field_value(event, "bytes_alloc", raw->data);
221
222 insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu);
223 insert_caller_stat(call_site, bytes_req, bytes_alloc);
224
225 total_requested += bytes_req;
226 total_allocated += bytes_alloc;
227
228 if (node) {
229 node1 = cpunode_map[cpu];
230 node2 = raw_field_value(event, "node", raw->data);
231 if (node1 != node2)
232 nr_cross_allocs++;
233 }
234 nr_allocs++;
235}
236
237static int ptr_cmp(struct alloc_stat *, struct alloc_stat *);
238static int callsite_cmp(struct alloc_stat *, struct alloc_stat *);
239
240static struct alloc_stat *search_alloc_stat(unsigned long ptr,
241 unsigned long call_site,
242 struct rb_root *root,
243 sort_fn_t sort_fn)
244{
245 struct rb_node *node = root->rb_node;
246 struct alloc_stat key = { .ptr = ptr, .call_site = call_site };
247
248 while (node) {
249 struct alloc_stat *data;
250 int cmp;
251
252 data = rb_entry(node, struct alloc_stat, node);
253
254 cmp = sort_fn(&key, data);
255 if (cmp < 0)
256 node = node->rb_left;
257 else if (cmp > 0)
258 node = node->rb_right;
259 else
260 return data;
261 }
262 return NULL;
263}
264
265static void process_free_event(struct raw_event_sample *raw,
266 struct event *event,
267 int cpu,
268 u64 timestamp __used,
269 struct thread *thread __used)
270{
271 unsigned long ptr;
272 struct alloc_stat *s_alloc, *s_caller;
273
274 ptr = raw_field_value(event, "ptr", raw->data);
275
276 s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp);
277 if (!s_alloc)
278 return;
279
280 if (cpu != s_alloc->alloc_cpu) {
281 s_alloc->pingpong++;
282
283 s_caller = search_alloc_stat(0, s_alloc->call_site,
284 &root_caller_stat, callsite_cmp);
285 assert(s_caller);
286 s_caller->pingpong++;
287 }
288 s_alloc->alloc_cpu = -1;
289}
290
291static void
292process_raw_event(event_t *raw_event __used, void *more_data,
293 int cpu, u64 timestamp, struct thread *thread)
294{
295 struct raw_event_sample *raw = more_data;
296 struct event *event;
297 int type;
298
299 type = trace_parse_common_type(raw->data);
300 event = trace_find_event(type);
301
302 if (!strcmp(event->name, "kmalloc") ||
303 !strcmp(event->name, "kmem_cache_alloc")) {
304 process_alloc_event(raw, event, cpu, timestamp, thread, 0);
305 return;
306 }
307
308 if (!strcmp(event->name, "kmalloc_node") ||
309 !strcmp(event->name, "kmem_cache_alloc_node")) {
310 process_alloc_event(raw, event, cpu, timestamp, thread, 1);
311 return;
312 }
313
314 if (!strcmp(event->name, "kfree") ||
315 !strcmp(event->name, "kmem_cache_free")) {
316 process_free_event(raw, event, cpu, timestamp, thread);
317 return;
318 }
319}
320
321static int process_sample_event(event_t *event)
322{
323 u64 ip = event->ip.ip;
324 u64 timestamp = -1;
325 u32 cpu = -1;
326 u64 period = 1;
327 void *more_data = event->ip.__more_data;
328 struct thread *thread = threads__findnew(event->ip.pid);
329
330 if (sample_type & PERF_SAMPLE_TIME) {
331 timestamp = *(u64 *)more_data;
332 more_data += sizeof(u64);
333 }
334
335 if (sample_type & PERF_SAMPLE_CPU) {
336 cpu = *(u32 *)more_data;
337 more_data += sizeof(u32);
338 more_data += sizeof(u32); /* reserved */
339 }
340
341 if (sample_type & PERF_SAMPLE_PERIOD) {
342 period = *(u64 *)more_data;
343 more_data += sizeof(u64);
344 }
345
346 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
347 event->header.misc,
348 event->ip.pid, event->ip.tid,
349 (void *)(long)ip,
350 (long long)period);
351
352 if (thread == NULL) {
353 pr_debug("problem processing %d event, skipping it.\n",
354 event->header.type);
355 return -1;
356 }
357
358 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
359
360 process_raw_event(event, more_data, cpu, timestamp, thread);
361
362 return 0;
363}
364
365static int sample_type_check(u64 type)
366{
367 sample_type = type;
368
369 if (!(sample_type & PERF_SAMPLE_RAW)) {
370 fprintf(stderr,
371 "No trace sample to read. Did you call perf record "
372 "without -R?");
373 return -1;
374 }
375
376 return 0;
377}
378
379static struct perf_file_handler file_handler = {
380 .process_sample_event = process_sample_event,
381 .process_comm_event = event__process_comm,
382 .sample_type_check = sample_type_check,
383};
384
385static int read_events(void)
386{
387 register_idle_thread();
388 register_perf_file_handler(&file_handler);
389
390 return mmap_dispatch_perf_file(&header, input_name, 0, 0,
391 &event__cwdlen, &event__cwd);
392}
393
394static double fragmentation(unsigned long n_req, unsigned long n_alloc)
395{
396 if (n_alloc == 0)
397 return 0.0;
398 else
399 return 100.0 - (100.0 * n_req / n_alloc);
400}
401
402static void __print_result(struct rb_root *root, int n_lines, int is_caller)
403{
404 struct rb_node *next;
405
406 printf("%.102s\n", graph_dotted_line);
407 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr");
408 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n");
409 printf("%.102s\n", graph_dotted_line);
410
411 next = rb_first(root);
412
413 while (next && n_lines--) {
414 struct alloc_stat *data = rb_entry(next, struct alloc_stat,
415 node);
416 struct symbol *sym = NULL;
417 char buf[BUFSIZ];
418 u64 addr;
419
420 if (is_caller) {
421 addr = data->call_site;
422 if (!raw_ip)
423 sym = thread__find_function(kthread, addr, NULL);
424 } else
425 addr = data->ptr;
426
427 if (sym != NULL)
428 snprintf(buf, sizeof(buf), "%s+%Lx", sym->name,
429 addr - sym->start);
430 else
431 snprintf(buf, sizeof(buf), "%#Lx", addr);
432 printf(" %-34s |", buf);
433
434 printf(" %9llu/%-5lu | %9llu/%-5lu | %6lu | %8lu | %6.3f%%\n",
435 (unsigned long long)data->bytes_alloc,
436 (unsigned long)data->bytes_alloc / data->hit,
437 (unsigned long long)data->bytes_req,
438 (unsigned long)data->bytes_req / data->hit,
439 (unsigned long)data->hit,
440 (unsigned long)data->pingpong,
441 fragmentation(data->bytes_req, data->bytes_alloc));
442
443 next = rb_next(next);
444 }
445
446 if (n_lines == -1)
447 printf(" ... | ... | ... | ... | ... | ... \n");
448
449 printf("%.102s\n", graph_dotted_line);
450}
451
452static void print_summary(void)
453{
454 printf("\nSUMMARY\n=======\n");
455 printf("Total bytes requested: %lu\n", total_requested);
456 printf("Total bytes allocated: %lu\n", total_allocated);
457 printf("Total bytes wasted on internal fragmentation: %lu\n",
458 total_allocated - total_requested);
459 printf("Internal fragmentation: %f%%\n",
460 fragmentation(total_requested, total_allocated));
461 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
462}
463
464static void print_result(void)
465{
466 if (caller_flag)
467 __print_result(&root_caller_sorted, caller_lines, 1);
468 if (alloc_flag)
469 __print_result(&root_alloc_sorted, alloc_lines, 0);
470 print_summary();
471}
472
473struct sort_dimension {
474 const char name[20];
475 sort_fn_t cmp;
476 struct list_head list;
477};
478
479static LIST_HEAD(caller_sort);
480static LIST_HEAD(alloc_sort);
481
482static void sort_insert(struct rb_root *root, struct alloc_stat *data,
483 struct list_head *sort_list)
484{
485 struct rb_node **new = &(root->rb_node);
486 struct rb_node *parent = NULL;
487 struct sort_dimension *sort;
488
489 while (*new) {
490 struct alloc_stat *this;
491 int cmp = 0;
492
493 this = rb_entry(*new, struct alloc_stat, node);
494 parent = *new;
495
496 list_for_each_entry(sort, sort_list, list) {
497 cmp = sort->cmp(data, this);
498 if (cmp)
499 break;
500 }
501
502 if (cmp > 0)
503 new = &((*new)->rb_left);
504 else
505 new = &((*new)->rb_right);
506 }
507
508 rb_link_node(&data->node, parent, new);
509 rb_insert_color(&data->node, root);
510}
511
512static void __sort_result(struct rb_root *root, struct rb_root *root_sorted,
513 struct list_head *sort_list)
514{
515 struct rb_node *node;
516 struct alloc_stat *data;
517
518 for (;;) {
519 node = rb_first(root);
520 if (!node)
521 break;
522
523 rb_erase(node, root);
524 data = rb_entry(node, struct alloc_stat, node);
525 sort_insert(root_sorted, data, sort_list);
526 }
527}
528
529static void sort_result(void)
530{
531 __sort_result(&root_alloc_stat, &root_alloc_sorted, &alloc_sort);
532 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
533}
534
535static int __cmd_kmem(void)
536{
537 setup_pager();
538 read_events();
539 sort_result();
540 print_result();
541
542 return 0;
543}
544
545static const char * const kmem_usage[] = {
546 "perf kmem [<options>] {record}",
547 NULL
548};
549
550static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
551{
552 if (l->ptr < r->ptr)
553 return -1;
554 else if (l->ptr > r->ptr)
555 return 1;
556 return 0;
557}
558
559static struct sort_dimension ptr_sort_dimension = {
560 .name = "ptr",
561 .cmp = ptr_cmp,
562};
563
564static int callsite_cmp(struct alloc_stat *l, struct alloc_stat *r)
565{
566 if (l->call_site < r->call_site)
567 return -1;
568 else if (l->call_site > r->call_site)
569 return 1;
570 return 0;
571}
572
573static struct sort_dimension callsite_sort_dimension = {
574 .name = "callsite",
575 .cmp = callsite_cmp,
576};
577
578static int hit_cmp(struct alloc_stat *l, struct alloc_stat *r)
579{
580 if (l->hit < r->hit)
581 return -1;
582 else if (l->hit > r->hit)
583 return 1;
584 return 0;
585}
586
587static struct sort_dimension hit_sort_dimension = {
588 .name = "hit",
589 .cmp = hit_cmp,
590};
591
592static int bytes_cmp(struct alloc_stat *l, struct alloc_stat *r)
593{
594 if (l->bytes_alloc < r->bytes_alloc)
595 return -1;
596 else if (l->bytes_alloc > r->bytes_alloc)
597 return 1;
598 return 0;
599}
600
601static struct sort_dimension bytes_sort_dimension = {
602 .name = "bytes",
603 .cmp = bytes_cmp,
604};
605
606static int frag_cmp(struct alloc_stat *l, struct alloc_stat *r)
607{
608 double x, y;
609
610 x = fragmentation(l->bytes_req, l->bytes_alloc);
611 y = fragmentation(r->bytes_req, r->bytes_alloc);
612
613 if (x < y)
614 return -1;
615 else if (x > y)
616 return 1;
617 return 0;
618}
619
620static struct sort_dimension frag_sort_dimension = {
621 .name = "frag",
622 .cmp = frag_cmp,
623};
624
625static int pingpong_cmp(struct alloc_stat *l, struct alloc_stat *r)
626{
627 if (l->pingpong < r->pingpong)
628 return -1;
629 else if (l->pingpong > r->pingpong)
630 return 1;
631 return 0;
632}
633
634static struct sort_dimension pingpong_sort_dimension = {
635 .name = "pingpong",
636 .cmp = pingpong_cmp,
637};
638
639static struct sort_dimension *avail_sorts[] = {
640 &ptr_sort_dimension,
641 &callsite_sort_dimension,
642 &hit_sort_dimension,
643 &bytes_sort_dimension,
644 &frag_sort_dimension,
645 &pingpong_sort_dimension,
646};
647
648#define NUM_AVAIL_SORTS \
649 (int)(sizeof(avail_sorts) / sizeof(struct sort_dimension *))
650
651static int sort_dimension__add(const char *tok, struct list_head *list)
652{
653 struct sort_dimension *sort;
654 int i;
655
656 for (i = 0; i < NUM_AVAIL_SORTS; i++) {
657 if (!strcmp(avail_sorts[i]->name, tok)) {
658 sort = malloc(sizeof(*sort));
659 if (!sort)
660 die("malloc");
661 memcpy(sort, avail_sorts[i], sizeof(*sort));
662 list_add_tail(&sort->list, list);
663 return 0;
664 }
665 }
666
667 return -1;
668}
669
670static int setup_sorting(struct list_head *sort_list, const char *arg)
671{
672 char *tok;
673 char *str = strdup(arg);
674
675 if (!str)
676 die("strdup");
677
678 while (true) {
679 tok = strsep(&str, ",");
680 if (!tok)
681 break;
682 if (sort_dimension__add(tok, sort_list) < 0) {
683 error("Unknown --sort key: '%s'", tok);
684 return -1;
685 }
686 }
687
688 free(str);
689 return 0;
690}
691
692static int parse_sort_opt(const struct option *opt __used,
693 const char *arg, int unset __used)
694{
695 if (!arg)
696 return -1;
697
698 if (caller_flag > alloc_flag)
699 return setup_sorting(&caller_sort, arg);
700 else
701 return setup_sorting(&alloc_sort, arg);
702
703 return 0;
704}
705
706static int parse_stat_opt(const struct option *opt __used,
707 const char *arg, int unset __used)
708{
709 if (!arg)
710 return -1;
711
712 if (strcmp(arg, "alloc") == 0)
713 alloc_flag = (caller_flag + 1);
714 else if (strcmp(arg, "caller") == 0)
715 caller_flag = (alloc_flag + 1);
716 else
717 return -1;
718 return 0;
719}
720
721static int parse_line_opt(const struct option *opt __used,
722 const char *arg, int unset __used)
723{
724 int lines;
725
726 if (!arg)
727 return -1;
728
729 lines = strtoul(arg, NULL, 10);
730
731 if (caller_flag > alloc_flag)
732 caller_lines = lines;
733 else
734 alloc_lines = lines;
735
736 return 0;
737}
738
739static const struct option kmem_options[] = {
740 OPT_STRING('i', "input", &input_name, "file",
741 "input file name"),
742 OPT_CALLBACK(0, "stat", NULL, "<alloc>|<caller>",
743 "stat selector, Pass 'alloc' or 'caller'.",
744 parse_stat_opt),
745 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
746 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
747 parse_sort_opt),
748 OPT_CALLBACK('l', "line", NULL, "num",
749 "show n lins",
750 parse_line_opt),
751 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
752 OPT_END()
753};
754
755static const char *record_args[] = {
756 "record",
757 "-a",
758 "-R",
759 "-M",
760 "-f",
761 "-c", "1",
762 "-e", "kmem:kmalloc",
763 "-e", "kmem:kmalloc_node",
764 "-e", "kmem:kfree",
765 "-e", "kmem:kmem_cache_alloc",
766 "-e", "kmem:kmem_cache_alloc_node",
767 "-e", "kmem:kmem_cache_free",
768};
769
770static int __cmd_record(int argc, const char **argv)
771{
772 unsigned int rec_argc, i, j;
773 const char **rec_argv;
774
775 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
776 rec_argv = calloc(rec_argc + 1, sizeof(char *));
777
778 for (i = 0; i < ARRAY_SIZE(record_args); i++)
779 rec_argv[i] = strdup(record_args[i]);
780
781 for (j = 1; j < (unsigned int)argc; j++, i++)
782 rec_argv[i] = argv[j];
783
784 return cmd_record(i, rec_argv, NULL);
785}
786
787int cmd_kmem(int argc, const char **argv, const char *prefix __used)
788{
789 symbol__init(0);
790
791 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
792
793 if (argc && !strncmp(argv[0], "rec", 3))
794 return __cmd_record(argc, argv);
795 else if (argc)
796 usage_with_options(kmem_usage, kmem_options);
797
798 if (list_empty(&caller_sort))
799 setup_sorting(&caller_sort, default_sort_order);
800 if (list_empty(&alloc_sort))
801 setup_sorting(&alloc_sort, default_sort_order);
802
803 setup_cpunode_map();
804
805 return __cmd_kmem();
806}
807
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
new file mode 100644
index 000000000000..a58e11b7ea80
--- /dev/null
+++ b/tools/perf/builtin-probe.c
@@ -0,0 +1,242 @@
1/*
2 * builtin-probe.c
3 *
4 * Builtin probe command: Set up probe events by C expression
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23#define _GNU_SOURCE
24#include <sys/utsname.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <errno.h>
29#include <stdio.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33
34#undef _GNU_SOURCE
35#include "perf.h"
36#include "builtin.h"
37#include "util/util.h"
38#include "util/event.h"
39#include "util/debug.h"
40#include "util/parse-options.h"
41#include "util/parse-events.h" /* For debugfs_path */
42#include "util/probe-finder.h"
43#include "util/probe-event.h"
44
45/* Default vmlinux search paths */
46#define NR_SEARCH_PATH 3
47const char *default_search_path[NR_SEARCH_PATH] = {
48"/lib/modules/%s/build/vmlinux", /* Custom build kernel */
49"/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */
50"/boot/vmlinux-debug-%s", /* Ubuntu */
51};
52
53#define MAX_PATH_LEN 256
54#define MAX_PROBES 128
55
56/* Session management structure */
57static struct {
58 char *vmlinux;
59 char *release;
60 int need_dwarf;
61 int nr_probe;
62 struct probe_point probes[MAX_PROBES];
63} session;
64
65static bool listing;
66
67/* Parse an event definition. Note that any error must die. */
68static void parse_probe_event(const char *str)
69{
70 struct probe_point *pp = &session.probes[session.nr_probe];
71
72 pr_debug("probe-definition(%d): %s\n", session.nr_probe, str);
73 if (++session.nr_probe == MAX_PROBES)
74 die("Too many probes (> %d) are specified.", MAX_PROBES);
75
76 /* Parse perf-probe event into probe_point */
77 session.need_dwarf = parse_perf_probe_event(str, pp);
78
79 pr_debug("%d arguments\n", pp->nr_args);
80}
81
82static int opt_add_probe_event(const struct option *opt __used,
83 const char *str, int unset __used)
84{
85 if (str)
86 parse_probe_event(str);
87 return 0;
88}
89
90#ifndef NO_LIBDWARF
91static int open_default_vmlinux(void)
92{
93 struct utsname uts;
94 char fname[MAX_PATH_LEN];
95 int fd, ret, i;
96
97 ret = uname(&uts);
98 if (ret) {
99 pr_debug("uname() failed.\n");
100 return -errno;
101 }
102 session.release = uts.release;
103 for (i = 0; i < NR_SEARCH_PATH; i++) {
104 ret = snprintf(fname, MAX_PATH_LEN,
105 default_search_path[i], session.release);
106 if (ret >= MAX_PATH_LEN || ret < 0) {
107 pr_debug("Filename(%d,%s) is too long.\n", i,
108 uts.release);
109 errno = E2BIG;
110 return -E2BIG;
111 }
112 pr_debug("try to open %s\n", fname);
113 fd = open(fname, O_RDONLY);
114 if (fd >= 0)
115 break;
116 }
117 return fd;
118}
119#endif
120
121static const char * const probe_usage[] = {
122 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
123 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
124 "perf probe --list",
125 NULL
126};
127
128static const struct option options[] = {
129 OPT_BOOLEAN('v', "verbose", &verbose,
130 "be more verbose (show parsed arguments, etc)"),
131#ifndef NO_LIBDWARF
132 OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
133 "vmlinux/module pathname"),
134#endif
135 OPT_BOOLEAN('l', "list", &listing, "list up current probes"),
136 OPT_CALLBACK('a', "add", NULL,
137#ifdef NO_LIBDWARF
138 "FUNC[+OFFS|%return] [ARG ...]",
139#else
140 "FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
141#endif
142 "probe point definition, where\n"
143 "\t\tGRP:\tGroup name (optional)\n"
144 "\t\tNAME:\tEvent name\n"
145 "\t\tFUNC:\tFunction name\n"
146 "\t\tOFFS:\tOffset from function entry (in byte)\n"
147 "\t\t%return:\tPut the probe at function return\n"
148#ifdef NO_LIBDWARF
149 "\t\tARG:\tProbe argument (only \n"
150#else
151 "\t\tSRC:\tSource code path\n"
152 "\t\tRLN:\tRelative line number from function entry.\n"
153 "\t\tALN:\tAbsolute line number in file.\n"
154 "\t\tARG:\tProbe argument (local variable name or\n"
155#endif
156 "\t\t\tkprobe-tracer argument format.)\n",
157 opt_add_probe_event),
158 OPT_END()
159};
160
161int cmd_probe(int argc, const char **argv, const char *prefix __used)
162{
163 int i, j, ret;
164#ifndef NO_LIBDWARF
165 int fd;
166#endif
167 struct probe_point *pp;
168
169 argc = parse_options(argc, argv, options, probe_usage,
170 PARSE_OPT_STOP_AT_NON_OPTION);
171 for (i = 0; i < argc; i++)
172 parse_probe_event(argv[i]);
173
174 if ((session.nr_probe == 0 && !listing) ||
175 (session.nr_probe != 0 && listing))
176 usage_with_options(probe_usage, options);
177
178 if (listing) {
179 show_perf_probe_events();
180 return 0;
181 }
182
183 if (session.need_dwarf)
184#ifdef NO_LIBDWARF
185 die("Debuginfo-analysis is not supported");
186#else /* !NO_LIBDWARF */
187 pr_debug("Some probes require debuginfo.\n");
188
189 if (session.vmlinux)
190 fd = open(session.vmlinux, O_RDONLY);
191 else
192 fd = open_default_vmlinux();
193 if (fd < 0) {
194 if (session.need_dwarf)
195 die("Could not open vmlinux/module file.");
196
197 pr_warning("Could not open vmlinux/module file."
198 " Try to use symbols.\n");
199 goto end_dwarf;
200 }
201
202 /* Searching probe points */
203 for (j = 0; j < session.nr_probe; j++) {
204 pp = &session.probes[j];
205 if (pp->found)
206 continue;
207
208 lseek(fd, SEEK_SET, 0);
209 ret = find_probepoint(fd, pp);
210 if (ret < 0) {
211 if (session.need_dwarf)
212 die("Could not analyze debuginfo.");
213
214 pr_warning("An error occurred in debuginfo analysis. Try to use symbols.\n");
215 break;
216 }
217 if (ret == 0) /* No error but failed to find probe point. */
218 die("No probe point found.");
219 }
220 close(fd);
221
222end_dwarf:
223#endif /* !NO_LIBDWARF */
224
225 /* Synthesize probes without dwarf */
226 for (j = 0; j < session.nr_probe; j++) {
227 pp = &session.probes[j];
228 if (pp->found) /* This probe is already found. */
229 continue;
230
231 ret = synthesize_trace_kprobe_event(pp);
232 if (ret == -E2BIG)
233 die("probe point definition becomes too long.");
234 else if (ret < 0)
235 die("Failed to synthesize a probe point.");
236 }
237
238 /* Settng up probe points */
239 add_trace_kprobe_events(session.probes, session.nr_probe);
240 return 0;
241}
242
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a4be453fc8a9..0e519c667e3a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,55 +17,52 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/trace-event.h" 20#include "util/symbol.h"
21 21
22#include <unistd.h> 22#include <unistd.h>
23#include <sched.h> 23#include <sched.h>
24 24
25#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
26#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27
28static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 25static int fd[MAX_NR_CPUS][MAX_COUNTERS];
29 26
30static long default_interval = 100000; 27static long default_interval = 0;
31 28
32static int nr_cpus = 0; 29static int nr_cpus = 0;
33static unsigned int page_size; 30static unsigned int page_size;
34static unsigned int mmap_pages = 128; 31static unsigned int mmap_pages = 128;
35static int freq = 0; 32static int freq = 1000;
36static int output; 33static int output;
37static const char *output_name = "perf.data"; 34static const char *output_name = "perf.data";
38static int group = 0; 35static int group = 0;
39static unsigned int realtime_prio = 0; 36static unsigned int realtime_prio = 0;
40static int raw_samples = 0; 37static int raw_samples = 0;
41static int system_wide = 0; 38static int system_wide = 0;
42static int profile_cpu = -1; 39static int profile_cpu = -1;
43static pid_t target_pid = -1; 40static pid_t target_pid = -1;
44static pid_t child_pid = -1; 41static pid_t child_pid = -1;
45static int inherit = 1; 42static int inherit = 1;
46static int force = 0; 43static int force = 0;
47static int append_file = 0; 44static int append_file = 0;
48static int call_graph = 0; 45static int call_graph = 0;
49static int inherit_stat = 0; 46static int inherit_stat = 0;
50static int no_samples = 0; 47static int no_samples = 0;
51static int sample_address = 0; 48static int sample_address = 0;
52static int multiplex = 0; 49static int multiplex = 0;
53static int multiplex_fd = -1; 50static int multiplex_fd = -1;
54 51
55static long samples; 52static long samples = 0;
56static struct timeval last_read; 53static struct timeval last_read;
57static struct timeval this_read; 54static struct timeval this_read;
58 55
59static u64 bytes_written; 56static u64 bytes_written = 0;
60 57
61static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 58static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
62 59
63static int nr_poll; 60static int nr_poll = 0;
64static int nr_cpu; 61static int nr_cpu = 0;
65 62
66static int file_new = 1; 63static int file_new = 1;
67 64
68struct perf_header *header; 65struct perf_header *header = NULL;
69 66
70struct mmap_data { 67struct mmap_data {
71 int counter; 68 int counter;
@@ -113,6 +110,24 @@ static void write_output(void *buf, size_t size)
113 } 110 }
114} 111}
115 112
113static void write_event(event_t *buf, size_t size)
114{
115 /*
116 * Add it to the list of DSOs, so that when we finish this
117 * record session we can pick the available build-ids.
118 */
119 if (buf->header.type == PERF_RECORD_MMAP)
120 dsos__findnew(buf->mmap.filename);
121
122 write_output(buf, size);
123}
124
125static int process_synthesized_event(event_t *event)
126{
127 write_event(event, event->header.size);
128 return 0;
129}
130
116static void mmap_read(struct mmap_data *md) 131static void mmap_read(struct mmap_data *md)
117{ 132{
118 unsigned int head = mmap_read_head(md); 133 unsigned int head = mmap_read_head(md);
@@ -161,14 +176,14 @@ static void mmap_read(struct mmap_data *md)
161 size = md->mask + 1 - (old & md->mask); 176 size = md->mask + 1 - (old & md->mask);
162 old += size; 177 old += size;
163 178
164 write_output(buf, size); 179 write_event(buf, size);
165 } 180 }
166 181
167 buf = &data[old & md->mask]; 182 buf = &data[old & md->mask];
168 size = head - old; 183 size = head - old;
169 old += size; 184 old += size;
170 185
171 write_output(buf, size); 186 write_event(buf, size);
172 187
173 md->prev = old; 188 md->prev = old;
174 mmap_write_tail(md, old); 189 mmap_write_tail(md, old);
@@ -195,168 +210,6 @@ static void sig_atexit(void)
195 kill(getpid(), signr); 210 kill(getpid(), signr);
196} 211}
197 212
198static pid_t pid_synthesize_comm_event(pid_t pid, int full)
199{
200 struct comm_event comm_ev;
201 char filename[PATH_MAX];
202 char bf[BUFSIZ];
203 FILE *fp;
204 size_t size = 0;
205 DIR *tasks;
206 struct dirent dirent, *next;
207 pid_t tgid = 0;
208
209 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
210
211 fp = fopen(filename, "r");
212 if (fp == NULL) {
213 /*
214 * We raced with a task exiting - just return:
215 */
216 if (verbose)
217 fprintf(stderr, "couldn't open %s\n", filename);
218 return 0;
219 }
220
221 memset(&comm_ev, 0, sizeof(comm_ev));
222 while (!comm_ev.comm[0] || !comm_ev.pid) {
223 if (fgets(bf, sizeof(bf), fp) == NULL)
224 goto out_failure;
225
226 if (memcmp(bf, "Name:", 5) == 0) {
227 char *name = bf + 5;
228 while (*name && isspace(*name))
229 ++name;
230 size = strlen(name) - 1;
231 memcpy(comm_ev.comm, name, size++);
232 } else if (memcmp(bf, "Tgid:", 5) == 0) {
233 char *tgids = bf + 5;
234 while (*tgids && isspace(*tgids))
235 ++tgids;
236 tgid = comm_ev.pid = atoi(tgids);
237 }
238 }
239
240 comm_ev.header.type = PERF_RECORD_COMM;
241 size = ALIGN(size, sizeof(u64));
242 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
243
244 if (!full) {
245 comm_ev.tid = pid;
246
247 write_output(&comm_ev, comm_ev.header.size);
248 goto out_fclose;
249 }
250
251 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
252
253 tasks = opendir(filename);
254 while (!readdir_r(tasks, &dirent, &next) && next) {
255 char *end;
256 pid = strtol(dirent.d_name, &end, 10);
257 if (*end)
258 continue;
259
260 comm_ev.tid = pid;
261
262 write_output(&comm_ev, comm_ev.header.size);
263 }
264 closedir(tasks);
265
266out_fclose:
267 fclose(fp);
268 return tgid;
269
270out_failure:
271 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
272 filename);
273 exit(EXIT_FAILURE);
274}
275
276static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
277{
278 char filename[PATH_MAX];
279 FILE *fp;
280
281 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
282
283 fp = fopen(filename, "r");
284 if (fp == NULL) {
285 /*
286 * We raced with a task exiting - just return:
287 */
288 if (verbose)
289 fprintf(stderr, "couldn't open %s\n", filename);
290 return;
291 }
292 while (1) {
293 char bf[BUFSIZ], *pbf = bf;
294 struct mmap_event mmap_ev = {
295 .header = { .type = PERF_RECORD_MMAP },
296 };
297 int n;
298 size_t size;
299 if (fgets(bf, sizeof(bf), fp) == NULL)
300 break;
301
302 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
303 n = hex2u64(pbf, &mmap_ev.start);
304 if (n < 0)
305 continue;
306 pbf += n + 1;
307 n = hex2u64(pbf, &mmap_ev.len);
308 if (n < 0)
309 continue;
310 pbf += n + 3;
311 if (*pbf == 'x') { /* vm_exec */
312 char *execname = strchr(bf, '/');
313
314 /* Catch VDSO */
315 if (execname == NULL)
316 execname = strstr(bf, "[vdso]");
317
318 if (execname == NULL)
319 continue;
320
321 size = strlen(execname);
322 execname[size - 1] = '\0'; /* Remove \n */
323 memcpy(mmap_ev.filename, execname, size);
324 size = ALIGN(size, sizeof(u64));
325 mmap_ev.len -= mmap_ev.start;
326 mmap_ev.header.size = (sizeof(mmap_ev) -
327 (sizeof(mmap_ev.filename) - size));
328 mmap_ev.pid = tgid;
329 mmap_ev.tid = pid;
330
331 write_output(&mmap_ev, mmap_ev.header.size);
332 }
333 }
334
335 fclose(fp);
336}
337
338static void synthesize_all(void)
339{
340 DIR *proc;
341 struct dirent dirent, *next;
342
343 proc = opendir("/proc");
344
345 while (!readdir_r(proc, &dirent, &next) && next) {
346 char *end;
347 pid_t pid, tgid;
348
349 pid = strtol(dirent.d_name, &end, 10);
350 if (*end) /* only interested in proper numerical dirents */
351 continue;
352
353 tgid = pid_synthesize_comm_event(pid, 1);
354 pid_synthesize_mmap_samples(pid, tgid);
355 }
356
357 closedir(proc);
358}
359
360static int group_fd; 213static int group_fd;
361 214
362static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr) 215static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
@@ -367,7 +220,11 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
367 h_attr = header->attr[nr]; 220 h_attr = header->attr[nr];
368 } else { 221 } else {
369 h_attr = perf_header_attr__new(a); 222 h_attr = perf_header_attr__new(a);
370 perf_header__add_attr(header, h_attr); 223 if (h_attr != NULL)
224 if (perf_header__add_attr(header, h_attr) < 0) {
225 perf_header_attr__delete(h_attr);
226 h_attr = NULL;
227 }
371 } 228 }
372 229
373 return h_attr; 230 return h_attr;
@@ -375,9 +232,11 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
375 232
376static void create_counter(int counter, int cpu, pid_t pid) 233static void create_counter(int counter, int cpu, pid_t pid)
377{ 234{
235 char *filter = filters[counter];
378 struct perf_event_attr *attr = attrs + counter; 236 struct perf_event_attr *attr = attrs + counter;
379 struct perf_header_attr *h_attr; 237 struct perf_header_attr *h_attr;
380 int track = !counter; /* only the first counter needs these */ 238 int track = !counter; /* only the first counter needs these */
239 int ret;
381 struct { 240 struct {
382 u64 count; 241 u64 count;
383 u64 time_enabled; 242 u64 time_enabled;
@@ -448,11 +307,19 @@ try_again:
448 printf("\n"); 307 printf("\n");
449 error("perfcounter syscall returned with %d (%s)\n", 308 error("perfcounter syscall returned with %d (%s)\n",
450 fd[nr_cpu][counter], strerror(err)); 309 fd[nr_cpu][counter], strerror(err));
310
311#if defined(__i386__) || defined(__x86_64__)
312 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
313 die("No hardware sampling interrupt available. No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.\n");
314#endif
315
451 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 316 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
452 exit(-1); 317 exit(-1);
453 } 318 }
454 319
455 h_attr = get_header_attr(attr, counter); 320 h_attr = get_header_attr(attr, counter);
321 if (h_attr == NULL)
322 die("nomem\n");
456 323
457 if (!file_new) { 324 if (!file_new) {
458 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { 325 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
@@ -466,7 +333,10 @@ try_again:
466 exit(-1); 333 exit(-1);
467 } 334 }
468 335
469 perf_header_attr__add_id(h_attr, read_data.id); 336 if (perf_header_attr__add_id(h_attr, read_data.id) < 0) {
337 pr_warning("Not enough memory to add id\n");
338 exit(-1);
339 }
470 340
471 assert(fd[nr_cpu][counter] >= 0); 341 assert(fd[nr_cpu][counter] >= 0);
472 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); 342 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
@@ -480,7 +350,6 @@ try_again:
480 multiplex_fd = fd[nr_cpu][counter]; 350 multiplex_fd = fd[nr_cpu][counter];
481 351
482 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { 352 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) {
483 int ret;
484 353
485 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); 354 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
486 assert(ret != -1); 355 assert(ret != -1);
@@ -500,6 +369,16 @@ try_again:
500 } 369 }
501 } 370 }
502 371
372 if (filter != NULL) {
373 ret = ioctl(fd[nr_cpu][counter],
374 PERF_EVENT_IOC_SET_FILTER, filter);
375 if (ret) {
376 error("failed to set filter with %d (%s)\n", errno,
377 strerror(errno));
378 exit(-1);
379 }
380 }
381
503 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); 382 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
504} 383}
505 384
@@ -518,7 +397,7 @@ static void atexit_header(void)
518{ 397{
519 header->data_size += bytes_written; 398 header->data_size += bytes_written;
520 399
521 perf_header__write(header, output); 400 perf_header__write(header, output, true);
522} 401}
523 402
524static int __cmd_record(int argc, const char **argv) 403static int __cmd_record(int argc, const char **argv)
@@ -527,7 +406,7 @@ static int __cmd_record(int argc, const char **argv)
527 struct stat st; 406 struct stat st;
528 pid_t pid = 0; 407 pid_t pid = 0;
529 int flags; 408 int flags;
530 int ret; 409 int err;
531 unsigned long waking = 0; 410 unsigned long waking = 0;
532 411
533 page_size = sysconf(_SC_PAGE_SIZE); 412 page_size = sysconf(_SC_PAGE_SIZE);
@@ -561,22 +440,29 @@ static int __cmd_record(int argc, const char **argv)
561 exit(-1); 440 exit(-1);
562 } 441 }
563 442
564 if (!file_new) 443 header = perf_header__new();
565 header = perf_header__read(output); 444 if (header == NULL) {
566 else 445 pr_err("Not enough memory for reading perf file header\n");
567 header = perf_header__new(); 446 return -1;
447 }
568 448
449 if (!file_new) {
450 err = perf_header__read(header, output);
451 if (err < 0)
452 return err;
453 }
569 454
570 if (raw_samples) { 455 if (raw_samples) {
571 read_tracing_data(attrs, nr_counters); 456 perf_header__set_feat(header, HEADER_TRACE_INFO);
572 } else { 457 } else {
573 for (i = 0; i < nr_counters; i++) { 458 for (i = 0; i < nr_counters; i++) {
574 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 459 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
575 read_tracing_data(attrs, nr_counters); 460 perf_header__set_feat(header, HEADER_TRACE_INFO);
576 break; 461 break;
577 } 462 }
578 } 463 }
579 } 464 }
465
580 atexit(atexit_header); 466 atexit(atexit_header);
581 467
582 if (!system_wide) { 468 if (!system_wide) {
@@ -594,25 +480,36 @@ static int __cmd_record(int argc, const char **argv)
594 } 480 }
595 } 481 }
596 482
597 if (file_new) 483 if (file_new) {
598 perf_header__write(header, output); 484 err = perf_header__write(header, output, false);
485 if (err < 0)
486 return err;
487 }
599 488
600 if (!system_wide) { 489 if (!system_wide)
601 pid_t tgid = pid_synthesize_comm_event(pid, 0); 490 event__synthesize_thread(pid, process_synthesized_event);
602 pid_synthesize_mmap_samples(pid, tgid); 491 else
603 } else 492 event__synthesize_threads(process_synthesized_event);
604 synthesize_all();
605 493
606 if (target_pid == -1 && argc) { 494 if (target_pid == -1 && argc) {
607 pid = fork(); 495 pid = fork();
608 if (pid < 0) 496 if (pid < 0)
609 perror("failed to fork"); 497 die("failed to fork");
610 498
611 if (!pid) { 499 if (!pid) {
612 if (execvp(argv[0], (char **)argv)) { 500 if (execvp(argv[0], (char **)argv)) {
613 perror(argv[0]); 501 perror(argv[0]);
614 exit(-1); 502 exit(-1);
615 } 503 }
504 } else {
505 /*
506 * Wait a bit for the execv'ed child to appear
507 * and be updated in /proc
508 * FIXME: Do you know a less heuristical solution?
509 */
510 usleep(1000);
511 event__synthesize_thread(pid,
512 process_synthesized_event);
616 } 513 }
617 514
618 child_pid = pid; 515 child_pid = pid;
@@ -623,7 +520,7 @@ static int __cmd_record(int argc, const char **argv)
623 520
624 param.sched_priority = realtime_prio; 521 param.sched_priority = realtime_prio;
625 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 522 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
626 printf("Could not set realtime priority.\n"); 523 pr_err("Could not set realtime priority.\n");
627 exit(-1); 524 exit(-1);
628 } 525 }
629 } 526 }
@@ -641,7 +538,7 @@ static int __cmd_record(int argc, const char **argv)
641 if (hits == samples) { 538 if (hits == samples) {
642 if (done) 539 if (done)
643 break; 540 break;
644 ret = poll(event_array, nr_poll, -1); 541 err = poll(event_array, nr_poll, -1);
645 waking++; 542 waking++;
646 } 543 }
647 544
@@ -677,6 +574,8 @@ static const struct option options[] = {
677 OPT_CALLBACK('e', "event", NULL, "event", 574 OPT_CALLBACK('e', "event", NULL, "event",
678 "event selector. use 'perf list' to list available events", 575 "event selector. use 'perf list' to list available events",
679 parse_events), 576 parse_events),
577 OPT_CALLBACK(0, "filter", NULL, "filter",
578 "event filter", parse_filter),
680 OPT_INTEGER('p', "pid", &target_pid, 579 OPT_INTEGER('p', "pid", &target_pid,
681 "record events on existing pid"), 580 "record events on existing pid"),
682 OPT_INTEGER('r', "realtime", &realtime_prio, 581 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -720,6 +619,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
720{ 619{
721 int counter; 620 int counter;
722 621
622 symbol__init(0);
623
723 argc = parse_options(argc, argv, options, record_usage, 624 argc = parse_options(argc, argv, options, record_usage,
724 PARSE_OPT_STOP_AT_NON_OPTION); 625 PARSE_OPT_STOP_AT_NON_OPTION);
725 if (!argc && target_pid == -1 && !system_wide) 626 if (!argc && target_pid == -1 && !system_wide)
@@ -731,6 +632,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
731 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 632 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
732 } 633 }
733 634
635 /*
636 * User specified count overrides default frequency.
637 */
638 if (default_interval)
639 freq = 0;
640 else if (freq) {
641 default_interval = freq;
642 } else {
643 fprintf(stderr, "frequency and count are zero, aborting\n");
644 exit(EXIT_FAILURE);
645 }
646
734 for (counter = 0; counter < nr_counters; counter++) { 647 for (counter = 0; counter < nr_counters; counter++) {
735 if (attrs[counter].sample_period) 648 if (attrs[counter].sample_period)
736 continue; 649 continue;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 19669c20088e..383c4ab4f9af 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -26,20 +26,18 @@
26#include "util/parse-options.h" 26#include "util/parse-options.h"
27#include "util/parse-events.h" 27#include "util/parse-events.h"
28 28
29#include "util/data_map.h"
29#include "util/thread.h" 30#include "util/thread.h"
31#include "util/sort.h"
32#include "util/hist.h"
30 33
31static char const *input_name = "perf.data"; 34static char const *input_name = "perf.data";
32 35
33static char default_sort_order[] = "comm,dso,symbol";
34static char *sort_order = default_sort_order;
35static char *dso_list_str, *comm_list_str, *sym_list_str, 36static char *dso_list_str, *comm_list_str, *sym_list_str,
36 *col_width_list_str; 37 *col_width_list_str;
37static struct strlist *dso_list, *comm_list, *sym_list; 38static struct strlist *dso_list, *comm_list, *sym_list;
38static char *field_sep;
39 39
40static int force; 40static int force;
41static int input;
42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
43 41
44static int full_paths; 42static int full_paths;
45static int show_nr_samples; 43static int show_nr_samples;
@@ -50,374 +48,38 @@ static struct perf_read_values show_threads_values;
50static char default_pretty_printing_style[] = "normal"; 48static char default_pretty_printing_style[] = "normal";
51static char *pretty_printing_style = default_pretty_printing_style; 49static char *pretty_printing_style = default_pretty_printing_style;
52 50
53static unsigned long page_size;
54static unsigned long mmap_window = 32;
55
56static char default_parent_pattern[] = "^sys_|^do_page_fault";
57static char *parent_pattern = default_parent_pattern;
58static regex_t parent_regex;
59
60static int exclude_other = 1; 51static int exclude_other = 1;
61 52
62static char callchain_default_opt[] = "fractal,0.5"; 53static char callchain_default_opt[] = "fractal,0.5";
63 54
64static int callchain;
65
66static char __cwd[PATH_MAX];
67static char *cwd = __cwd;
68static int cwdlen;
69
70static struct rb_root threads;
71static struct thread *last_match;
72
73static struct perf_header *header; 55static struct perf_header *header;
74 56
75static
76struct callchain_param callchain_param = {
77 .mode = CHAIN_GRAPH_REL,
78 .min_percent = 0.5
79};
80
81static u64 sample_type; 57static u64 sample_type;
82 58
83static int repsep_fprintf(FILE *fp, const char *fmt, ...) 59struct symbol_conf symbol_conf;
84{
85 int n;
86 va_list ap;
87
88 va_start(ap, fmt);
89 if (!field_sep)
90 n = vfprintf(fp, fmt, ap);
91 else {
92 char *bf = NULL;
93 n = vasprintf(&bf, fmt, ap);
94 if (n > 0) {
95 char *sep = bf;
96
97 while (1) {
98 sep = strchr(sep, *field_sep);
99 if (sep == NULL)
100 break;
101 *sep = '.';
102 }
103 }
104 fputs(bf, fp);
105 free(bf);
106 }
107 va_end(ap);
108 return n;
109}
110
111static unsigned int dsos__col_width,
112 comms__col_width,
113 threads__col_width;
114 60
115/*
116 * histogram, sorted on item, collects counts
117 */
118
119static struct rb_root hist;
120
121struct hist_entry {
122 struct rb_node rb_node;
123
124 struct thread *thread;
125 struct map *map;
126 struct dso *dso;
127 struct symbol *sym;
128 struct symbol *parent;
129 u64 ip;
130 char level;
131 struct callchain_node callchain;
132 struct rb_root sorted_chain;
133
134 u64 count;
135};
136
137/*
138 * configurable sorting bits
139 */
140
141struct sort_entry {
142 struct list_head list;
143
144 const char *header;
145
146 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
147 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
148 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
149 unsigned int *width;
150 bool elide;
151};
152
153static int64_t cmp_null(void *l, void *r)
154{
155 if (!l && !r)
156 return 0;
157 else if (!l)
158 return -1;
159 else
160 return 1;
161}
162
163/* --sort pid */
164
165static int64_t
166sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
167{
168 return right->thread->pid - left->thread->pid;
169}
170 61
171static size_t 62static size_t
172sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width) 63callchain__fprintf_left_margin(FILE *fp, int left_margin)
173{ 64{
174 return repsep_fprintf(fp, "%*s:%5d", width - 6, 65 int i;
175 self->thread->comm ?: "", self->thread->pid); 66 int ret;
176}
177
178static struct sort_entry sort_thread = {
179 .header = "Command: Pid",
180 .cmp = sort__thread_cmp,
181 .print = sort__thread_print,
182 .width = &threads__col_width,
183};
184
185/* --sort comm */
186
187static int64_t
188sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
189{
190 return right->thread->pid - left->thread->pid;
191}
192
193static int64_t
194sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
195{
196 char *comm_l = left->thread->comm;
197 char *comm_r = right->thread->comm;
198
199 if (!comm_l || !comm_r)
200 return cmp_null(comm_l, comm_r);
201
202 return strcmp(comm_l, comm_r);
203}
204
205static size_t
206sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
207{
208 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
209}
210
211static struct sort_entry sort_comm = {
212 .header = "Command",
213 .cmp = sort__comm_cmp,
214 .collapse = sort__comm_collapse,
215 .print = sort__comm_print,
216 .width = &comms__col_width,
217};
218
219/* --sort dso */
220
221static int64_t
222sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
223{
224 struct dso *dso_l = left->dso;
225 struct dso *dso_r = right->dso;
226
227 if (!dso_l || !dso_r)
228 return cmp_null(dso_l, dso_r);
229
230 return strcmp(dso_l->name, dso_r->name);
231}
232
233static size_t
234sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
235{
236 if (self->dso)
237 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
238
239 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
240}
241
242static struct sort_entry sort_dso = {
243 .header = "Shared Object",
244 .cmp = sort__dso_cmp,
245 .print = sort__dso_print,
246 .width = &dsos__col_width,
247};
248
249/* --sort symbol */
250
251static int64_t
252sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
253{
254 u64 ip_l, ip_r;
255
256 if (left->sym == right->sym)
257 return 0;
258
259 ip_l = left->sym ? left->sym->start : left->ip;
260 ip_r = right->sym ? right->sym->start : right->ip;
261
262 return (int64_t)(ip_r - ip_l);
263}
264
265static size_t
266sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
267{
268 size_t ret = 0;
269 67
270 if (verbose) 68 ret = fprintf(fp, " ");
271 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
272 dso__symtab_origin(self->dso));
273 69
274 ret += repsep_fprintf(fp, "[%c] ", self->level); 70 for (i = 0; i < left_margin; i++)
275 if (self->sym) { 71 ret += fprintf(fp, " ");
276 ret += repsep_fprintf(fp, "%s", self->sym->name);
277
278 if (self->sym->module)
279 ret += repsep_fprintf(fp, "\t[%s]",
280 self->sym->module->name);
281 } else {
282 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
283 }
284 72
285 return ret; 73 return ret;
286} 74}
287 75
288static struct sort_entry sort_sym = { 76static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
289 .header = "Symbol", 77 int left_margin)
290 .cmp = sort__sym_cmp,
291 .print = sort__sym_print,
292};
293
294/* --sort parent */
295
296static int64_t
297sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
298{
299 struct symbol *sym_l = left->parent;
300 struct symbol *sym_r = right->parent;
301
302 if (!sym_l || !sym_r)
303 return cmp_null(sym_l, sym_r);
304
305 return strcmp(sym_l->name, sym_r->name);
306}
307
308static size_t
309sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
310{
311 return repsep_fprintf(fp, "%-*s", width,
312 self->parent ? self->parent->name : "[other]");
313}
314
315static unsigned int parent_symbol__col_width;
316
317static struct sort_entry sort_parent = {
318 .header = "Parent symbol",
319 .cmp = sort__parent_cmp,
320 .print = sort__parent_print,
321 .width = &parent_symbol__col_width,
322};
323
324static int sort__need_collapse = 0;
325static int sort__has_parent = 0;
326
327struct sort_dimension {
328 const char *name;
329 struct sort_entry *entry;
330 int taken;
331};
332
333static struct sort_dimension sort_dimensions[] = {
334 { .name = "pid", .entry = &sort_thread, },
335 { .name = "comm", .entry = &sort_comm, },
336 { .name = "dso", .entry = &sort_dso, },
337 { .name = "symbol", .entry = &sort_sym, },
338 { .name = "parent", .entry = &sort_parent, },
339};
340
341static LIST_HEAD(hist_entry__sort_list);
342
343static int sort_dimension__add(const char *tok)
344{
345 unsigned int i;
346
347 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
348 struct sort_dimension *sd = &sort_dimensions[i];
349
350 if (sd->taken)
351 continue;
352
353 if (strncasecmp(tok, sd->name, strlen(tok)))
354 continue;
355
356 if (sd->entry->collapse)
357 sort__need_collapse = 1;
358
359 if (sd->entry == &sort_parent) {
360 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
361 if (ret) {
362 char err[BUFSIZ];
363
364 regerror(ret, &parent_regex, err, sizeof(err));
365 fprintf(stderr, "Invalid regex: %s\n%s",
366 parent_pattern, err);
367 exit(-1);
368 }
369 sort__has_parent = 1;
370 }
371
372 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
373 sd->taken = 1;
374
375 return 0;
376 }
377
378 return -ESRCH;
379}
380
381static int64_t
382hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
383{
384 struct sort_entry *se;
385 int64_t cmp = 0;
386
387 list_for_each_entry(se, &hist_entry__sort_list, list) {
388 cmp = se->cmp(left, right);
389 if (cmp)
390 break;
391 }
392
393 return cmp;
394}
395
396static int64_t
397hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
398{
399 struct sort_entry *se;
400 int64_t cmp = 0;
401
402 list_for_each_entry(se, &hist_entry__sort_list, list) {
403 int64_t (*f)(struct hist_entry *, struct hist_entry *);
404
405 f = se->collapse ?: se->cmp;
406
407 cmp = f(left, right);
408 if (cmp)
409 break;
410 }
411
412 return cmp;
413}
414
415static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
416{ 78{
417 int i; 79 int i;
418 size_t ret = 0; 80 size_t ret = 0;
419 81
420 ret += fprintf(fp, "%s", " "); 82 ret += callchain__fprintf_left_margin(fp, left_margin);
421 83
422 for (i = 0; i < depth; i++) 84 for (i = 0; i < depth; i++)
423 if (depth_mask & (1 << i)) 85 if (depth_mask & (1 << i))
@@ -432,12 +94,12 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
432static size_t 94static size_t
433ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, 95ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
434 int depth_mask, int count, u64 total_samples, 96 int depth_mask, int count, u64 total_samples,
435 int hits) 97 int hits, int left_margin)
436{ 98{
437 int i; 99 int i;
438 size_t ret = 0; 100 size_t ret = 0;
439 101
440 ret += fprintf(fp, "%s", " "); 102 ret += callchain__fprintf_left_margin(fp, left_margin);
441 for (i = 0; i < depth; i++) { 103 for (i = 0; i < depth; i++) {
442 if (depth_mask & (1 << i)) 104 if (depth_mask & (1 << i))
443 ret += fprintf(fp, "|"); 105 ret += fprintf(fp, "|");
@@ -475,8 +137,9 @@ static void init_rem_hits(void)
475} 137}
476 138
477static size_t 139static size_t
478callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 140__callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
479 u64 total_samples, int depth, int depth_mask) 141 u64 total_samples, int depth, int depth_mask,
142 int left_margin)
480{ 143{
481 struct rb_node *node, *next; 144 struct rb_node *node, *next;
482 struct callchain_node *child; 145 struct callchain_node *child;
@@ -517,7 +180,8 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
517 * But we keep the older depth mask for the line seperator 180 * But we keep the older depth mask for the line seperator
518 * to keep the level link until we reach the last child 181 * to keep the level link until we reach the last child
519 */ 182 */
520 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); 183 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
184 left_margin);
521 i = 0; 185 i = 0;
522 list_for_each_entry(chain, &child->val, list) { 186 list_for_each_entry(chain, &child->val, list) {
523 if (chain->ip >= PERF_CONTEXT_MAX) 187 if (chain->ip >= PERF_CONTEXT_MAX)
@@ -525,11 +189,13 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
525 ret += ipchain__fprintf_graph(fp, chain, depth, 189 ret += ipchain__fprintf_graph(fp, chain, depth,
526 new_depth_mask, i++, 190 new_depth_mask, i++,
527 new_total, 191 new_total,
528 cumul); 192 cumul,
193 left_margin);
529 } 194 }
530 ret += callchain__fprintf_graph(fp, child, new_total, 195 ret += __callchain__fprintf_graph(fp, child, new_total,
531 depth + 1, 196 depth + 1,
532 new_depth_mask | (1 << depth)); 197 new_depth_mask | (1 << depth),
198 left_margin);
533 node = next; 199 node = next;
534 } 200 }
535 201
@@ -543,9 +209,48 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
543 209
544 ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 210 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
545 new_depth_mask, 0, new_total, 211 new_depth_mask, 0, new_total,
546 remaining); 212 remaining, left_margin);
213 }
214
215 return ret;
216}
217
218
219static size_t
220callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
221 u64 total_samples, int left_margin)
222{
223 struct callchain_list *chain;
224 bool printed = false;
225 int i = 0;
226 int ret = 0;
227
228 list_for_each_entry(chain, &self->val, list) {
229 if (chain->ip >= PERF_CONTEXT_MAX)
230 continue;
231
232 if (!i++ && sort__first_dimension == SORT_SYM)
233 continue;
234
235 if (!printed) {
236 ret += callchain__fprintf_left_margin(fp, left_margin);
237 ret += fprintf(fp, "|\n");
238 ret += callchain__fprintf_left_margin(fp, left_margin);
239 ret += fprintf(fp, "---");
240
241 left_margin += 3;
242 printed = true;
243 } else
244 ret += callchain__fprintf_left_margin(fp, left_margin);
245
246 if (chain->sym)
247 ret += fprintf(fp, " %s\n", chain->sym->name);
248 else
249 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
547 } 250 }
548 251
252 ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
253
549 return ret; 254 return ret;
550} 255}
551 256
@@ -577,7 +282,7 @@ callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
577 282
578static size_t 283static size_t
579hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 284hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
580 u64 total_samples) 285 u64 total_samples, int left_margin)
581{ 286{
582 struct rb_node *rb_node; 287 struct rb_node *rb_node;
583 struct callchain_node *chain; 288 struct callchain_node *chain;
@@ -597,8 +302,8 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
597 break; 302 break;
598 case CHAIN_GRAPH_ABS: /* Falldown */ 303 case CHAIN_GRAPH_ABS: /* Falldown */
599 case CHAIN_GRAPH_REL: 304 case CHAIN_GRAPH_REL:
600 ret += callchain__fprintf_graph(fp, chain, 305 ret += callchain__fprintf_graph(fp, chain, total_samples,
601 total_samples, 1, 1); 306 left_margin);
602 case CHAIN_NONE: 307 case CHAIN_NONE:
603 default: 308 default:
604 break; 309 break;
@@ -610,7 +315,6 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
610 return ret; 315 return ret;
611} 316}
612 317
613
614static size_t 318static size_t
615hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 319hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
616{ 320{
@@ -644,8 +348,19 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
644 348
645 ret += fprintf(fp, "\n"); 349 ret += fprintf(fp, "\n");
646 350
647 if (callchain) 351 if (callchain) {
648 hist_entry_callchain__fprintf(fp, self, total_samples); 352 int left_margin = 0;
353
354 if (sort__first_dimension == SORT_COMM) {
355 se = list_first_entry(&hist_entry__sort_list, typeof(*se),
356 list);
357 left_margin = se->width ? *se->width : 0;
358 left_margin -= thread__comm_len(self->thread);
359 }
360
361 hist_entry_callchain__fprintf(fp, self, total_samples,
362 left_margin);
363 }
649 364
650 return ret; 365 return ret;
651} 366}
@@ -693,63 +408,6 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
693 return 0; 408 return 0;
694} 409}
695 410
696
697static struct symbol *
698resolve_symbol(struct thread *thread, struct map **mapp,
699 struct dso **dsop, u64 *ipp)
700{
701 struct dso *dso = dsop ? *dsop : NULL;
702 struct map *map = mapp ? *mapp : NULL;
703 u64 ip = *ipp;
704
705 if (!thread)
706 return NULL;
707
708 if (dso)
709 goto got_dso;
710
711 if (map)
712 goto got_map;
713
714 map = thread__find_map(thread, ip);
715 if (map != NULL) {
716 /*
717 * We have to do this here as we may have a dso
718 * with no symbol hit that has a name longer than
719 * the ones with symbols sampled.
720 */
721 if (!sort_dso.elide && !map->dso->slen_calculated)
722 dso__calc_col_width(map->dso);
723
724 if (mapp)
725 *mapp = map;
726got_map:
727 ip = map->map_ip(map, ip);
728
729 dso = map->dso;
730 } else {
731 /*
732 * If this is outside of all known maps,
733 * and is a negative address, try to look it
734 * up in the kernel dso, as it might be a
735 * vsyscall (which executes in user-mode):
736 */
737 if ((long long)ip < 0)
738 dso = kernel_dso;
739 }
740 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
741 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
742 *ipp = ip;
743
744 if (dsop)
745 *dsop = dso;
746
747 if (!dso)
748 return NULL;
749got_dso:
750 return dso->find_symbol(dso, ip);
751}
752
753static int call__match(struct symbol *sym) 411static int call__match(struct symbol *sym)
754{ 412{
755 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 413 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
@@ -758,11 +416,11 @@ static int call__match(struct symbol *sym)
758 return 0; 416 return 0;
759} 417}
760 418
761static struct symbol ** 419static struct symbol **resolve_callchain(struct thread *thread,
762resolve_callchain(struct thread *thread, struct map *map __used, 420 struct ip_callchain *chain,
763 struct ip_callchain *chain, struct hist_entry *entry) 421 struct symbol **parent)
764{ 422{
765 u64 context = PERF_CONTEXT_MAX; 423 u8 cpumode = PERF_RECORD_MISC_USER;
766 struct symbol **syms = NULL; 424 struct symbol **syms = NULL;
767 unsigned int i; 425 unsigned int i;
768 426
@@ -776,34 +434,31 @@ resolve_callchain(struct thread *thread, struct map *map __used,
776 434
777 for (i = 0; i < chain->nr; i++) { 435 for (i = 0; i < chain->nr; i++) {
778 u64 ip = chain->ips[i]; 436 u64 ip = chain->ips[i];
779 struct dso *dso = NULL; 437 struct addr_location al;
780 struct symbol *sym;
781 438
782 if (ip >= PERF_CONTEXT_MAX) { 439 if (ip >= PERF_CONTEXT_MAX) {
783 context = ip; 440 switch (ip) {
441 case PERF_CONTEXT_HV:
442 cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
443 case PERF_CONTEXT_KERNEL:
444 cpumode = PERF_RECORD_MISC_KERNEL; break;
445 case PERF_CONTEXT_USER:
446 cpumode = PERF_RECORD_MISC_USER; break;
447 default:
448 break;
449 }
784 continue; 450 continue;
785 } 451 }
786 452
787 switch (context) { 453 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
788 case PERF_CONTEXT_HV: 454 ip, &al, NULL);
789 dso = hypervisor_dso; 455 if (al.sym != NULL) {
790 break; 456 if (sort__has_parent && !*parent &&
791 case PERF_CONTEXT_KERNEL: 457 call__match(al.sym))
792 dso = kernel_dso; 458 *parent = al.sym;
793 break;
794 default:
795 break;
796 }
797
798 sym = resolve_symbol(thread, NULL, &dso, &ip);
799
800 if (sym) {
801 if (sort__has_parent && call__match(sym) &&
802 !entry->parent)
803 entry->parent = sym;
804 if (!callchain) 459 if (!callchain)
805 break; 460 break;
806 syms[i] = sym; 461 syms[i] = al.sym;
807 } 462 }
808 } 463 }
809 464
@@ -814,178 +469,33 @@ resolve_callchain(struct thread *thread, struct map *map __used,
814 * collect histogram counts 469 * collect histogram counts
815 */ 470 */
816 471
817static int 472static int hist_entry__add(struct addr_location *al,
818hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 473 struct ip_callchain *chain, u64 count)
819 struct symbol *sym, u64 ip, struct ip_callchain *chain,
820 char level, u64 count)
821{ 474{
822 struct rb_node **p = &hist.rb_node; 475 struct symbol **syms = NULL, *parent = NULL;
823 struct rb_node *parent = NULL; 476 bool hit;
824 struct hist_entry *he; 477 struct hist_entry *he;
825 struct symbol **syms = NULL;
826 struct hist_entry entry = {
827 .thread = thread,
828 .map = map,
829 .dso = dso,
830 .sym = sym,
831 .ip = ip,
832 .level = level,
833 .count = count,
834 .parent = NULL,
835 .sorted_chain = RB_ROOT
836 };
837 int cmp;
838 478
839 if ((sort__has_parent || callchain) && chain) 479 if ((sort__has_parent || callchain) && chain)
840 syms = resolve_callchain(thread, map, chain, &entry); 480 syms = resolve_callchain(al->thread, chain, &parent);
841 481
842 while (*p != NULL) { 482 he = __hist_entry__add(al, parent, count, &hit);
843 parent = *p; 483 if (he == NULL)
844 he = rb_entry(parent, struct hist_entry, rb_node); 484 return -ENOMEM;
845 485
846 cmp = hist_entry__cmp(&entry, he); 486 if (hit)
487 he->count += count;
847 488
848 if (!cmp) {
849 he->count += count;
850 if (callchain) {
851 append_chain(&he->callchain, chain, syms);
852 free(syms);
853 }
854 return 0;
855 }
856
857 if (cmp < 0)
858 p = &(*p)->rb_left;
859 else
860 p = &(*p)->rb_right;
861 }
862
863 he = malloc(sizeof(*he));
864 if (!he)
865 return -ENOMEM;
866 *he = entry;
867 if (callchain) { 489 if (callchain) {
868 callchain_init(&he->callchain); 490 if (!hit)
491 callchain_init(&he->callchain);
869 append_chain(&he->callchain, chain, syms); 492 append_chain(&he->callchain, chain, syms);
870 free(syms); 493 free(syms);
871 } 494 }
872 rb_link_node(&he->rb_node, parent, p);
873 rb_insert_color(&he->rb_node, &hist);
874 495
875 return 0; 496 return 0;
876} 497}
877 498
878static void hist_entry__free(struct hist_entry *he)
879{
880 free(he);
881}
882
883/*
884 * collapse the histogram
885 */
886
887static struct rb_root collapse_hists;
888
889static void collapse__insert_entry(struct hist_entry *he)
890{
891 struct rb_node **p = &collapse_hists.rb_node;
892 struct rb_node *parent = NULL;
893 struct hist_entry *iter;
894 int64_t cmp;
895
896 while (*p != NULL) {
897 parent = *p;
898 iter = rb_entry(parent, struct hist_entry, rb_node);
899
900 cmp = hist_entry__collapse(iter, he);
901
902 if (!cmp) {
903 iter->count += he->count;
904 hist_entry__free(he);
905 return;
906 }
907
908 if (cmp < 0)
909 p = &(*p)->rb_left;
910 else
911 p = &(*p)->rb_right;
912 }
913
914 rb_link_node(&he->rb_node, parent, p);
915 rb_insert_color(&he->rb_node, &collapse_hists);
916}
917
918static void collapse__resort(void)
919{
920 struct rb_node *next;
921 struct hist_entry *n;
922
923 if (!sort__need_collapse)
924 return;
925
926 next = rb_first(&hist);
927 while (next) {
928 n = rb_entry(next, struct hist_entry, rb_node);
929 next = rb_next(&n->rb_node);
930
931 rb_erase(&n->rb_node, &hist);
932 collapse__insert_entry(n);
933 }
934}
935
936/*
937 * reverse the map, sort on count.
938 */
939
940static struct rb_root output_hists;
941
942static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
943{
944 struct rb_node **p = &output_hists.rb_node;
945 struct rb_node *parent = NULL;
946 struct hist_entry *iter;
947
948 if (callchain)
949 callchain_param.sort(&he->sorted_chain, &he->callchain,
950 min_callchain_hits, &callchain_param);
951
952 while (*p != NULL) {
953 parent = *p;
954 iter = rb_entry(parent, struct hist_entry, rb_node);
955
956 if (he->count > iter->count)
957 p = &(*p)->rb_left;
958 else
959 p = &(*p)->rb_right;
960 }
961
962 rb_link_node(&he->rb_node, parent, p);
963 rb_insert_color(&he->rb_node, &output_hists);
964}
965
966static void output__resort(u64 total_samples)
967{
968 struct rb_node *next;
969 struct hist_entry *n;
970 struct rb_root *tree = &hist;
971 u64 min_callchain_hits;
972
973 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
974
975 if (sort__need_collapse)
976 tree = &collapse_hists;
977
978 next = rb_first(tree);
979
980 while (next) {
981 n = rb_entry(next, struct hist_entry, rb_node);
982 next = rb_next(&n->rb_node);
983
984 rb_erase(&n->rb_node, tree);
985 output__insert_entry(n, min_callchain_hits);
986 }
987}
988
989static size_t output__fprintf(FILE *fp, u64 total_samples) 499static size_t output__fprintf(FILE *fp, u64 total_samples)
990{ 500{
991 struct hist_entry *pos; 501 struct hist_entry *pos;
@@ -1080,13 +590,6 @@ print_entries:
1080 return ret; 590 return ret;
1081} 591}
1082 592
1083static unsigned long total = 0,
1084 total_mmap = 0,
1085 total_comm = 0,
1086 total_fork = 0,
1087 total_unknown = 0,
1088 total_lost = 0;
1089
1090static int validate_chain(struct ip_callchain *chain, event_t *event) 593static int validate_chain(struct ip_callchain *chain, event_t *event)
1091{ 594{
1092 unsigned int chain_size; 595 unsigned int chain_size;
@@ -1100,30 +603,22 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
1100 return 0; 603 return 0;
1101} 604}
1102 605
1103static int 606static int process_sample_event(event_t *event)
1104process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1105{ 607{
1106 char level;
1107 int show = 0;
1108 struct dso *dso = NULL;
1109 struct thread *thread;
1110 u64 ip = event->ip.ip; 608 u64 ip = event->ip.ip;
1111 u64 period = 1; 609 u64 period = 1;
1112 struct map *map = NULL;
1113 void *more_data = event->ip.__more_data; 610 void *more_data = event->ip.__more_data;
1114 struct ip_callchain *chain = NULL; 611 struct ip_callchain *chain = NULL;
1115 int cpumode; 612 int cpumode;
1116 613 struct addr_location al;
1117 thread = threads__findnew(event->ip.pid, &threads, &last_match); 614 struct thread *thread = threads__findnew(event->ip.pid);
1118 615
1119 if (sample_type & PERF_SAMPLE_PERIOD) { 616 if (sample_type & PERF_SAMPLE_PERIOD) {
1120 period = *(u64 *)more_data; 617 period = *(u64 *)more_data;
1121 more_data += sizeof(u64); 618 more_data += sizeof(u64);
1122 } 619 }
1123 620
1124 dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", 621 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
1125 (void *)(offset + head),
1126 (void *)(long)(event->header.size),
1127 event->header.misc, 622 event->header.misc,
1128 event->ip.pid, event->ip.tid, 623 event->ip.pid, event->ip.tid,
1129 (void *)(long)ip, 624 (void *)(long)ip,
@@ -1137,7 +632,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1137 dump_printf("... chain: nr:%Lu\n", chain->nr); 632 dump_printf("... chain: nr:%Lu\n", chain->nr);
1138 633
1139 if (validate_chain(chain, event) < 0) { 634 if (validate_chain(chain, event) < 0) {
1140 eprintf("call-chain problem with event, skipping it.\n"); 635 pr_debug("call-chain problem with event, "
636 "skipping it.\n");
1141 return 0; 637 return 0;
1142 } 638 }
1143 639
@@ -1147,163 +643,64 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1147 } 643 }
1148 } 644 }
1149 645
1150 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1151
1152 if (thread == NULL) { 646 if (thread == NULL) {
1153 eprintf("problem processing %d event, skipping it.\n", 647 pr_debug("problem processing %d event, skipping it.\n",
1154 event->header.type); 648 event->header.type);
1155 return -1; 649 return -1;
1156 } 650 }
1157 651
652 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
653
1158 if (comm_list && !strlist__has_entry(comm_list, thread->comm)) 654 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1159 return 0; 655 return 0;
1160 656
1161 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 657 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1162 658
1163 if (cpumode == PERF_RECORD_MISC_KERNEL) { 659 thread__find_addr_location(thread, cpumode,
1164 show = SHOW_KERNEL; 660 MAP__FUNCTION, ip, &al, NULL);
1165 level = 'k'; 661 /*
1166 662 * We have to do this here as we may have a dso with no symbol hit that
1167 dso = kernel_dso; 663 * has a name longer than the ones with symbols sampled.
1168 664 */
1169 dump_printf(" ...... dso: %s\n", dso->name); 665 if (al.map && !sort_dso.elide && !al.map->dso->slen_calculated)
1170 666 dso__calc_col_width(al.map->dso);
1171 } else if (cpumode == PERF_RECORD_MISC_USER) { 667
1172 668 if (dso_list &&
1173 show = SHOW_USER; 669 (!al.map || !al.map->dso ||
1174 level = '.'; 670 !(strlist__has_entry(dso_list, al.map->dso->short_name) ||
1175 671 (al.map->dso->short_name != al.map->dso->long_name &&
1176 } else { 672 strlist__has_entry(dso_list, al.map->dso->long_name)))))
1177 show = SHOW_HV; 673 return 0;
1178 level = 'H';
1179
1180 dso = hypervisor_dso;
1181
1182 dump_printf(" ...... dso: [hypervisor]\n");
1183 }
1184
1185 if (show & show_mask) {
1186 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1187
1188 if (dso_list && (!dso || !dso->name ||
1189 !strlist__has_entry(dso_list, dso->name)))
1190 return 0;
1191
1192 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
1193 return 0;
1194
1195 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
1196 eprintf("problem incrementing symbol count, skipping event\n");
1197 return -1;
1198 }
1199 }
1200 total += period;
1201
1202 return 0;
1203}
1204 674
1205static int 675 if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
1206process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1207{
1208 struct thread *thread;
1209 struct map *map = map__new(&event->mmap, cwd, cwdlen);
1210
1211 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
1212
1213 dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1214 (void *)(offset + head),
1215 (void *)(long)(event->header.size),
1216 event->mmap.pid,
1217 event->mmap.tid,
1218 (void *)(long)event->mmap.start,
1219 (void *)(long)event->mmap.len,
1220 (void *)(long)event->mmap.pgoff,
1221 event->mmap.filename);
1222
1223 if (thread == NULL || map == NULL) {
1224 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
1225 return 0; 676 return 0;
677
678 if (hist_entry__add(&al, chain, period)) {
679 pr_debug("problem incrementing symbol count, skipping event\n");
680 return -1;
1226 } 681 }
1227 682
1228 thread__insert_map(thread, map); 683 event__stats.total += period;
1229 total_mmap++;
1230 684
1231 return 0; 685 return 0;
1232} 686}
1233 687
1234static int 688static int process_comm_event(event_t *event)
1235process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1236{ 689{
1237 struct thread *thread; 690 struct thread *thread = threads__findnew(event->comm.pid);
1238
1239 thread = threads__findnew(event->comm.pid, &threads, &last_match);
1240 691
1241 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 692 dump_printf(": %s:%d\n", event->comm.comm, event->comm.pid);
1242 (void *)(offset + head),
1243 (void *)(long)(event->header.size),
1244 event->comm.comm, event->comm.pid);
1245 693
1246 if (thread == NULL || 694 if (thread == NULL ||
1247 thread__set_comm_adjust(thread, event->comm.comm)) { 695 thread__set_comm_adjust(thread, event->comm.comm)) {
1248 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 696 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
1249 return -1; 697 return -1;
1250 } 698 }
1251 total_comm++;
1252
1253 return 0;
1254}
1255
1256static int
1257process_task_event(event_t *event, unsigned long offset, unsigned long head)
1258{
1259 struct thread *thread;
1260 struct thread *parent;
1261
1262 thread = threads__findnew(event->fork.pid, &threads, &last_match);
1263 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
1264
1265 dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n",
1266 (void *)(offset + head),
1267 (void *)(long)(event->header.size),
1268 event->header.type == PERF_RECORD_FORK ? "FORK" : "EXIT",
1269 event->fork.pid, event->fork.tid,
1270 event->fork.ppid, event->fork.ptid);
1271
1272 /*
1273 * A thread clone will have the same PID for both
1274 * parent and child.
1275 */
1276 if (thread == parent)
1277 return 0;
1278
1279 if (event->header.type == PERF_RECORD_EXIT)
1280 return 0;
1281
1282 if (!thread || !parent || thread__fork(thread, parent)) {
1283 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1284 return -1;
1285 }
1286 total_fork++;
1287 699
1288 return 0; 700 return 0;
1289} 701}
1290 702
1291static int 703static int process_read_event(event_t *event)
1292process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1293{
1294 dump_printf("%p [%p]: PERF_RECORD_LOST: id:%Ld: lost:%Ld\n",
1295 (void *)(offset + head),
1296 (void *)(long)(event->header.size),
1297 event->lost.id,
1298 event->lost.lost);
1299
1300 total_lost += event->lost.lost;
1301
1302 return 0;
1303}
1304
1305static int
1306process_read_event(event_t *event, unsigned long offset, unsigned long head)
1307{ 704{
1308 struct perf_event_attr *attr; 705 struct perf_event_attr *attr;
1309 706
@@ -1319,238 +716,91 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head)
1319 event->read.value); 716 event->read.value);
1320 } 717 }
1321 718
1322 dump_printf("%p [%p]: PERF_RECORD_READ: %d %d %s %Lu\n", 719 dump_printf(": %d %d %s %Lu\n", event->read.pid, event->read.tid,
1323 (void *)(offset + head), 720 attr ? __event_name(attr->type, attr->config) : "FAIL",
1324 (void *)(long)(event->header.size), 721 event->read.value);
1325 event->read.pid,
1326 event->read.tid,
1327 attr ? __event_name(attr->type, attr->config)
1328 : "FAIL",
1329 event->read.value);
1330
1331 return 0;
1332}
1333
1334static int
1335process_event(event_t *event, unsigned long offset, unsigned long head)
1336{
1337 trace_event(event);
1338
1339 switch (event->header.type) {
1340 case PERF_RECORD_SAMPLE:
1341 return process_sample_event(event, offset, head);
1342
1343 case PERF_RECORD_MMAP:
1344 return process_mmap_event(event, offset, head);
1345
1346 case PERF_RECORD_COMM:
1347 return process_comm_event(event, offset, head);
1348
1349 case PERF_RECORD_FORK:
1350 case PERF_RECORD_EXIT:
1351 return process_task_event(event, offset, head);
1352
1353 case PERF_RECORD_LOST:
1354 return process_lost_event(event, offset, head);
1355
1356 case PERF_RECORD_READ:
1357 return process_read_event(event, offset, head);
1358
1359 /*
1360 * We dont process them right now but they are fine:
1361 */
1362
1363 case PERF_RECORD_THROTTLE:
1364 case PERF_RECORD_UNTHROTTLE:
1365 return 0;
1366
1367 default:
1368 return -1;
1369 }
1370 722
1371 return 0; 723 return 0;
1372} 724}
1373 725
1374static int __cmd_report(void) 726static int sample_type_check(u64 type)
1375{ 727{
1376 int ret, rc = EXIT_FAILURE; 728 sample_type = type;
1377 unsigned long offset = 0;
1378 unsigned long head, shift;
1379 struct stat input_stat;
1380 struct thread *idle;
1381 event_t *event;
1382 uint32_t size;
1383 char *buf;
1384
1385 idle = register_idle_thread(&threads, &last_match);
1386 thread__comm_adjust(idle);
1387
1388 if (show_threads)
1389 perf_read_values_init(&show_threads_values);
1390
1391 input = open(input_name, O_RDONLY);
1392 if (input < 0) {
1393 fprintf(stderr, " failed to open file: %s", input_name);
1394 if (!strcmp(input_name, "perf.data"))
1395 fprintf(stderr, " (try 'perf record' first)");
1396 fprintf(stderr, "\n");
1397 exit(-1);
1398 }
1399
1400 ret = fstat(input, &input_stat);
1401 if (ret < 0) {
1402 perror("failed to stat file");
1403 exit(-1);
1404 }
1405
1406 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
1407 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
1408 exit(-1);
1409 }
1410
1411 if (!input_stat.st_size) {
1412 fprintf(stderr, "zero-sized file, nothing to do!\n");
1413 exit(0);
1414 }
1415
1416 header = perf_header__read(input);
1417 head = header->data_offset;
1418
1419 sample_type = perf_header__sample_type(header);
1420 729
1421 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 730 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1422 if (sort__has_parent) { 731 if (sort__has_parent) {
1423 fprintf(stderr, "selected --sort parent, but no" 732 fprintf(stderr, "selected --sort parent, but no"
1424 " callchain data. Did you call" 733 " callchain data. Did you call"
1425 " perf record without -g?\n"); 734 " perf record without -g?\n");
1426 exit(-1); 735 return -1;
1427 } 736 }
1428 if (callchain) { 737 if (callchain) {
1429 fprintf(stderr, "selected -g but no callchain data." 738 fprintf(stderr, "selected -g but no callchain data."
1430 " Did you call perf record without" 739 " Did you call perf record without"
1431 " -g?\n"); 740 " -g?\n");
1432 exit(-1); 741 return -1;
1433 } 742 }
1434 } else if (callchain_param.mode != CHAIN_NONE && !callchain) { 743 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1435 callchain = 1; 744 callchain = 1;
1436 if (register_callchain_param(&callchain_param) < 0) { 745 if (register_callchain_param(&callchain_param) < 0) {
1437 fprintf(stderr, "Can't register callchain" 746 fprintf(stderr, "Can't register callchain"
1438 " params\n"); 747 " params\n");
1439 exit(-1); 748 return -1;
1440 } 749 }
1441 } 750 }
1442 751
1443 if (load_kernel() < 0) { 752 return 0;
1444 perror("failed to load kernel symbols"); 753}
1445 return EXIT_FAILURE;
1446 }
1447
1448 if (!full_paths) {
1449 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
1450 perror("failed to get the current directory");
1451 return EXIT_FAILURE;
1452 }
1453 cwdlen = strlen(cwd);
1454 } else {
1455 cwd = NULL;
1456 cwdlen = 0;
1457 }
1458
1459 shift = page_size * (head / page_size);
1460 offset += shift;
1461 head -= shift;
1462
1463remap:
1464 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1465 MAP_SHARED, input, offset);
1466 if (buf == MAP_FAILED) {
1467 perror("failed to mmap file");
1468 exit(-1);
1469 }
1470
1471more:
1472 event = (event_t *)(buf + head);
1473
1474 size = event->header.size;
1475 if (!size)
1476 size = 8;
1477
1478 if (head + event->header.size >= page_size * mmap_window) {
1479 int munmap_ret;
1480
1481 shift = page_size * (head / page_size);
1482
1483 munmap_ret = munmap(buf, page_size * mmap_window);
1484 assert(munmap_ret == 0);
1485
1486 offset += shift;
1487 head -= shift;
1488 goto remap;
1489 }
1490
1491 size = event->header.size;
1492
1493 dump_printf("\n%p [%p]: event: %d\n",
1494 (void *)(offset + head),
1495 (void *)(long)event->header.size,
1496 event->header.type);
1497
1498 if (!size || process_event(event, offset, head) < 0) {
1499
1500 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1501 (void *)(offset + head),
1502 (void *)(long)(event->header.size),
1503 event->header.type);
1504
1505 total_unknown++;
1506
1507 /*
1508 * assume we lost track of the stream, check alignment, and
1509 * increment a single u64 in the hope to catch on again 'soon'.
1510 */
1511 754
1512 if (unlikely(head & 7)) 755static struct perf_file_handler file_handler = {
1513 head &= ~7ULL; 756 .process_sample_event = process_sample_event,
757 .process_mmap_event = event__process_mmap,
758 .process_comm_event = process_comm_event,
759 .process_exit_event = event__process_task,
760 .process_fork_event = event__process_task,
761 .process_lost_event = event__process_lost,
762 .process_read_event = process_read_event,
763 .sample_type_check = sample_type_check,
764};
1514 765
1515 size = 8;
1516 }
1517 766
1518 head += size; 767static int __cmd_report(void)
768{
769 struct thread *idle;
770 int ret;
1519 771
1520 if (offset + head >= header->data_offset + header->data_size) 772 idle = register_idle_thread();
1521 goto done; 773 thread__comm_adjust(idle);
1522 774
1523 if (offset + head < (unsigned long)input_stat.st_size) 775 if (show_threads)
1524 goto more; 776 perf_read_values_init(&show_threads_values);
1525 777
1526done: 778 register_perf_file_handler(&file_handler);
1527 rc = EXIT_SUCCESS;
1528 close(input);
1529 779
1530 dump_printf(" IP events: %10ld\n", total); 780 ret = mmap_dispatch_perf_file(&header, input_name, force,
1531 dump_printf(" mmap events: %10ld\n", total_mmap); 781 full_paths, &event__cwdlen, &event__cwd);
1532 dump_printf(" comm events: %10ld\n", total_comm); 782 if (ret)
1533 dump_printf(" fork events: %10ld\n", total_fork); 783 return ret;
1534 dump_printf(" lost events: %10ld\n", total_lost);
1535 dump_printf(" unknown events: %10ld\n", total_unknown);
1536 784
1537 if (dump_trace) 785 if (dump_trace) {
786 event__print_totals();
1538 return 0; 787 return 0;
788 }
1539 789
1540 if (verbose >= 3) 790 if (verbose > 3)
1541 threads__fprintf(stdout, &threads); 791 threads__fprintf(stdout);
1542 792
1543 if (verbose >= 2) 793 if (verbose > 2)
1544 dsos__fprintf(stdout); 794 dsos__fprintf(stdout);
1545 795
1546 collapse__resort(); 796 collapse__resort();
1547 output__resort(total); 797 output__resort(event__stats.total);
1548 output__fprintf(stdout, total); 798 output__fprintf(stdout, event__stats.total);
1549 799
1550 if (show_threads) 800 if (show_threads)
1551 perf_read_values_destroy(&show_threads_values); 801 perf_read_values_destroy(&show_threads_values);
1552 802
1553 return rc; 803 return ret;
1554} 804}
1555 805
1556static int 806static int
@@ -1606,7 +856,8 @@ setup:
1606 return 0; 856 return 0;
1607} 857}
1608 858
1609static const char * const report_usage[] = { 859//static const char * const report_usage[] = {
860const char * const report_usage[] = {
1610 "perf report [<options>] <command>", 861 "perf report [<options>] <command>",
1611 NULL 862 NULL
1612}; 863};
@@ -1618,9 +869,10 @@ static const struct option options[] = {
1618 "be more verbose (show symbol address, etc)"), 869 "be more verbose (show symbol address, etc)"),
1619 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 870 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1620 "dump raw trace in ASCII"), 871 "dump raw trace in ASCII"),
1621 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 872 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
873 "file", "vmlinux pathname"),
1622 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 874 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1623 OPT_BOOLEAN('m', "modules", &modules, 875 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
1624 "load module symbols - WARNING: use only with -k and LIVE kernel"), 876 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1625 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, 877 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
1626 "Show a column with the number of samples"), 878 "Show a column with the number of samples"),
@@ -1690,9 +942,8 @@ static void setup_list(struct strlist **list, const char *list_str,
1690 942
1691int cmd_report(int argc, const char **argv, const char *prefix __used) 943int cmd_report(int argc, const char **argv, const char *prefix __used)
1692{ 944{
1693 symbol__init(); 945 if (symbol__init(&symbol_conf) < 0)
1694 946 return -1;
1695 page_size = getpagesize();
1696 947
1697 argc = parse_options(argc, argv, options, report_usage, 0); 948 argc = parse_options(argc, argv, options, report_usage, 0);
1698 949
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index ce2d5be4f30e..26b782f26ee1 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,7 @@
11#include "util/trace-event.h" 11#include "util/trace-event.h"
12 12
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/data_map.h"
14 15
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/prctl.h> 17#include <sys/prctl.h>
@@ -20,14 +21,6 @@
20#include <math.h> 21#include <math.h>
21 22
22static char const *input_name = "perf.data"; 23static char const *input_name = "perf.data";
23static int input;
24static unsigned long page_size;
25static unsigned long mmap_window = 32;
26
27static unsigned long total_comm = 0;
28
29static struct rb_root threads;
30static struct thread *last_match;
31 24
32static struct perf_header *header; 25static struct perf_header *header;
33static u64 sample_type; 26static u64 sample_type;
@@ -35,11 +28,11 @@ static u64 sample_type;
35static char default_sort_order[] = "avg, max, switch, runtime"; 28static char default_sort_order[] = "avg, max, switch, runtime";
36static char *sort_order = default_sort_order; 29static char *sort_order = default_sort_order;
37 30
31static int profile_cpu = -1;
32
38#define PR_SET_NAME 15 /* Set process name */ 33#define PR_SET_NAME 15 /* Set process name */
39#define MAX_CPUS 4096 34#define MAX_CPUS 4096
40 35
41#define BUG_ON(x) assert(!(x))
42
43static u64 run_measurement_overhead; 36static u64 run_measurement_overhead;
44static u64 sleep_measurement_overhead; 37static u64 sleep_measurement_overhead;
45 38
@@ -74,6 +67,7 @@ enum sched_event_type {
74 SCHED_EVENT_RUN, 67 SCHED_EVENT_RUN,
75 SCHED_EVENT_SLEEP, 68 SCHED_EVENT_SLEEP,
76 SCHED_EVENT_WAKEUP, 69 SCHED_EVENT_WAKEUP,
70 SCHED_EVENT_MIGRATION,
77}; 71};
78 72
79struct sched_atom { 73struct sched_atom {
@@ -226,7 +220,7 @@ static void calibrate_sleep_measurement_overhead(void)
226static struct sched_atom * 220static struct sched_atom *
227get_new_event(struct task_desc *task, u64 timestamp) 221get_new_event(struct task_desc *task, u64 timestamp)
228{ 222{
229 struct sched_atom *event = calloc(1, sizeof(*event)); 223 struct sched_atom *event = zalloc(sizeof(*event));
230 unsigned long idx = task->nr_events; 224 unsigned long idx = task->nr_events;
231 size_t size; 225 size_t size;
232 226
@@ -294,7 +288,7 @@ add_sched_event_wakeup(struct task_desc *task, u64 timestamp,
294 return; 288 return;
295 } 289 }
296 290
297 wakee_event->wait_sem = calloc(1, sizeof(*wakee_event->wait_sem)); 291 wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem));
298 sem_init(wakee_event->wait_sem, 0, 0); 292 sem_init(wakee_event->wait_sem, 0, 0);
299 wakee_event->specific_wait = 1; 293 wakee_event->specific_wait = 1;
300 event->wait_sem = wakee_event->wait_sem; 294 event->wait_sem = wakee_event->wait_sem;
@@ -324,7 +318,7 @@ static struct task_desc *register_pid(unsigned long pid, const char *comm)
324 if (task) 318 if (task)
325 return task; 319 return task;
326 320
327 task = calloc(1, sizeof(*task)); 321 task = zalloc(sizeof(*task));
328 task->pid = pid; 322 task->pid = pid;
329 task->nr = nr_tasks; 323 task->nr = nr_tasks;
330 strcpy(task->comm, comm); 324 strcpy(task->comm, comm);
@@ -398,6 +392,8 @@ process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
398 ret = sem_post(atom->wait_sem); 392 ret = sem_post(atom->wait_sem);
399 BUG_ON(ret); 393 BUG_ON(ret);
400 break; 394 break;
395 case SCHED_EVENT_MIGRATION:
396 break;
401 default: 397 default:
402 BUG_ON(1); 398 BUG_ON(1);
403 } 399 }
@@ -632,29 +628,6 @@ static void test_calibrations(void)
632 printf("the sleep test took %Ld nsecs\n", T1-T0); 628 printf("the sleep test took %Ld nsecs\n", T1-T0);
633} 629}
634 630
635static int
636process_comm_event(event_t *event, unsigned long offset, unsigned long head)
637{
638 struct thread *thread;
639
640 thread = threads__findnew(event->comm.pid, &threads, &last_match);
641
642 dump_printf("%p [%p]: perf_event_comm: %s:%d\n",
643 (void *)(offset + head),
644 (void *)(long)(event->header.size),
645 event->comm.comm, event->comm.pid);
646
647 if (thread == NULL ||
648 thread__set_comm(thread, event->comm.comm)) {
649 dump_printf("problem processing perf_event_comm, skipping event.\n");
650 return -1;
651 }
652 total_comm++;
653
654 return 0;
655}
656
657
658struct raw_event_sample { 631struct raw_event_sample {
659 u32 size; 632 u32 size;
660 char data[0]; 633 char data[0];
@@ -745,6 +718,22 @@ struct trace_fork_event {
745 u32 child_pid; 718 u32 child_pid;
746}; 719};
747 720
721struct trace_migrate_task_event {
722 u32 size;
723
724 u16 common_type;
725 u8 common_flags;
726 u8 common_preempt_count;
727 u32 common_pid;
728 u32 common_tgid;
729
730 char comm[16];
731 u32 pid;
732
733 u32 prio;
734 u32 cpu;
735};
736
748struct trace_sched_handler { 737struct trace_sched_handler {
749 void (*switch_event)(struct trace_switch_event *, 738 void (*switch_event)(struct trace_switch_event *,
750 struct event *, 739 struct event *,
@@ -769,6 +758,12 @@ struct trace_sched_handler {
769 int cpu, 758 int cpu,
770 u64 timestamp, 759 u64 timestamp,
771 struct thread *thread); 760 struct thread *thread);
761
762 void (*migrate_task_event)(struct trace_migrate_task_event *,
763 struct event *,
764 int cpu,
765 u64 timestamp,
766 struct thread *thread);
772}; 767};
773 768
774 769
@@ -941,9 +936,7 @@ __thread_latency_insert(struct rb_root *root, struct work_atoms *data,
941 936
942static void thread_atoms_insert(struct thread *thread) 937static void thread_atoms_insert(struct thread *thread)
943{ 938{
944 struct work_atoms *atoms; 939 struct work_atoms *atoms = zalloc(sizeof(*atoms));
945
946 atoms = calloc(sizeof(*atoms), 1);
947 if (!atoms) 940 if (!atoms)
948 die("No memory"); 941 die("No memory");
949 942
@@ -975,9 +968,7 @@ add_sched_out_event(struct work_atoms *atoms,
975 char run_state, 968 char run_state,
976 u64 timestamp) 969 u64 timestamp)
977{ 970{
978 struct work_atom *atom; 971 struct work_atom *atom = zalloc(sizeof(*atom));
979
980 atom = calloc(sizeof(*atom), 1);
981 if (!atom) 972 if (!atom)
982 die("Non memory"); 973 die("Non memory");
983 974
@@ -1058,8 +1049,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
1058 die("hm, delta: %Ld < 0 ?\n", delta); 1049 die("hm, delta: %Ld < 0 ?\n", delta);
1059 1050
1060 1051
1061 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1052 sched_out = threads__findnew(switch_event->prev_pid);
1062 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1053 sched_in = threads__findnew(switch_event->next_pid);
1063 1054
1064 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1055 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
1065 if (!out_events) { 1056 if (!out_events) {
@@ -1092,13 +1083,10 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
1092 u64 timestamp, 1083 u64 timestamp,
1093 struct thread *this_thread __used) 1084 struct thread *this_thread __used)
1094{ 1085{
1095 struct work_atoms *atoms; 1086 struct thread *thread = threads__findnew(runtime_event->pid);
1096 struct thread *thread; 1087 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1097 1088
1098 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1089 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
1099
1100 thread = threads__findnew(runtime_event->pid, &threads, &last_match);
1101 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1102 if (!atoms) { 1090 if (!atoms) {
1103 thread_atoms_insert(thread); 1091 thread_atoms_insert(thread);
1104 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1092 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
@@ -1125,7 +1113,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1125 if (!wakeup_event->success) 1113 if (!wakeup_event->success)
1126 return; 1114 return;
1127 1115
1128 wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); 1116 wakee = threads__findnew(wakeup_event->pid);
1129 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1117 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
1130 if (!atoms) { 1118 if (!atoms) {
1131 thread_atoms_insert(wakee); 1119 thread_atoms_insert(wakee);
@@ -1139,7 +1127,12 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1139 1127
1140 atom = list_entry(atoms->work_list.prev, struct work_atom, list); 1128 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1141 1129
1142 if (atom->state != THREAD_SLEEPING) 1130 /*
1131 * You WILL be missing events if you've recorded only
1132 * one CPU, or are only looking at only one, so don't
1133 * make useless noise.
1134 */
1135 if (profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1143 nr_state_machine_bugs++; 1136 nr_state_machine_bugs++;
1144 1137
1145 nr_timestamps++; 1138 nr_timestamps++;
@@ -1152,11 +1145,51 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1152 atom->wake_up_time = timestamp; 1145 atom->wake_up_time = timestamp;
1153} 1146}
1154 1147
1148static void
1149latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1150 struct event *__event __used,
1151 int cpu __used,
1152 u64 timestamp,
1153 struct thread *thread __used)
1154{
1155 struct work_atoms *atoms;
1156 struct work_atom *atom;
1157 struct thread *migrant;
1158
1159 /*
1160 * Only need to worry about migration when profiling one CPU.
1161 */
1162 if (profile_cpu == -1)
1163 return;
1164
1165 migrant = threads__findnew(migrate_task_event->pid);
1166 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1167 if (!atoms) {
1168 thread_atoms_insert(migrant);
1169 register_pid(migrant->pid, migrant->comm);
1170 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1171 if (!atoms)
1172 die("migration-event: Internal tree error");
1173 add_sched_out_event(atoms, 'R', timestamp);
1174 }
1175
1176 BUG_ON(list_empty(&atoms->work_list));
1177
1178 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1179 atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp;
1180
1181 nr_timestamps++;
1182
1183 if (atom->sched_out_time > timestamp)
1184 nr_unordered_timestamps++;
1185}
1186
1155static struct trace_sched_handler lat_ops = { 1187static struct trace_sched_handler lat_ops = {
1156 .wakeup_event = latency_wakeup_event, 1188 .wakeup_event = latency_wakeup_event,
1157 .switch_event = latency_switch_event, 1189 .switch_event = latency_switch_event,
1158 .runtime_event = latency_runtime_event, 1190 .runtime_event = latency_runtime_event,
1159 .fork_event = latency_fork_event, 1191 .fork_event = latency_fork_event,
1192 .migrate_task_event = latency_migrate_task_event,
1160}; 1193};
1161 1194
1162static void output_lat_thread(struct work_atoms *work_list) 1195static void output_lat_thread(struct work_atoms *work_list)
@@ -1385,8 +1418,8 @@ map_switch_event(struct trace_switch_event *switch_event,
1385 die("hm, delta: %Ld < 0 ?\n", delta); 1418 die("hm, delta: %Ld < 0 ?\n", delta);
1386 1419
1387 1420
1388 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1421 sched_out = threads__findnew(switch_event->prev_pid);
1389 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1422 sched_in = threads__findnew(switch_event->next_pid);
1390 1423
1391 curr_thread[this_cpu] = sched_in; 1424 curr_thread[this_cpu] = sched_in;
1392 1425
@@ -1517,6 +1550,26 @@ process_sched_exit_event(struct event *event,
1517} 1550}
1518 1551
1519static void 1552static void
1553process_sched_migrate_task_event(struct raw_event_sample *raw,
1554 struct event *event,
1555 int cpu __used,
1556 u64 timestamp __used,
1557 struct thread *thread __used)
1558{
1559 struct trace_migrate_task_event migrate_task_event;
1560
1561 FILL_COMMON_FIELDS(migrate_task_event, event, raw->data);
1562
1563 FILL_ARRAY(migrate_task_event, comm, event, raw->data);
1564 FILL_FIELD(migrate_task_event, pid, event, raw->data);
1565 FILL_FIELD(migrate_task_event, prio, event, raw->data);
1566 FILL_FIELD(migrate_task_event, cpu, event, raw->data);
1567
1568 if (trace_handler->migrate_task_event)
1569 trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread);
1570}
1571
1572static void
1520process_raw_event(event_t *raw_event __used, void *more_data, 1573process_raw_event(event_t *raw_event __used, void *more_data,
1521 int cpu, u64 timestamp, struct thread *thread) 1574 int cpu, u64 timestamp, struct thread *thread)
1522{ 1575{
@@ -1539,23 +1592,23 @@ process_raw_event(event_t *raw_event __used, void *more_data,
1539 process_sched_fork_event(raw, event, cpu, timestamp, thread); 1592 process_sched_fork_event(raw, event, cpu, timestamp, thread);
1540 if (!strcmp(event->name, "sched_process_exit")) 1593 if (!strcmp(event->name, "sched_process_exit"))
1541 process_sched_exit_event(event, cpu, timestamp, thread); 1594 process_sched_exit_event(event, cpu, timestamp, thread);
1595 if (!strcmp(event->name, "sched_migrate_task"))
1596 process_sched_migrate_task_event(raw, event, cpu, timestamp, thread);
1542} 1597}
1543 1598
1544static int 1599static int process_sample_event(event_t *event)
1545process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1546{ 1600{
1547 char level;
1548 int show = 0;
1549 struct dso *dso = NULL;
1550 struct thread *thread; 1601 struct thread *thread;
1551 u64 ip = event->ip.ip; 1602 u64 ip = event->ip.ip;
1552 u64 timestamp = -1; 1603 u64 timestamp = -1;
1553 u32 cpu = -1; 1604 u32 cpu = -1;
1554 u64 period = 1; 1605 u64 period = 1;
1555 void *more_data = event->ip.__more_data; 1606 void *more_data = event->ip.__more_data;
1556 int cpumode;
1557 1607
1558 thread = threads__findnew(event->ip.pid, &threads, &last_match); 1608 if (!(sample_type & PERF_SAMPLE_RAW))
1609 return 0;
1610
1611 thread = threads__findnew(event->ip.pid);
1559 1612
1560 if (sample_type & PERF_SAMPLE_TIME) { 1613 if (sample_type & PERF_SAMPLE_TIME) {
1561 timestamp = *(u64 *)more_data; 1614 timestamp = *(u64 *)more_data;
@@ -1573,177 +1626,64 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1573 more_data += sizeof(u64); 1626 more_data += sizeof(u64);
1574 } 1627 }
1575 1628
1576 dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", 1629 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
1577 (void *)(offset + head),
1578 (void *)(long)(event->header.size),
1579 event->header.misc, 1630 event->header.misc,
1580 event->ip.pid, event->ip.tid, 1631 event->ip.pid, event->ip.tid,
1581 (void *)(long)ip, 1632 (void *)(long)ip,
1582 (long long)period); 1633 (long long)period);
1583 1634
1584 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1585
1586 if (thread == NULL) { 1635 if (thread == NULL) {
1587 eprintf("problem processing %d event, skipping it.\n", 1636 pr_debug("problem processing %d event, skipping it.\n",
1588 event->header.type); 1637 event->header.type);
1589 return -1; 1638 return -1;
1590 } 1639 }
1591 1640
1592 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1641 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1593
1594 if (cpumode == PERF_RECORD_MISC_KERNEL) {
1595 show = SHOW_KERNEL;
1596 level = 'k';
1597
1598 dso = kernel_dso;
1599
1600 dump_printf(" ...... dso: %s\n", dso->name);
1601
1602 } else if (cpumode == PERF_RECORD_MISC_USER) {
1603
1604 show = SHOW_USER;
1605 level = '.';
1606
1607 } else {
1608 show = SHOW_HV;
1609 level = 'H';
1610
1611 dso = hypervisor_dso;
1612 1642
1613 dump_printf(" ...... dso: [hypervisor]\n"); 1643 if (profile_cpu != -1 && profile_cpu != (int) cpu)
1614 } 1644 return 0;
1615 1645
1616 if (sample_type & PERF_SAMPLE_RAW) 1646 process_raw_event(event, more_data, cpu, timestamp, thread);
1617 process_raw_event(event, more_data, cpu, timestamp, thread);
1618 1647
1619 return 0; 1648 return 0;
1620} 1649}
1621 1650
1622static int 1651static int process_lost_event(event_t *event __used)
1623process_event(event_t *event, unsigned long offset, unsigned long head)
1624{ 1652{
1625 trace_event(event); 1653 nr_lost_chunks++;
1626 1654 nr_lost_events += event->lost.lost;
1627 nr_events++;
1628 switch (event->header.type) {
1629 case PERF_RECORD_MMAP:
1630 return 0;
1631 case PERF_RECORD_LOST:
1632 nr_lost_chunks++;
1633 nr_lost_events += event->lost.lost;
1634 return 0;
1635
1636 case PERF_RECORD_COMM:
1637 return process_comm_event(event, offset, head);
1638 1655
1639 case PERF_RECORD_EXIT ... PERF_RECORD_READ: 1656 return 0;
1640 return 0; 1657}
1641 1658
1642 case PERF_RECORD_SAMPLE: 1659static int sample_type_check(u64 type)
1643 return process_sample_event(event, offset, head); 1660{
1661 sample_type = type;
1644 1662
1645 case PERF_RECORD_MAX: 1663 if (!(sample_type & PERF_SAMPLE_RAW)) {
1646 default: 1664 fprintf(stderr,
1665 "No trace sample to read. Did you call perf record "
1666 "without -R?");
1647 return -1; 1667 return -1;
1648 } 1668 }
1649 1669
1650 return 0; 1670 return 0;
1651} 1671}
1652 1672
1673static struct perf_file_handler file_handler = {
1674 .process_sample_event = process_sample_event,
1675 .process_comm_event = event__process_comm,
1676 .process_lost_event = process_lost_event,
1677 .sample_type_check = sample_type_check,
1678};
1679
1653static int read_events(void) 1680static int read_events(void)
1654{ 1681{
1655 int ret, rc = EXIT_FAILURE; 1682 register_idle_thread();
1656 unsigned long offset = 0; 1683 register_perf_file_handler(&file_handler);
1657 unsigned long head = 0;
1658 struct stat perf_stat;
1659 event_t *event;
1660 uint32_t size;
1661 char *buf;
1662
1663 trace_report();
1664 register_idle_thread(&threads, &last_match);
1665
1666 input = open(input_name, O_RDONLY);
1667 if (input < 0) {
1668 perror("failed to open file");
1669 exit(-1);
1670 }
1671
1672 ret = fstat(input, &perf_stat);
1673 if (ret < 0) {
1674 perror("failed to stat file");
1675 exit(-1);
1676 }
1677
1678 if (!perf_stat.st_size) {
1679 fprintf(stderr, "zero-sized file, nothing to do!\n");
1680 exit(0);
1681 }
1682 header = perf_header__read(input);
1683 head = header->data_offset;
1684 sample_type = perf_header__sample_type(header);
1685
1686 if (!(sample_type & PERF_SAMPLE_RAW))
1687 die("No trace sample to read. Did you call perf record "
1688 "without -R?");
1689
1690 if (load_kernel() < 0) {
1691 perror("failed to load kernel symbols");
1692 return EXIT_FAILURE;
1693 }
1694
1695remap:
1696 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1697 MAP_SHARED, input, offset);
1698 if (buf == MAP_FAILED) {
1699 perror("failed to mmap file");
1700 exit(-1);
1701 }
1702
1703more:
1704 event = (event_t *)(buf + head);
1705
1706 size = event->header.size;
1707 if (!size)
1708 size = 8;
1709
1710 if (head + event->header.size >= page_size * mmap_window) {
1711 unsigned long shift = page_size * (head / page_size);
1712 int res;
1713
1714 res = munmap(buf, page_size * mmap_window);
1715 assert(res == 0);
1716
1717 offset += shift;
1718 head -= shift;
1719 goto remap;
1720 }
1721
1722 size = event->header.size;
1723
1724
1725 if (!size || process_event(event, offset, head) < 0) {
1726
1727 /*
1728 * assume we lost track of the stream, check alignment, and
1729 * increment a single u64 in the hope to catch on again 'soon'.
1730 */
1731
1732 if (unlikely(head & 7))
1733 head &= ~7ULL;
1734
1735 size = 8;
1736 }
1737
1738 head += size;
1739
1740 if (offset + head < (unsigned long)perf_stat.st_size)
1741 goto more;
1742
1743 rc = EXIT_SUCCESS;
1744 close(input);
1745 1684
1746 return rc; 1685 return mmap_dispatch_perf_file(&header, input_name, 0, 0,
1686 &event__cwdlen, &event__cwd);
1747} 1687}
1748 1688
1749static void print_bad_events(void) 1689static void print_bad_events(void)
@@ -1883,6 +1823,8 @@ static const struct option latency_options[] = {
1883 "sort by key(s): runtime, switch, avg, max"), 1823 "sort by key(s): runtime, switch, avg, max"),
1884 OPT_BOOLEAN('v', "verbose", &verbose, 1824 OPT_BOOLEAN('v', "verbose", &verbose,
1885 "be more verbose (show symbol address, etc)"), 1825 "be more verbose (show symbol address, etc)"),
1826 OPT_INTEGER('C', "CPU", &profile_cpu,
1827 "CPU to profile on"),
1886 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1828 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1887 "dump raw trace in ASCII"), 1829 "dump raw trace in ASCII"),
1888 OPT_END() 1830 OPT_END()
@@ -1960,8 +1902,7 @@ static int __cmd_record(int argc, const char **argv)
1960 1902
1961int cmd_sched(int argc, const char **argv, const char *prefix __used) 1903int cmd_sched(int argc, const char **argv, const char *prefix __used)
1962{ 1904{
1963 symbol__init(); 1905 symbol__init(0);
1964 page_size = getpagesize();
1965 1906
1966 argc = parse_options(argc, argv, sched_options, sched_usage, 1907 argc = parse_options(argc, argv, sched_options, sched_usage,
1967 PARSE_OPT_STOP_AT_NON_OPTION); 1908 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3db31e7bf173..c70d72003557 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -50,15 +50,17 @@
50 50
51static struct perf_event_attr default_attrs[] = { 51static struct perf_event_attr default_attrs[] = {
52 52
53 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 53 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
54 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 54 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
55 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 55 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
56 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 56 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
57 57
58 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 58 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
59 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 59 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
60 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES}, 60 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
61 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 61 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
62 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES },
63 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES },
62 64
63}; 65};
64 66
@@ -125,6 +127,7 @@ struct stats event_res_stats[MAX_COUNTERS][3];
125struct stats runtime_nsecs_stats; 127struct stats runtime_nsecs_stats;
126struct stats walltime_nsecs_stats; 128struct stats walltime_nsecs_stats;
127struct stats runtime_cycles_stats; 129struct stats runtime_cycles_stats;
130struct stats runtime_branches_stats;
128 131
129#define MATCH_EVENT(t, c, counter) \ 132#define MATCH_EVENT(t, c, counter) \
130 (attrs[counter].type == PERF_TYPE_##t && \ 133 (attrs[counter].type == PERF_TYPE_##t && \
@@ -235,6 +238,8 @@ static void read_counter(int counter)
235 update_stats(&runtime_nsecs_stats, count[0]); 238 update_stats(&runtime_nsecs_stats, count[0]);
236 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) 239 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
237 update_stats(&runtime_cycles_stats, count[0]); 240 update_stats(&runtime_cycles_stats, count[0]);
241 if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
242 update_stats(&runtime_branches_stats, count[0]);
238} 243}
239 244
240static int run_perf_stat(int argc __used, const char **argv) 245static int run_perf_stat(int argc __used, const char **argv)
@@ -352,7 +357,16 @@ static void abs_printout(int counter, double avg)
352 ratio = avg / total; 357 ratio = avg / total;
353 358
354 fprintf(stderr, " # %10.3f IPC ", ratio); 359 fprintf(stderr, " # %10.3f IPC ", ratio);
355 } else { 360 } else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter) &&
361 runtime_branches_stats.n != 0) {
362 total = avg_stats(&runtime_branches_stats);
363
364 if (total)
365 ratio = avg * 100 / total;
366
367 fprintf(stderr, " # %10.3f %% ", ratio);
368
369 } else if (runtime_nsecs_stats.n != 0) {
356 total = avg_stats(&runtime_nsecs_stats); 370 total = avg_stats(&runtime_nsecs_stats);
357 371
358 if (total) 372 if (total)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index e8a510d935e5..cb58b6605fcc 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -29,14 +29,14 @@
29#include "util/header.h" 29#include "util/header.h"
30#include "util/parse-options.h" 30#include "util/parse-options.h"
31#include "util/parse-events.h" 31#include "util/parse-events.h"
32#include "util/event.h"
33#include "util/data_map.h"
32#include "util/svghelper.h" 34#include "util/svghelper.h"
33 35
34static char const *input_name = "perf.data"; 36static char const *input_name = "perf.data";
35static char const *output_name = "output.svg"; 37static char const *output_name = "output.svg";
36 38
37 39
38static unsigned long page_size;
39static unsigned long mmap_window = 32;
40static u64 sample_type; 40static u64 sample_type;
41 41
42static unsigned int numcpus; 42static unsigned int numcpus;
@@ -49,8 +49,6 @@ static u64 first_time, last_time;
49static int power_only; 49static int power_only;
50 50
51 51
52static struct perf_header *header;
53
54struct per_pid; 52struct per_pid;
55struct per_pidcomm; 53struct per_pidcomm;
56 54
@@ -153,6 +151,17 @@ static struct wake_event *wake_events;
153 151
154struct sample_wrapper *all_samples; 152struct sample_wrapper *all_samples;
155 153
154
155struct process_filter;
156struct process_filter {
157 char *name;
158 int pid;
159 struct process_filter *next;
160};
161
162static struct process_filter *process_filter;
163
164
156static struct per_pid *find_create_pid(int pid) 165static struct per_pid *find_create_pid(int pid)
157{ 166{
158 struct per_pid *cursor = all_data; 167 struct per_pid *cursor = all_data;
@@ -763,11 +772,11 @@ static void draw_wakeups(void)
763 c = p->all; 772 c = p->all;
764 while (c) { 773 while (c) {
765 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { 774 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
766 if (p->pid == we->waker) { 775 if (p->pid == we->waker && !from) {
767 from = c->Y; 776 from = c->Y;
768 task_from = strdup(c->comm); 777 task_from = strdup(c->comm);
769 } 778 }
770 if (p->pid == we->wakee) { 779 if (p->pid == we->wakee && !to) {
771 to = c->Y; 780 to = c->Y;
772 task_to = strdup(c->comm); 781 task_to = strdup(c->comm);
773 } 782 }
@@ -882,12 +891,89 @@ static void draw_process_bars(void)
882 } 891 }
883} 892}
884 893
894static void add_process_filter(const char *string)
895{
896 struct process_filter *filt;
897 int pid;
898
899 pid = strtoull(string, NULL, 10);
900 filt = malloc(sizeof(struct process_filter));
901 if (!filt)
902 return;
903
904 filt->name = strdup(string);
905 filt->pid = pid;
906 filt->next = process_filter;
907
908 process_filter = filt;
909}
910
911static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
912{
913 struct process_filter *filt;
914 if (!process_filter)
915 return 1;
916
917 filt = process_filter;
918 while (filt) {
919 if (filt->pid && p->pid == filt->pid)
920 return 1;
921 if (strcmp(filt->name, c->comm) == 0)
922 return 1;
923 filt = filt->next;
924 }
925 return 0;
926}
927
928static int determine_display_tasks_filtered(void)
929{
930 struct per_pid *p;
931 struct per_pidcomm *c;
932 int count = 0;
933
934 p = all_data;
935 while (p) {
936 p->display = 0;
937 if (p->start_time == 1)
938 p->start_time = first_time;
939
940 /* no exit marker, task kept running to the end */
941 if (p->end_time == 0)
942 p->end_time = last_time;
943
944 c = p->all;
945
946 while (c) {
947 c->display = 0;
948
949 if (c->start_time == 1)
950 c->start_time = first_time;
951
952 if (passes_filter(p, c)) {
953 c->display = 1;
954 p->display = 1;
955 count++;
956 }
957
958 if (c->end_time == 0)
959 c->end_time = last_time;
960
961 c = c->next;
962 }
963 p = p->next;
964 }
965 return count;
966}
967
885static int determine_display_tasks(u64 threshold) 968static int determine_display_tasks(u64 threshold)
886{ 969{
887 struct per_pid *p; 970 struct per_pid *p;
888 struct per_pidcomm *c; 971 struct per_pidcomm *c;
889 int count = 0; 972 int count = 0;
890 973
974 if (process_filter)
975 return determine_display_tasks_filtered();
976
891 p = all_data; 977 p = all_data;
892 while (p) { 978 while (p) {
893 p->display = 0; 979 p->display = 0;
@@ -957,36 +1043,6 @@ static void write_svg_file(const char *filename)
957 svg_close(); 1043 svg_close();
958} 1044}
959 1045
960static int
961process_event(event_t *event)
962{
963
964 switch (event->header.type) {
965
966 case PERF_RECORD_COMM:
967 return process_comm_event(event);
968 case PERF_RECORD_FORK:
969 return process_fork_event(event);
970 case PERF_RECORD_EXIT:
971 return process_exit_event(event);
972 case PERF_RECORD_SAMPLE:
973 return queue_sample_event(event);
974
975 /*
976 * We dont process them right now but they are fine:
977 */
978 case PERF_RECORD_MMAP:
979 case PERF_RECORD_THROTTLE:
980 case PERF_RECORD_UNTHROTTLE:
981 return 0;
982
983 default:
984 return -1;
985 }
986
987 return 0;
988}
989
990static void process_samples(void) 1046static void process_samples(void)
991{ 1047{
992 struct sample_wrapper *cursor; 1048 struct sample_wrapper *cursor;
@@ -1002,107 +1058,38 @@ static void process_samples(void)
1002 } 1058 }
1003} 1059}
1004 1060
1005 1061static int sample_type_check(u64 type)
1006static int __cmd_timechart(void)
1007{ 1062{
1008 int ret, rc = EXIT_FAILURE; 1063 sample_type = type;
1009 unsigned long offset = 0;
1010 unsigned long head, shift;
1011 struct stat statbuf;
1012 event_t *event;
1013 uint32_t size;
1014 char *buf;
1015 int input;
1016
1017 input = open(input_name, O_RDONLY);
1018 if (input < 0) {
1019 fprintf(stderr, " failed to open file: %s", input_name);
1020 if (!strcmp(input_name, "perf.data"))
1021 fprintf(stderr, " (try 'perf record' first)");
1022 fprintf(stderr, "\n");
1023 exit(-1);
1024 }
1025
1026 ret = fstat(input, &statbuf);
1027 if (ret < 0) {
1028 perror("failed to stat file");
1029 exit(-1);
1030 }
1031
1032 if (!statbuf.st_size) {
1033 fprintf(stderr, "zero-sized file, nothing to do!\n");
1034 exit(0);
1035 }
1036
1037 header = perf_header__read(input);
1038 head = header->data_offset;
1039
1040 sample_type = perf_header__sample_type(header);
1041 1064
1042 shift = page_size * (head / page_size); 1065 if (!(sample_type & PERF_SAMPLE_RAW)) {
1043 offset += shift; 1066 fprintf(stderr, "No trace samples found in the file.\n"
1044 head -= shift; 1067 "Have you used 'perf timechart record' to record it?\n");
1045 1068 return -1;
1046remap:
1047 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1048 MAP_SHARED, input, offset);
1049 if (buf == MAP_FAILED) {
1050 perror("failed to mmap file");
1051 exit(-1);
1052 }
1053
1054more:
1055 event = (event_t *)(buf + head);
1056
1057 size = event->header.size;
1058 if (!size)
1059 size = 8;
1060
1061 if (head + event->header.size >= page_size * mmap_window) {
1062 int ret2;
1063
1064 shift = page_size * (head / page_size);
1065
1066 ret2 = munmap(buf, page_size * mmap_window);
1067 assert(ret2 == 0);
1068
1069 offset += shift;
1070 head -= shift;
1071 goto remap;
1072 }
1073
1074 size = event->header.size;
1075
1076 if (!size || process_event(event) < 0) {
1077
1078 printf("%p [%p]: skipping unknown header type: %d\n",
1079 (void *)(offset + head),
1080 (void *)(long)(event->header.size),
1081 event->header.type);
1082
1083 /*
1084 * assume we lost track of the stream, check alignment, and
1085 * increment a single u64 in the hope to catch on again 'soon'.
1086 */
1087
1088 if (unlikely(head & 7))
1089 head &= ~7ULL;
1090
1091 size = 8;
1092 } 1069 }
1093 1070
1094 head += size; 1071 return 0;
1072}
1095 1073
1096 if (offset + head >= header->data_offset + header->data_size) 1074static struct perf_file_handler file_handler = {
1097 goto done; 1075 .process_comm_event = process_comm_event,
1076 .process_fork_event = process_fork_event,
1077 .process_exit_event = process_exit_event,
1078 .process_sample_event = queue_sample_event,
1079 .sample_type_check = sample_type_check,
1080};
1098 1081
1099 if (offset + head < (unsigned long)statbuf.st_size) 1082static int __cmd_timechart(void)
1100 goto more; 1083{
1084 struct perf_header *header;
1085 int ret;
1101 1086
1102done: 1087 register_perf_file_handler(&file_handler);
1103 rc = EXIT_SUCCESS;
1104 close(input);
1105 1088
1089 ret = mmap_dispatch_perf_file(&header, input_name, 0, 0,
1090 &event__cwdlen, &event__cwd);
1091 if (ret)
1092 return EXIT_FAILURE;
1106 1093
1107 process_samples(); 1094 process_samples();
1108 1095
@@ -1112,9 +1099,10 @@ done:
1112 1099
1113 write_svg_file(output_name); 1100 write_svg_file(output_name);
1114 1101
1115 printf("Written %2.1f seconds of trace to %s.\n", (last_time - first_time) / 1000000000.0, output_name); 1102 pr_info("Written %2.1f seconds of trace to %s.\n",
1103 (last_time - first_time) / 1000000000.0, output_name);
1116 1104
1117 return rc; 1105 return EXIT_SUCCESS;
1118} 1106}
1119 1107
1120static const char * const timechart_usage[] = { 1108static const char * const timechart_usage[] = {
@@ -1153,6 +1141,14 @@ static int __cmd_record(int argc, const char **argv)
1153 return cmd_record(i, rec_argv, NULL); 1141 return cmd_record(i, rec_argv, NULL);
1154} 1142}
1155 1143
1144static int
1145parse_process(const struct option *opt __used, const char *arg, int __used unset)
1146{
1147 if (arg)
1148 add_process_filter(arg);
1149 return 0;
1150}
1151
1156static const struct option options[] = { 1152static const struct option options[] = {
1157 OPT_STRING('i', "input", &input_name, "file", 1153 OPT_STRING('i', "input", &input_name, "file",
1158 "input file name"), 1154 "input file name"),
@@ -1160,17 +1156,18 @@ static const struct option options[] = {
1160 "output file name"), 1156 "output file name"),
1161 OPT_INTEGER('w', "width", &svg_page_width, 1157 OPT_INTEGER('w', "width", &svg_page_width,
1162 "page width"), 1158 "page width"),
1163 OPT_BOOLEAN('p', "power-only", &power_only, 1159 OPT_BOOLEAN('P', "power-only", &power_only,
1164 "output power data only"), 1160 "output power data only"),
1161 OPT_CALLBACK('p', "process", NULL, "process",
1162 "process selector. Pass a pid or process name.",
1163 parse_process),
1165 OPT_END() 1164 OPT_END()
1166}; 1165};
1167 1166
1168 1167
1169int cmd_timechart(int argc, const char **argv, const char *prefix __used) 1168int cmd_timechart(int argc, const char **argv, const char *prefix __used)
1170{ 1169{
1171 symbol__init(); 1170 symbol__init(0);
1172
1173 page_size = getpagesize();
1174 1171
1175 argc = parse_options(argc, argv, options, timechart_usage, 1172 argc = parse_options(argc, argv, options, timechart_usage,
1176 PARSE_OPT_STOP_AT_NON_OPTION); 1173 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e23bc74e734f..e0a374d0e43a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -54,26 +55,31 @@
54 55
55static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 56static int fd[MAX_NR_CPUS][MAX_COUNTERS];
56 57
57static int system_wide = 0; 58static int system_wide = 0;
58 59
59static int default_interval = 100000; 60static int default_interval = 0;
60 61
61static int count_filter = 5; 62static int count_filter = 5;
62static int print_entries = 15; 63static int print_entries;
63 64
64static int target_pid = -1; 65static int target_pid = -1;
65static int inherit = 0; 66static int inherit = 0;
66static int profile_cpu = -1; 67static int profile_cpu = -1;
67static int nr_cpus = 0; 68static int nr_cpus = 0;
68static unsigned int realtime_prio = 0; 69static unsigned int realtime_prio = 0;
69static int group = 0; 70static int group = 0;
70static unsigned int page_size; 71static unsigned int page_size;
71static unsigned int mmap_pages = 16; 72static unsigned int mmap_pages = 16;
72static int freq = 0; 73static int freq = 1000; /* 1 KHz */
73 74
74static int delay_secs = 2; 75static int delay_secs = 2;
75static int zero; 76static int zero = 0;
76static int dump_symtab; 77static int dump_symtab = 0;
78
79static bool hide_kernel_symbols = false;
80static bool hide_user_symbols = false;
81static struct winsize winsize;
82struct symbol_conf symbol_conf;
77 83
78/* 84/*
79 * Source 85 * Source
@@ -86,83 +92,126 @@ struct source_line {
86 struct source_line *next; 92 struct source_line *next;
87}; 93};
88 94
89static char *sym_filter = NULL; 95static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL; 96struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5; 97static int sym_pcnt_filter = 5;
92static int sym_counter = 0; 98static int sym_counter = 0;
93static int display_weighted = -1; 99static int display_weighted = -1;
94 100
95/* 101/*
96 * Symbols 102 * Symbols
97 */ 103 */
98 104
99static u64 min_ip; 105struct sym_entry_source {
100static u64 max_ip = -1ll; 106 struct source_line *source;
107 struct source_line *lines;
108 struct source_line **lines_tail;
109 pthread_mutex_t lock;
110};
101 111
102struct sym_entry { 112struct sym_entry {
103 struct rb_node rb_node; 113 struct rb_node rb_node;
104 struct list_head node; 114 struct list_head node;
105 unsigned long count[MAX_COUNTERS];
106 unsigned long snap_count; 115 unsigned long snap_count;
107 double weight; 116 double weight;
108 int skip; 117 int skip;
109 struct source_line *source; 118 u16 name_len;
110 struct source_line *lines; 119 u8 origin;
111 struct source_line **lines_tail; 120 struct map *map;
112 pthread_mutex_t source_lock; 121 struct sym_entry_source *src;
122 unsigned long count[0];
113}; 123};
114 124
115/* 125/*
116 * Source functions 126 * Source functions
117 */ 127 */
118 128
129static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
130{
131 return ((void *)self) + symbol_conf.priv_size;
132}
133
134static void get_term_dimensions(struct winsize *ws)
135{
136 char *s = getenv("LINES");
137
138 if (s != NULL) {
139 ws->ws_row = atoi(s);
140 s = getenv("COLUMNS");
141 if (s != NULL) {
142 ws->ws_col = atoi(s);
143 if (ws->ws_row && ws->ws_col)
144 return;
145 }
146 }
147#ifdef TIOCGWINSZ
148 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
149 ws->ws_row && ws->ws_col)
150 return;
151#endif
152 ws->ws_row = 25;
153 ws->ws_col = 80;
154}
155
156static void update_print_entries(struct winsize *ws)
157{
158 print_entries = ws->ws_row;
159
160 if (print_entries > 9)
161 print_entries -= 9;
162}
163
164static void sig_winch_handler(int sig __used)
165{
166 get_term_dimensions(&winsize);
167 update_print_entries(&winsize);
168}
169
119static void parse_source(struct sym_entry *syme) 170static void parse_source(struct sym_entry *syme)
120{ 171{
121 struct symbol *sym; 172 struct symbol *sym;
122 struct module *module; 173 struct sym_entry_source *source;
123 struct section *section = NULL; 174 struct map *map;
124 FILE *file; 175 FILE *file;
125 char command[PATH_MAX*2]; 176 char command[PATH_MAX*2];
126 const char *path = vmlinux_name; 177 const char *path;
127 u64 start, end, len; 178 u64 len;
128 179
129 if (!syme) 180 if (!syme)
130 return; 181 return;
131 182
132 if (syme->lines) { 183 if (syme->src == NULL) {
133 pthread_mutex_lock(&syme->source_lock); 184 syme->src = zalloc(sizeof(*source));
134 goto out_assign; 185 if (syme->src == NULL)
186 return;
187 pthread_mutex_init(&syme->src->lock, NULL);
135 } 188 }
136 189
137 sym = (struct symbol *)(syme + 1); 190 source = syme->src;
138 module = sym->module;
139
140 if (module)
141 path = module->path;
142 if (!path)
143 return;
144
145 start = sym->obj_start;
146 if (!start)
147 start = sym->start;
148 191
149 if (module) { 192 if (source->lines) {
150 section = module->sections->find_section(module->sections, ".text"); 193 pthread_mutex_lock(&source->lock);
151 if (section) 194 goto out_assign;
152 start -= section->vma;
153 } 195 }
154 196
155 end = start + sym->end - sym->start + 1; 197 sym = sym_entry__symbol(syme);
198 map = syme->map;
199 path = map->dso->long_name;
200
156 len = sym->end - sym->start; 201 len = sym->end - sym->start;
157 202
158 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 203 sprintf(command,
204 "objdump --start-address=0x%016Lx "
205 "--stop-address=0x%016Lx -dS %s",
206 map->unmap_ip(map, sym->start),
207 map->unmap_ip(map, sym->end), path);
159 208
160 file = popen(command, "r"); 209 file = popen(command, "r");
161 if (!file) 210 if (!file)
162 return; 211 return;
163 212
164 pthread_mutex_lock(&syme->source_lock); 213 pthread_mutex_lock(&source->lock);
165 syme->lines_tail = &syme->lines; 214 source->lines_tail = &source->lines;
166 while (!feof(file)) { 215 while (!feof(file)) {
167 struct source_line *src; 216 struct source_line *src;
168 size_t dummy = 0; 217 size_t dummy = 0;
@@ -182,24 +231,22 @@ static void parse_source(struct sym_entry *syme)
182 *c = 0; 231 *c = 0;
183 232
184 src->next = NULL; 233 src->next = NULL;
185 *syme->lines_tail = src; 234 *source->lines_tail = src;
186 syme->lines_tail = &src->next; 235 source->lines_tail = &src->next;
187 236
188 if (strlen(src->line)>8 && src->line[8] == ':') { 237 if (strlen(src->line)>8 && src->line[8] == ':') {
189 src->eip = strtoull(src->line, NULL, 16); 238 src->eip = strtoull(src->line, NULL, 16);
190 if (section) 239 src->eip = map->unmap_ip(map, src->eip);
191 src->eip += section->vma;
192 } 240 }
193 if (strlen(src->line)>8 && src->line[16] == ':') { 241 if (strlen(src->line)>8 && src->line[16] == ':') {
194 src->eip = strtoull(src->line, NULL, 16); 242 src->eip = strtoull(src->line, NULL, 16);
195 if (section) 243 src->eip = map->unmap_ip(map, src->eip);
196 src->eip += section->vma;
197 } 244 }
198 } 245 }
199 pclose(file); 246 pclose(file);
200out_assign: 247out_assign:
201 sym_filter_entry = syme; 248 sym_filter_entry = syme;
202 pthread_mutex_unlock(&syme->source_lock); 249 pthread_mutex_unlock(&source->lock);
203} 250}
204 251
205static void __zero_source_counters(struct sym_entry *syme) 252static void __zero_source_counters(struct sym_entry *syme)
@@ -207,7 +254,7 @@ static void __zero_source_counters(struct sym_entry *syme)
207 int i; 254 int i;
208 struct source_line *line; 255 struct source_line *line;
209 256
210 line = syme->lines; 257 line = syme->src->lines;
211 while (line) { 258 while (line) {
212 for (i = 0; i < nr_counters; i++) 259 for (i = 0; i < nr_counters; i++)
213 line->count[i] = 0; 260 line->count[i] = 0;
@@ -222,13 +269,13 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
222 if (syme != sym_filter_entry) 269 if (syme != sym_filter_entry)
223 return; 270 return;
224 271
225 if (pthread_mutex_trylock(&syme->source_lock)) 272 if (pthread_mutex_trylock(&syme->src->lock))
226 return; 273 return;
227 274
228 if (!syme->source) 275 if (syme->src == NULL || syme->src->source == NULL)
229 goto out_unlock; 276 goto out_unlock;
230 277
231 for (line = syme->lines; line; line = line->next) { 278 for (line = syme->src->lines; line; line = line->next) {
232 if (line->eip == ip) { 279 if (line->eip == ip) {
233 line->count[counter]++; 280 line->count[counter]++;
234 break; 281 break;
@@ -237,32 +284,25 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
237 break; 284 break;
238 } 285 }
239out_unlock: 286out_unlock:
240 pthread_mutex_unlock(&syme->source_lock); 287 pthread_mutex_unlock(&syme->src->lock);
241} 288}
242 289
243static void lookup_sym_source(struct sym_entry *syme) 290static void lookup_sym_source(struct sym_entry *syme)
244{ 291{
245 struct symbol *symbol = (struct symbol *)(syme + 1); 292 struct symbol *symbol = sym_entry__symbol(syme);
246 struct source_line *line; 293 struct source_line *line;
247 char pattern[PATH_MAX]; 294 char pattern[PATH_MAX];
248 char *idx;
249 295
250 sprintf(pattern, "<%s>:", symbol->name); 296 sprintf(pattern, "<%s>:", symbol->name);
251 297
252 if (symbol->module) { 298 pthread_mutex_lock(&syme->src->lock);
253 idx = strstr(pattern, "\t"); 299 for (line = syme->src->lines; line; line = line->next) {
254 if (idx)
255 *idx = 0;
256 }
257
258 pthread_mutex_lock(&syme->source_lock);
259 for (line = syme->lines; line; line = line->next) {
260 if (strstr(line->line, pattern)) { 300 if (strstr(line->line, pattern)) {
261 syme->source = line; 301 syme->src->source = line;
262 break; 302 break;
263 } 303 }
264 } 304 }
265 pthread_mutex_unlock(&syme->source_lock); 305 pthread_mutex_unlock(&syme->src->lock);
266} 306}
267 307
268static void show_lines(struct source_line *queue, int count, int total) 308static void show_lines(struct source_line *queue, int count, int total)
@@ -292,24 +332,24 @@ static void show_details(struct sym_entry *syme)
292 if (!syme) 332 if (!syme)
293 return; 333 return;
294 334
295 if (!syme->source) 335 if (!syme->src->source)
296 lookup_sym_source(syme); 336 lookup_sym_source(syme);
297 337
298 if (!syme->source) 338 if (!syme->src->source)
299 return; 339 return;
300 340
301 symbol = (struct symbol *)(syme + 1); 341 symbol = sym_entry__symbol(syme);
302 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 342 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
303 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 343 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
304 344
305 pthread_mutex_lock(&syme->source_lock); 345 pthread_mutex_lock(&syme->src->lock);
306 line = syme->source; 346 line = syme->src->source;
307 while (line) { 347 while (line) {
308 total += line->count[sym_counter]; 348 total += line->count[sym_counter];
309 line = line->next; 349 line = line->next;
310 } 350 }
311 351
312 line = syme->source; 352 line = syme->src->source;
313 while (line) { 353 while (line) {
314 float pcnt = 0.0; 354 float pcnt = 0.0;
315 355
@@ -334,13 +374,13 @@ static void show_details(struct sym_entry *syme)
334 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; 374 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
335 line = line->next; 375 line = line->next;
336 } 376 }
337 pthread_mutex_unlock(&syme->source_lock); 377 pthread_mutex_unlock(&syme->src->lock);
338 if (more) 378 if (more)
339 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 379 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
340} 380}
341 381
342/* 382/*
343 * Symbols will be added here in record_ip and will get out 383 * Symbols will be added here in event__process_sample and will get out
344 * after decayed. 384 * after decayed.
345 */ 385 */
346static LIST_HEAD(active_symbols); 386static LIST_HEAD(active_symbols);
@@ -411,6 +451,8 @@ static void print_sym_table(void)
411 struct sym_entry *syme, *n; 451 struct sym_entry *syme, *n;
412 struct rb_root tmp = RB_ROOT; 452 struct rb_root tmp = RB_ROOT;
413 struct rb_node *nd; 453 struct rb_node *nd;
454 int sym_width = 0, dso_width = 0, max_dso_width;
455 const int win_width = winsize.ws_col - 1;
414 456
415 samples = userspace_samples = 0; 457 samples = userspace_samples = 0;
416 458
@@ -422,6 +464,14 @@ static void print_sym_table(void)
422 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 464 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
423 syme->snap_count = syme->count[snap]; 465 syme->snap_count = syme->count[snap];
424 if (syme->snap_count != 0) { 466 if (syme->snap_count != 0) {
467
468 if ((hide_user_symbols &&
469 syme->origin == PERF_RECORD_MISC_USER) ||
470 (hide_kernel_symbols &&
471 syme->origin == PERF_RECORD_MISC_KERNEL)) {
472 list_remove_active_sym(syme);
473 continue;
474 }
425 syme->weight = sym_weight(syme); 475 syme->weight = sym_weight(syme);
426 rb_insert_active_sym(&tmp, syme); 476 rb_insert_active_sym(&tmp, syme);
427 sum_ksamples += syme->snap_count; 477 sum_ksamples += syme->snap_count;
@@ -434,8 +484,7 @@ static void print_sym_table(void)
434 484
435 puts(CONSOLE_CLEAR); 485 puts(CONSOLE_CLEAR);
436 486
437 printf( 487 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
438"------------------------------------------------------------------------------\n");
439 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [", 488 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
440 samples_per_sec, 489 samples_per_sec,
441 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 490 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
@@ -473,33 +522,57 @@ static void print_sym_table(void)
473 printf(", %d CPUs)\n", nr_cpus); 522 printf(", %d CPUs)\n", nr_cpus);
474 } 523 }
475 524
476 printf("------------------------------------------------------------------------------\n\n"); 525 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
477 526
478 if (sym_filter_entry) { 527 if (sym_filter_entry) {
479 show_details(sym_filter_entry); 528 show_details(sym_filter_entry);
480 return; 529 return;
481 } 530 }
482 531
532 /*
533 * Find the longest symbol name that will be displayed
534 */
535 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
536 syme = rb_entry(nd, struct sym_entry, rb_node);
537 if (++printed > print_entries ||
538 (int)syme->snap_count < count_filter)
539 continue;
540
541 if (syme->map->dso->long_name_len > dso_width)
542 dso_width = syme->map->dso->long_name_len;
543
544 if (syme->name_len > sym_width)
545 sym_width = syme->name_len;
546 }
547
548 printed = 0;
549
550 max_dso_width = winsize.ws_col - sym_width - 29;
551 if (dso_width > max_dso_width)
552 dso_width = max_dso_width;
553 putchar('\n');
483 if (nr_counters == 1) 554 if (nr_counters == 1)
484 printf(" samples pcnt"); 555 printf(" samples pcnt");
485 else 556 else
486 printf(" weight samples pcnt"); 557 printf(" weight samples pcnt");
487 558
488 if (verbose) 559 if (verbose)
489 printf(" RIP "); 560 printf(" RIP ");
490 printf(" kernel function\n"); 561 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
491 printf(" %s _______ _____", 562 printf(" %s _______ _____",
492 nr_counters == 1 ? " " : "______"); 563 nr_counters == 1 ? " " : "______");
493 if (verbose) 564 if (verbose)
494 printf(" ________________"); 565 printf(" ________________");
495 printf(" _______________\n\n"); 566 printf(" %-*.*s", sym_width, sym_width, graph_line);
567 printf(" %-*.*s", dso_width, dso_width, graph_line);
568 puts("\n");
496 569
497 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 570 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
498 struct symbol *sym; 571 struct symbol *sym;
499 double pcnt; 572 double pcnt;
500 573
501 syme = rb_entry(nd, struct sym_entry, rb_node); 574 syme = rb_entry(nd, struct sym_entry, rb_node);
502 sym = (struct symbol *)(syme + 1); 575 sym = sym_entry__symbol(syme);
503 576
504 if (++printed > print_entries || (int)syme->snap_count < count_filter) 577 if (++printed > print_entries || (int)syme->snap_count < count_filter)
505 continue; 578 continue;
@@ -508,17 +581,18 @@ static void print_sym_table(void)
508 sum_ksamples)); 581 sum_ksamples));
509 582
510 if (nr_counters == 1 || !display_weighted) 583 if (nr_counters == 1 || !display_weighted)
511 printf("%20.2f - ", syme->weight); 584 printf("%20.2f ", syme->weight);
512 else 585 else
513 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 586 printf("%9.1f %10ld ", syme->weight, syme->snap_count);
514 587
515 percent_color_fprintf(stdout, "%4.1f%%", pcnt); 588 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
516 if (verbose) 589 if (verbose)
517 printf(" - %016llx", sym->start); 590 printf(" %016llx", sym->start);
518 printf(" : %s", sym->name); 591 printf(" %-*.*s", sym_width, sym_width, sym->name);
519 if (sym->module) 592 printf(" %-*.*s\n", dso_width, dso_width,
520 printf("\t[%s]", sym->module->name); 593 dso_width >= syme->map->dso->long_name_len ?
521 printf("\n"); 594 syme->map->dso->long_name :
595 syme->map->dso->short_name);
522 } 596 }
523} 597}
524 598
@@ -565,10 +639,10 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
565 639
566 /* zero counters of active symbol */ 640 /* zero counters of active symbol */
567 if (syme) { 641 if (syme) {
568 pthread_mutex_lock(&syme->source_lock); 642 pthread_mutex_lock(&syme->src->lock);
569 __zero_source_counters(syme); 643 __zero_source_counters(syme);
570 *target = NULL; 644 *target = NULL;
571 pthread_mutex_unlock(&syme->source_lock); 645 pthread_mutex_unlock(&syme->src->lock);
572 } 646 }
573 647
574 fprintf(stdout, "\n%s: ", msg); 648 fprintf(stdout, "\n%s: ", msg);
@@ -584,7 +658,7 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
584 pthread_mutex_unlock(&active_symbols_lock); 658 pthread_mutex_unlock(&active_symbols_lock);
585 659
586 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 660 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
587 struct symbol *sym = (struct symbol *)(syme + 1); 661 struct symbol *sym = sym_entry__symbol(syme);
588 662
589 if (!strcmp(buf, sym->name)) { 663 if (!strcmp(buf, sym->name)) {
590 found = syme; 664 found = syme;
@@ -608,7 +682,7 @@ static void print_mapped_keys(void)
608 char *name = NULL; 682 char *name = NULL;
609 683
610 if (sym_filter_entry) { 684 if (sym_filter_entry) {
611 struct symbol *sym = (struct symbol *)(sym_filter_entry+1); 685 struct symbol *sym = sym_entry__symbol(sym_filter_entry);
612 name = sym->name; 686 name = sym->name;
613 } 687 }
614 688
@@ -621,7 +695,7 @@ static void print_mapped_keys(void)
621 695
622 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 696 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
623 697
624 if (vmlinux_name) { 698 if (symbol_conf.vmlinux_name) {
625 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 699 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
626 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 700 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
627 fprintf(stdout, "\t[S] stop annotation.\n"); 701 fprintf(stdout, "\t[S] stop annotation.\n");
@@ -630,6 +704,12 @@ static void print_mapped_keys(void)
630 if (nr_counters > 1) 704 if (nr_counters > 1)
631 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 705 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
632 706
707 fprintf(stdout,
708 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
709 hide_kernel_symbols ? "yes" : "no");
710 fprintf(stdout,
711 "\t[U] hide user symbols. \t(%s)\n",
712 hide_user_symbols ? "yes" : "no");
633 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); 713 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0);
634 fprintf(stdout, "\t[qQ] quit.\n"); 714 fprintf(stdout, "\t[qQ] quit.\n");
635} 715}
@@ -643,6 +723,8 @@ static int key_mapped(int c)
643 case 'z': 723 case 'z':
644 case 'q': 724 case 'q':
645 case 'Q': 725 case 'Q':
726 case 'K':
727 case 'U':
646 return 1; 728 return 1;
647 case 'E': 729 case 'E':
648 case 'w': 730 case 'w':
@@ -650,7 +732,7 @@ static int key_mapped(int c)
650 case 'F': 732 case 'F':
651 case 's': 733 case 's':
652 case 'S': 734 case 'S':
653 return vmlinux_name ? 1 : 0; 735 return symbol_conf.vmlinux_name ? 1 : 0;
654 default: 736 default:
655 break; 737 break;
656 } 738 }
@@ -691,6 +773,11 @@ static void handle_keypress(int c)
691 break; 773 break;
692 case 'e': 774 case 'e':
693 prompt_integer(&print_entries, "Enter display entries (lines)"); 775 prompt_integer(&print_entries, "Enter display entries (lines)");
776 if (print_entries == 0) {
777 sig_winch_handler(SIGWINCH);
778 signal(SIGWINCH, sig_winch_handler);
779 } else
780 signal(SIGWINCH, SIG_DFL);
694 break; 781 break;
695 case 'E': 782 case 'E':
696 if (nr_counters > 1) { 783 if (nr_counters > 1) {
@@ -715,9 +802,14 @@ static void handle_keypress(int c)
715 case 'F': 802 case 'F':
716 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 803 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
717 break; 804 break;
805 case 'K':
806 hide_kernel_symbols = !hide_kernel_symbols;
807 break;
718 case 'q': 808 case 'q':
719 case 'Q': 809 case 'Q':
720 printf("exiting.\n"); 810 printf("exiting.\n");
811 if (dump_symtab)
812 dsos__fprintf(stderr);
721 exit(0); 813 exit(0);
722 case 's': 814 case 's':
723 prompt_symbol(&sym_filter_entry, "Enter details symbol"); 815 prompt_symbol(&sym_filter_entry, "Enter details symbol");
@@ -728,12 +820,15 @@ static void handle_keypress(int c)
728 else { 820 else {
729 struct sym_entry *syme = sym_filter_entry; 821 struct sym_entry *syme = sym_filter_entry;
730 822
731 pthread_mutex_lock(&syme->source_lock); 823 pthread_mutex_lock(&syme->src->lock);
732 sym_filter_entry = NULL; 824 sym_filter_entry = NULL;
733 __zero_source_counters(syme); 825 __zero_source_counters(syme);
734 pthread_mutex_unlock(&syme->source_lock); 826 pthread_mutex_unlock(&syme->src->lock);
735 } 827 }
736 break; 828 break;
829 case 'U':
830 hide_user_symbols = !hide_user_symbols;
831 break;
737 case 'w': 832 case 'w':
738 display_weighted = ~display_weighted; 833 display_weighted = ~display_weighted;
739 break; 834 break;
@@ -790,7 +885,7 @@ static const char *skip_symbols[] = {
790 NULL 885 NULL
791}; 886};
792 887
793static int symbol_filter(struct dso *self, struct symbol *sym) 888static int symbol_filter(struct map *map, struct symbol *sym)
794{ 889{
795 struct sym_entry *syme; 890 struct sym_entry *syme;
796 const char *name = sym->name; 891 const char *name = sym->name;
@@ -812,8 +907,9 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
812 strstr(name, "_text_end")) 907 strstr(name, "_text_end"))
813 return 1; 908 return 1;
814 909
815 syme = dso__sym_priv(self, sym); 910 syme = symbol__priv(sym);
816 pthread_mutex_init(&syme->source_lock, NULL); 911 syme->map = map;
912 syme->src = NULL;
817 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 913 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
818 sym_filter_entry = syme; 914 sym_filter_entry = syme;
819 915
@@ -824,75 +920,65 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
824 } 920 }
825 } 921 }
826 922
827 return 0; 923 if (!syme->skip)
828} 924 syme->name_len = strlen(sym->name);
829
830static int parse_symbols(void)
831{
832 struct rb_node *node;
833 struct symbol *sym;
834 int use_modules = vmlinux_name ? 1 : 0;
835
836 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
837 if (kernel_dso == NULL)
838 return -1;
839
840 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
841 goto out_delete_dso;
842
843 node = rb_first(&kernel_dso->syms);
844 sym = rb_entry(node, struct symbol, rb_node);
845 min_ip = sym->start;
846
847 node = rb_last(&kernel_dso->syms);
848 sym = rb_entry(node, struct symbol, rb_node);
849 max_ip = sym->end;
850
851 if (dump_symtab)
852 dso__fprintf(kernel_dso, stderr);
853 925
854 return 0; 926 return 0;
855
856out_delete_dso:
857 dso__delete(kernel_dso);
858 kernel_dso = NULL;
859 return -1;
860} 927}
861 928
862/* 929static void event__process_sample(const event_t *self, int counter)
863 * Binary search in the histogram table and record the hit:
864 */
865static void record_ip(u64 ip, int counter)
866{ 930{
867 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 931 u64 ip = self->ip.ip;
868 932 struct sym_entry *syme;
869 if (sym != NULL) { 933 struct addr_location al;
870 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 934 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
871 935
872 if (!syme->skip) { 936 switch (origin) {
873 syme->count[counter]++; 937 case PERF_RECORD_MISC_USER:
874 record_precise_ip(syme, counter, ip); 938 if (hide_user_symbols)
875 pthread_mutex_lock(&active_symbols_lock);
876 if (list_empty(&syme->node) || !syme->node.next)
877 __list_insert_active_sym(syme);
878 pthread_mutex_unlock(&active_symbols_lock);
879 return; 939 return;
880 } 940 break;
941 case PERF_RECORD_MISC_KERNEL:
942 if (hide_kernel_symbols)
943 return;
944 break;
945 default:
946 return;
881 } 947 }
882 948
883 samples--; 949 if (event__preprocess_sample(self, &al, symbol_filter) < 0 ||
950 al.sym == NULL)
951 return;
952
953 syme = symbol__priv(al.sym);
954 if (!syme->skip) {
955 syme->count[counter]++;
956 syme->origin = origin;
957 record_precise_ip(syme, counter, ip);
958 pthread_mutex_lock(&active_symbols_lock);
959 if (list_empty(&syme->node) || !syme->node.next)
960 __list_insert_active_sym(syme);
961 pthread_mutex_unlock(&active_symbols_lock);
962 if (origin == PERF_RECORD_MISC_USER)
963 ++userspace_samples;
964 ++samples;
965 }
884} 966}
885 967
886static void process_event(u64 ip, int counter, int user) 968static int event__process(event_t *event)
887{ 969{
888 samples++; 970 switch (event->header.type) {
889 971 case PERF_RECORD_COMM:
890 if (user) { 972 event__process_comm(event);
891 userspace_samples++; 973 break;
892 return; 974 case PERF_RECORD_MMAP:
975 event__process_mmap(event);
976 break;
977 default:
978 break;
893 } 979 }
894 980
895 record_ip(ip, counter); 981 return 0;
896} 982}
897 983
898struct mmap_data { 984struct mmap_data {
@@ -913,8 +999,6 @@ static unsigned int mmap_read_head(struct mmap_data *md)
913 return head; 999 return head;
914} 1000}
915 1001
916struct timeval last_read, this_read;
917
918static void mmap_read_counter(struct mmap_data *md) 1002static void mmap_read_counter(struct mmap_data *md)
919{ 1003{
920 unsigned int head = mmap_read_head(md); 1004 unsigned int head = mmap_read_head(md);
@@ -922,8 +1006,6 @@ static void mmap_read_counter(struct mmap_data *md)
922 unsigned char *data = md->base + page_size; 1006 unsigned char *data = md->base + page_size;
923 int diff; 1007 int diff;
924 1008
925 gettimeofday(&this_read, NULL);
926
927 /* 1009 /*
928 * If we're further behind than half the buffer, there's a chance 1010 * If we're further behind than half the buffer, there's a chance
929 * the writer will bite our tail and mess up the samples under us. 1011 * the writer will bite our tail and mess up the samples under us.
@@ -934,14 +1016,7 @@ static void mmap_read_counter(struct mmap_data *md)
934 */ 1016 */
935 diff = head - old; 1017 diff = head - old;
936 if (diff > md->mask / 2 || diff < 0) { 1018 if (diff > md->mask / 2 || diff < 0) {
937 struct timeval iv; 1019 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
938 unsigned long msecs;
939
940 timersub(&this_read, &last_read, &iv);
941 msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
942
943 fprintf(stderr, "WARNING: failed to keep up with mmap data."
944 " Last read %lu msecs ago.\n", msecs);
945 1020
946 /* 1021 /*
947 * head points to a known good entry, start there. 1022 * head points to a known good entry, start there.
@@ -949,8 +1024,6 @@ static void mmap_read_counter(struct mmap_data *md)
949 old = head; 1024 old = head;
950 } 1025 }
951 1026
952 last_read = this_read;
953
954 for (; old != head;) { 1027 for (; old != head;) {
955 event_t *event = (event_t *)&data[old & md->mask]; 1028 event_t *event = (event_t *)&data[old & md->mask];
956 1029
@@ -978,13 +1051,11 @@ static void mmap_read_counter(struct mmap_data *md)
978 event = &event_copy; 1051 event = &event_copy;
979 } 1052 }
980 1053
1054 if (event->header.type == PERF_RECORD_SAMPLE)
1055 event__process_sample(event, md->counter);
1056 else
1057 event__process(event);
981 old += size; 1058 old += size;
982
983 if (event->header.type == PERF_RECORD_SAMPLE) {
984 int user =
985 (event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_USER;
986 process_event(event->ip.ip, md->counter, user);
987 }
988 } 1059 }
989 1060
990 md->prev = old; 1061 md->prev = old;
@@ -1018,8 +1089,15 @@ static void start_counter(int i, int counter)
1018 attr = attrs + counter; 1089 attr = attrs + counter;
1019 1090
1020 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1091 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1021 attr->freq = freq; 1092
1093 if (freq) {
1094 attr->sample_type |= PERF_SAMPLE_PERIOD;
1095 attr->freq = 1;
1096 attr->sample_freq = freq;
1097 }
1098
1022 attr->inherit = (cpu < 0) && inherit; 1099 attr->inherit = (cpu < 0) && inherit;
1100 attr->mmap = 1;
1023 1101
1024try_again: 1102try_again:
1025 fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0); 1103 fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0);
@@ -1078,6 +1156,11 @@ static int __cmd_top(void)
1078 int i, counter; 1156 int i, counter;
1079 int ret; 1157 int ret;
1080 1158
1159 if (target_pid != -1)
1160 event__synthesize_thread(target_pid, event__process);
1161 else
1162 event__synthesize_threads(event__process);
1163
1081 for (i = 0; i < nr_cpus; i++) { 1164 for (i = 0; i < nr_cpus; i++) {
1082 group_fd = -1; 1165 group_fd = -1;
1083 for (counter = 0; counter < nr_counters; counter++) 1166 for (counter = 0; counter < nr_counters; counter++)
@@ -1133,7 +1216,10 @@ static const struct option options[] = {
1133 "system-wide collection from all CPUs"), 1216 "system-wide collection from all CPUs"),
1134 OPT_INTEGER('C', "CPU", &profile_cpu, 1217 OPT_INTEGER('C', "CPU", &profile_cpu,
1135 "CPU to profile on"), 1218 "CPU to profile on"),
1136 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 1219 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1220 "file", "vmlinux pathname"),
1221 OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
1222 "hide kernel symbols"),
1137 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1223 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
1138 "number of mmap data pages"), 1224 "number of mmap data pages"),
1139 OPT_INTEGER('r', "realtime", &realtime_prio, 1225 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -1156,6 +1242,8 @@ static const struct option options[] = {
1156 "profile at this frequency"), 1242 "profile at this frequency"),
1157 OPT_INTEGER('E', "entries", &print_entries, 1243 OPT_INTEGER('E', "entries", &print_entries,
1158 "display this many functions"), 1244 "display this many functions"),
1245 OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols,
1246 "hide user symbols"),
1159 OPT_BOOLEAN('v', "verbose", &verbose, 1247 OPT_BOOLEAN('v', "verbose", &verbose,
1160 "be more verbose (show counter open errors, etc)"), 1248 "be more verbose (show counter open errors, etc)"),
1161 OPT_END() 1249 OPT_END()
@@ -1165,19 +1253,12 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1165{ 1253{
1166 int counter; 1254 int counter;
1167 1255
1168 symbol__init();
1169
1170 page_size = sysconf(_SC_PAGE_SIZE); 1256 page_size = sysconf(_SC_PAGE_SIZE);
1171 1257
1172 argc = parse_options(argc, argv, options, top_usage, 0); 1258 argc = parse_options(argc, argv, options, top_usage, 0);
1173 if (argc) 1259 if (argc)
1174 usage_with_options(top_usage, options); 1260 usage_with_options(top_usage, options);
1175 1261
1176 if (freq) {
1177 default_interval = freq;
1178 freq = 1;
1179 }
1180
1181 /* CPU and PID are mutually exclusive */ 1262 /* CPU and PID are mutually exclusive */
1182 if (target_pid != -1 && profile_cpu != -1) { 1263 if (target_pid != -1 && profile_cpu != -1) {
1183 printf("WARNING: PID switch overriding CPU\n"); 1264 printf("WARNING: PID switch overriding CPU\n");
@@ -1188,13 +1269,31 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1188 if (!nr_counters) 1269 if (!nr_counters)
1189 nr_counters = 1; 1270 nr_counters = 1;
1190 1271
1272 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1273 (nr_counters + 1) * sizeof(unsigned long));
1274 if (symbol_conf.vmlinux_name == NULL)
1275 symbol_conf.try_vmlinux_path = true;
1276 if (symbol__init(&symbol_conf) < 0)
1277 return -1;
1278
1191 if (delay_secs < 1) 1279 if (delay_secs < 1)
1192 delay_secs = 1; 1280 delay_secs = 1;
1193 1281
1194 parse_symbols();
1195 parse_source(sym_filter_entry); 1282 parse_source(sym_filter_entry);
1196 1283
1197 /* 1284 /*
1285 * User specified count overrides default frequency.
1286 */
1287 if (default_interval)
1288 freq = 0;
1289 else if (freq) {
1290 default_interval = freq;
1291 } else {
1292 fprintf(stderr, "frequency and count are zero, aborting\n");
1293 exit(EXIT_FAILURE);
1294 }
1295
1296 /*
1198 * Fill in the ones not specifically initialized via -c: 1297 * Fill in the ones not specifically initialized via -c:
1199 */ 1298 */
1200 for (counter = 0; counter < nr_counters; counter++) { 1299 for (counter = 0; counter < nr_counters; counter++) {
@@ -1211,5 +1310,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1211 if (target_pid != -1 || profile_cpu != -1) 1310 if (target_pid != -1 || profile_cpu != -1)
1212 nr_cpus = 1; 1311 nr_cpus = 1;
1213 1312
1313 get_term_dimensions(&winsize);
1314 if (print_entries == 0) {
1315 update_print_entries(&winsize);
1316 signal(SIGWINCH, sig_winch_handler);
1317 }
1318
1214 return __cmd_top(); 1319 return __cmd_top();
1215} 1320}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0c5e4f72f2ba..abb914aa7be6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -5,66 +5,73 @@
5#include "util/symbol.h" 5#include "util/symbol.h"
6#include "util/thread.h" 6#include "util/thread.h"
7#include "util/header.h" 7#include "util/header.h"
8#include "util/exec_cmd.h"
9#include "util/trace-event.h"
8 10
9#include "util/parse-options.h" 11static char const *script_name;
12static char const *generate_script_lang;
10 13
11#include "perf.h" 14static int default_start_script(const char *script __attribute((unused)))
12#include "util/debug.h" 15{
16 return 0;
17}
13 18
14#include "util/trace-event.h" 19static int default_stop_script(void)
20{
21 return 0;
22}
15 23
16static char const *input_name = "perf.data"; 24static int default_generate_script(const char *outfile __attribute ((unused)))
17static int input; 25{
18static unsigned long page_size; 26 return 0;
19static unsigned long mmap_window = 32; 27}
20 28
21static unsigned long total = 0; 29static struct scripting_ops default_scripting_ops = {
22static unsigned long total_comm = 0; 30 .start_script = default_start_script,
31 .stop_script = default_stop_script,
32 .process_event = print_event,
33 .generate_script = default_generate_script,
34};
35
36static struct scripting_ops *scripting_ops;
23 37
24static struct rb_root threads; 38static void setup_scripting(void)
25static struct thread *last_match; 39{
40 /* make sure PERF_EXEC_PATH is set for scripts */
41 perf_set_argv_exec_path(perf_exec_path());
26 42
27static struct perf_header *header; 43 setup_perl_scripting();
28static u64 sample_type;
29 44
45 scripting_ops = &default_scripting_ops;
46}
30 47
31static int 48static int cleanup_scripting(void)
32process_comm_event(event_t *event, unsigned long offset, unsigned long head)
33{ 49{
34 struct thread *thread; 50 return scripting_ops->stop_script();
51}
35 52
36 thread = threads__findnew(event->comm.pid, &threads, &last_match); 53#include "util/parse-options.h"
37 54
38 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 55#include "perf.h"
39 (void *)(offset + head), 56#include "util/debug.h"
40 (void *)(long)(event->header.size),
41 event->comm.comm, event->comm.pid);
42 57
43 if (thread == NULL || 58#include "util/trace-event.h"
44 thread__set_comm(thread, event->comm.comm)) { 59#include "util/data_map.h"
45 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 60#include "util/exec_cmd.h"
46 return -1;
47 }
48 total_comm++;
49 61
50 return 0; 62static char const *input_name = "perf.data";
51}
52 63
53static int 64static struct perf_header *header;
54process_sample_event(event_t *event, unsigned long offset, unsigned long head) 65static u64 sample_type;
66
67static int process_sample_event(event_t *event)
55{ 68{
56 char level;
57 int show = 0;
58 struct dso *dso = NULL;
59 struct thread *thread;
60 u64 ip = event->ip.ip; 69 u64 ip = event->ip.ip;
61 u64 timestamp = -1; 70 u64 timestamp = -1;
62 u32 cpu = -1; 71 u32 cpu = -1;
63 u64 period = 1; 72 u64 period = 1;
64 void *more_data = event->ip.__more_data; 73 void *more_data = event->ip.__more_data;
65 int cpumode; 74 struct thread *thread = threads__findnew(event->ip.pid);
66
67 thread = threads__findnew(event->ip.pid, &threads, &last_match);
68 75
69 if (sample_type & PERF_SAMPLE_TIME) { 76 if (sample_type & PERF_SAMPLE_TIME) {
70 timestamp = *(u64 *)more_data; 77 timestamp = *(u64 *)more_data;
@@ -82,45 +89,19 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
82 more_data += sizeof(u64); 89 more_data += sizeof(u64);
83 } 90 }
84 91
85 dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", 92 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
86 (void *)(offset + head),
87 (void *)(long)(event->header.size),
88 event->header.misc, 93 event->header.misc,
89 event->ip.pid, event->ip.tid, 94 event->ip.pid, event->ip.tid,
90 (void *)(long)ip, 95 (void *)(long)ip,
91 (long long)period); 96 (long long)period);
92 97
93 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
94
95 if (thread == NULL) { 98 if (thread == NULL) {
96 eprintf("problem processing %d event, skipping it.\n", 99 pr_debug("problem processing %d event, skipping it.\n",
97 event->header.type); 100 event->header.type);
98 return -1; 101 return -1;
99 } 102 }
100 103
101 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 104 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
102
103 if (cpumode == PERF_RECORD_MISC_KERNEL) {
104 show = SHOW_KERNEL;
105 level = 'k';
106
107 dso = kernel_dso;
108
109 dump_printf(" ...... dso: %s\n", dso->name);
110
111 } else if (cpumode == PERF_RECORD_MISC_USER) {
112
113 show = SHOW_USER;
114 level = '.';
115
116 } else {
117 show = SHOW_HV;
118 level = 'H';
119
120 dso = hypervisor_dso;
121
122 dump_printf(" ...... dso: [hypervisor]\n");
123 }
124 105
125 if (sample_type & PERF_SAMPLE_RAW) { 106 if (sample_type & PERF_SAMPLE_RAW) {
126 struct { 107 struct {
@@ -133,128 +114,189 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
133 * field, although it should be the same than this perf 114 * field, although it should be the same than this perf
134 * event pid 115 * event pid
135 */ 116 */
136 print_event(cpu, raw->data, raw->size, timestamp, thread->comm); 117 scripting_ops->process_event(cpu, raw->data, raw->size,
118 timestamp, thread->comm);
137 } 119 }
138 total += period; 120 event__stats.total += period;
139 121
140 return 0; 122 return 0;
141} 123}
142 124
143static int 125static int sample_type_check(u64 type)
144process_event(event_t *event, unsigned long offset, unsigned long head)
145{ 126{
146 trace_event(event); 127 sample_type = type;
147
148 switch (event->header.type) {
149 case PERF_RECORD_MMAP ... PERF_RECORD_LOST:
150 return 0;
151
152 case PERF_RECORD_COMM:
153 return process_comm_event(event, offset, head);
154
155 case PERF_RECORD_EXIT ... PERF_RECORD_READ:
156 return 0;
157
158 case PERF_RECORD_SAMPLE:
159 return process_sample_event(event, offset, head);
160 128
161 case PERF_RECORD_MAX: 129 if (!(sample_type & PERF_SAMPLE_RAW)) {
162 default: 130 fprintf(stderr,
131 "No trace sample to read. Did you call perf record "
132 "without -R?");
163 return -1; 133 return -1;
164 } 134 }
165 135
166 return 0; 136 return 0;
167} 137}
168 138
139static struct perf_file_handler file_handler = {
140 .process_sample_event = process_sample_event,
141 .process_comm_event = event__process_comm,
142 .sample_type_check = sample_type_check,
143};
144
169static int __cmd_trace(void) 145static int __cmd_trace(void)
170{ 146{
171 int ret, rc = EXIT_FAILURE; 147 register_idle_thread();
172 unsigned long offset = 0; 148 register_perf_file_handler(&file_handler);
173 unsigned long head = 0;
174 struct stat perf_stat;
175 event_t *event;
176 uint32_t size;
177 char *buf;
178
179 trace_report();
180 register_idle_thread(&threads, &last_match);
181
182 input = open(input_name, O_RDONLY);
183 if (input < 0) {
184 perror("failed to open file");
185 exit(-1);
186 }
187 149
188 ret = fstat(input, &perf_stat); 150 return mmap_dispatch_perf_file(&header, input_name,
189 if (ret < 0) { 151 0, 0, &event__cwdlen, &event__cwd);
190 perror("failed to stat file"); 152}
191 exit(-1);
192 }
193 153
194 if (!perf_stat.st_size) { 154struct script_spec {
195 fprintf(stderr, "zero-sized file, nothing to do!\n"); 155 struct list_head node;
196 exit(0); 156 struct scripting_ops *ops;
197 } 157 char spec[0];
198 header = perf_header__read(input); 158};
199 head = header->data_offset;
200 sample_type = perf_header__sample_type(header);
201 159
202 if (!(sample_type & PERF_SAMPLE_RAW)) 160LIST_HEAD(script_specs);
203 die("No trace sample to read. Did you call perf record "
204 "without -R?");
205 161
206 if (load_kernel() < 0) { 162static struct script_spec *script_spec__new(const char *spec,
207 perror("failed to load kernel symbols"); 163 struct scripting_ops *ops)
208 return EXIT_FAILURE; 164{
209 } 165 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
210 166
211remap: 167 if (s != NULL) {
212 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 168 strcpy(s->spec, spec);
213 MAP_SHARED, input, offset); 169 s->ops = ops;
214 if (buf == MAP_FAILED) {
215 perror("failed to mmap file");
216 exit(-1);
217 } 170 }
218 171
219more: 172 return s;
220 event = (event_t *)(buf + head); 173}
221 174
222 if (head + event->header.size >= page_size * mmap_window) { 175static void script_spec__delete(struct script_spec *s)
223 unsigned long shift = page_size * (head / page_size); 176{
224 int res; 177 free(s->spec);
178 free(s);
179}
225 180
226 res = munmap(buf, page_size * mmap_window); 181static void script_spec__add(struct script_spec *s)
227 assert(res == 0); 182{
183 list_add_tail(&s->node, &script_specs);
184}
228 185
229 offset += shift; 186static struct script_spec *script_spec__find(const char *spec)
230 head -= shift; 187{
231 goto remap; 188 struct script_spec *s;
232 }
233 189
234 size = event->header.size; 190 list_for_each_entry(s, &script_specs, node)
191 if (strcasecmp(s->spec, spec) == 0)
192 return s;
193 return NULL;
194}
235 195
236 if (!size || process_event(event, offset, head) < 0) { 196static struct script_spec *script_spec__findnew(const char *spec,
197 struct scripting_ops *ops)
198{
199 struct script_spec *s = script_spec__find(spec);
237 200
238 /* 201 if (s)
239 * assume we lost track of the stream, check alignment, and 202 return s;
240 * increment a single u64 in the hope to catch on again 'soon'.
241 */
242 203
243 if (unlikely(head & 7)) 204 s = script_spec__new(spec, ops);
244 head &= ~7ULL; 205 if (!s)
206 goto out_delete_spec;
245 207
246 size = 8; 208 script_spec__add(s);
247 } 209
210 return s;
248 211
249 head += size; 212out_delete_spec:
213 script_spec__delete(s);
214
215 return NULL;
216}
250 217
251 if (offset + head < (unsigned long)perf_stat.st_size) 218int script_spec_register(const char *spec, struct scripting_ops *ops)
252 goto more; 219{
220 struct script_spec *s;
221
222 s = script_spec__find(spec);
223 if (s)
224 return -1;
253 225
254 rc = EXIT_SUCCESS; 226 s = script_spec__findnew(spec, ops);
255 close(input); 227 if (!s)
228 return -1;
229
230 return 0;
231}
232
233static struct scripting_ops *script_spec__lookup(const char *spec)
234{
235 struct script_spec *s = script_spec__find(spec);
236 if (!s)
237 return NULL;
256 238
257 return rc; 239 return s->ops;
240}
241
242static void list_available_languages(void)
243{
244 struct script_spec *s;
245
246 fprintf(stderr, "\n");
247 fprintf(stderr, "Scripting language extensions (used in "
248 "perf trace -s [spec:]script.[spec]):\n\n");
249
250 list_for_each_entry(s, &script_specs, node)
251 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
252
253 fprintf(stderr, "\n");
254}
255
256static int parse_scriptname(const struct option *opt __used,
257 const char *str, int unset __used)
258{
259 char spec[PATH_MAX];
260 const char *script, *ext;
261 int len;
262
263 if (strcmp(str, "list") == 0) {
264 list_available_languages();
265 return 0;
266 }
267
268 script = strchr(str, ':');
269 if (script) {
270 len = script - str;
271 if (len >= PATH_MAX) {
272 fprintf(stderr, "invalid language specifier");
273 return -1;
274 }
275 strncpy(spec, str, len);
276 spec[len] = '\0';
277 scripting_ops = script_spec__lookup(spec);
278 if (!scripting_ops) {
279 fprintf(stderr, "invalid language specifier");
280 return -1;
281 }
282 script++;
283 } else {
284 script = str;
285 ext = strchr(script, '.');
286 if (!ext) {
287 fprintf(stderr, "invalid script extension");
288 return -1;
289 }
290 scripting_ops = script_spec__lookup(++ext);
291 if (!scripting_ops) {
292 fprintf(stderr, "invalid script extension");
293 return -1;
294 }
295 }
296
297 script_name = strdup(script);
298
299 return 0;
258} 300}
259 301
260static const char * const annotate_usage[] = { 302static const char * const annotate_usage[] = {
@@ -267,13 +309,24 @@ static const struct option options[] = {
267 "dump raw trace in ASCII"), 309 "dump raw trace in ASCII"),
268 OPT_BOOLEAN('v', "verbose", &verbose, 310 OPT_BOOLEAN('v', "verbose", &verbose,
269 "be more verbose (show symbol address, etc)"), 311 "be more verbose (show symbol address, etc)"),
312 OPT_BOOLEAN('l', "latency", &latency_format,
313 "show latency attributes (irqs/preemption disabled, etc)"),
314 OPT_CALLBACK('s', "script", NULL, "name",
315 "script file name (lang:script name, script name, or *)",
316 parse_scriptname),
317 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
318 "generate perf-trace.xx script in specified language"),
319
270 OPT_END() 320 OPT_END()
271}; 321};
272 322
273int cmd_trace(int argc, const char **argv, const char *prefix __used) 323int cmd_trace(int argc, const char **argv, const char *prefix __used)
274{ 324{
275 symbol__init(); 325 int err;
276 page_size = getpagesize(); 326
327 symbol__init(0);
328
329 setup_scripting();
277 330
278 argc = parse_options(argc, argv, options, annotate_usage, 0); 331 argc = parse_options(argc, argv, options, annotate_usage, 0);
279 if (argc) { 332 if (argc) {
@@ -287,5 +340,50 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
287 340
288 setup_pager(); 341 setup_pager();
289 342
290 return __cmd_trace(); 343 if (generate_script_lang) {
344 struct stat perf_stat;
345
346 int input = open(input_name, O_RDONLY);
347 if (input < 0) {
348 perror("failed to open file");
349 exit(-1);
350 }
351
352 err = fstat(input, &perf_stat);
353 if (err < 0) {
354 perror("failed to stat file");
355 exit(-1);
356 }
357
358 if (!perf_stat.st_size) {
359 fprintf(stderr, "zero-sized file, nothing to do!\n");
360 exit(0);
361 }
362
363 scripting_ops = script_spec__lookup(generate_script_lang);
364 if (!scripting_ops) {
365 fprintf(stderr, "invalid language specifier");
366 return -1;
367 }
368
369 header = perf_header__new();
370 if (header == NULL)
371 return -1;
372
373 perf_header__read(header, input);
374 err = scripting_ops->generate_script("perf-trace");
375 goto out;
376 }
377
378 if (script_name) {
379 err = scripting_ops->start_script(script_name);
380 if (err)
381 goto out;
382 }
383
384 err = __cmd_trace();
385
386 cleanup_scripting();
387out:
388 return err;
291} 389}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index e11d8d231c3b..a3d8bf65f26c 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -15,6 +15,8 @@ extern int read_line_with_nul(char *buf, int size, FILE *file);
15extern int check_pager_config(const char *cmd); 15extern int check_pager_config(const char *cmd);
16 16
17extern int cmd_annotate(int argc, const char **argv, const char *prefix); 17extern int cmd_annotate(int argc, const char **argv, const char *prefix);
18extern int cmd_bench(int argc, const char **argv, const char *prefix);
19extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
18extern int cmd_help(int argc, const char **argv, const char *prefix); 20extern int cmd_help(int argc, const char **argv, const char *prefix);
19extern int cmd_sched(int argc, const char **argv, const char *prefix); 21extern int cmd_sched(int argc, const char **argv, const char *prefix);
20extern int cmd_list(int argc, const char **argv, const char *prefix); 22extern int cmd_list(int argc, const char **argv, const char *prefix);
@@ -25,5 +27,7 @@ extern int cmd_timechart(int argc, const char **argv, const char *prefix);
25extern int cmd_top(int argc, const char **argv, const char *prefix); 27extern int cmd_top(int argc, const char **argv, const char *prefix);
26extern int cmd_trace(int argc, const char **argv, const char *prefix); 28extern int cmd_trace(int argc, const char **argv, const char *prefix);
27extern int cmd_version(int argc, const char **argv, const char *prefix); 29extern int cmd_version(int argc, const char **argv, const char *prefix);
30extern int cmd_probe(int argc, const char **argv, const char *prefix);
31extern int cmd_kmem(int argc, const char **argv, const char *prefix);
28 32
29#endif 33#endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 00326e230d87..02b09ea17a3e 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -3,6 +3,8 @@
3# command name category [deprecated] [common] 3# command name category [deprecated] [common]
4# 4#
5perf-annotate mainporcelain common 5perf-annotate mainporcelain common
6perf-bench mainporcelain common
7perf-buildid-list mainporcelain common
6perf-list mainporcelain common 8perf-list mainporcelain common
7perf-sched mainporcelain common 9perf-sched mainporcelain common
8perf-record mainporcelain common 10perf-record mainporcelain common
@@ -11,3 +13,5 @@ perf-stat mainporcelain common
11perf-timechart mainporcelain common 13perf-timechart mainporcelain common
12perf-top mainporcelain common 14perf-top mainporcelain common
13perf-trace mainporcelain common 15perf-trace mainporcelain common
16perf-probe mainporcelain common
17perf-kmem mainporcelain common
diff --git a/tools/perf/design.txt b/tools/perf/design.txt
index fdd42a824c98..f000c30877ac 100644
--- a/tools/perf/design.txt
+++ b/tools/perf/design.txt
@@ -137,6 +137,8 @@ enum sw_event_ids {
137 PERF_COUNT_SW_CPU_MIGRATIONS = 4, 137 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
138 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, 138 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
139 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, 139 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
140 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
141 PERF_COUNT_SW_EMULATION_FAULTS = 8,
140}; 142};
141 143
142Counters of the type PERF_TYPE_TRACEPOINT are available when the ftrace event 144Counters of the type PERF_TYPE_TRACEPOINT are available when the ftrace event
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 19fc7feb9d59..cf64049bc9bd 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -14,6 +14,7 @@
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include "util/string.h" 16#include "util/string.h"
17#include "util/debugfs.h"
17 18
18const char perf_usage_string[] = 19const char perf_usage_string[] =
19 "perf [--version] [--help] COMMAND [ARGS]"; 20 "perf [--version] [--help] COMMAND [ARGS]";
@@ -89,8 +90,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
89 /* 90 /*
90 * Check remaining flags. 91 * Check remaining flags.
91 */ 92 */
92 if (!prefixcmp(cmd, "--exec-path")) { 93 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
93 cmd += 11; 94 cmd += strlen(CMD_EXEC_PATH);
94 if (*cmd == '=') 95 if (*cmd == '=')
95 perf_set_argv_exec_path(cmd + 1); 96 perf_set_argv_exec_path(cmd + 1);
96 else { 97 else {
@@ -117,8 +118,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
117 (*argv)++; 118 (*argv)++;
118 (*argc)--; 119 (*argc)--;
119 handled++; 120 handled++;
120 } else if (!prefixcmp(cmd, "--perf-dir=")) { 121 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
121 setenv(PERF_DIR_ENVIRONMENT, cmd + 10, 1); 122 setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
122 if (envchanged) 123 if (envchanged)
123 *envchanged = 1; 124 *envchanged = 1;
124 } else if (!strcmp(cmd, "--work-tree")) { 125 } else if (!strcmp(cmd, "--work-tree")) {
@@ -131,8 +132,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
131 *envchanged = 1; 132 *envchanged = 1;
132 (*argv)++; 133 (*argv)++;
133 (*argc)--; 134 (*argc)--;
134 } else if (!prefixcmp(cmd, "--work-tree=")) { 135 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 136 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
136 if (envchanged) 137 if (envchanged)
137 *envchanged = 1; 138 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) { 139 } else if (!strcmp(cmd, "--debugfs-dir")) {
@@ -146,8 +147,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
146 *envchanged = 1; 147 *envchanged = 1;
147 (*argv)++; 148 (*argv)++;
148 (*argc)--; 149 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) { 150 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN); 151 strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0'; 152 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged) 153 if (envchanged)
153 *envchanged = 1; 154 *envchanged = 1;
@@ -284,17 +285,21 @@ static void handle_internal_command(int argc, const char **argv)
284{ 285{
285 const char *cmd = argv[0]; 286 const char *cmd = argv[0];
286 static struct cmd_struct commands[] = { 287 static struct cmd_struct commands[] = {
287 { "help", cmd_help, 0 }, 288 { "buildid-list", cmd_buildid_list, 0 },
288 { "list", cmd_list, 0 }, 289 { "help", cmd_help, 0 },
289 { "record", cmd_record, 0 }, 290 { "list", cmd_list, 0 },
290 { "report", cmd_report, 0 }, 291 { "record", cmd_record, 0 },
291 { "stat", cmd_stat, 0 }, 292 { "report", cmd_report, 0 },
292 { "timechart", cmd_timechart, 0 }, 293 { "bench", cmd_bench, 0 },
293 { "top", cmd_top, 0 }, 294 { "stat", cmd_stat, 0 },
294 { "annotate", cmd_annotate, 0 }, 295 { "timechart", cmd_timechart, 0 },
295 { "version", cmd_version, 0 }, 296 { "top", cmd_top, 0 },
296 { "trace", cmd_trace, 0 }, 297 { "annotate", cmd_annotate, 0 },
297 { "sched", cmd_sched, 0 }, 298 { "version", cmd_version, 0 },
299 { "trace", cmd_trace, 0 },
300 { "sched", cmd_sched, 0 },
301 { "probe", cmd_probe, 0 },
302 { "kmem", cmd_kmem, 0 },
298 }; 303 };
299 unsigned int i; 304 unsigned int i;
300 static const char ext[] = STRIP_EXTENSION; 305 static const char ext[] = STRIP_EXTENSION;
@@ -382,45 +387,12 @@ static int run_argv(int *argcp, const char ***argv)
382/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */ 387/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
383static void get_debugfs_mntpt(void) 388static void get_debugfs_mntpt(void)
384{ 389{
385 FILE *file; 390 const char *path = debugfs_find_mountpoint();
386 char fs_type[100];
387 char debugfs[MAXPATHLEN];
388 391
389 /* 392 if (path)
390 * try the standard location 393 strncpy(debugfs_mntpt, path, sizeof(debugfs_mntpt));
391 */ 394 else
392 if (valid_debugfs_mount("/sys/kernel/debug/") == 0) { 395 debugfs_mntpt[0] = '\0';
393 strcpy(debugfs_mntpt, "/sys/kernel/debug/");
394 return;
395 }
396
397 /*
398 * try the sane location
399 */
400 if (valid_debugfs_mount("/debug/") == 0) {
401 strcpy(debugfs_mntpt, "/debug/");
402 return;
403 }
404
405 /*
406 * give up and parse /proc/mounts
407 */
408 file = fopen("/proc/mounts", "r");
409 if (file == NULL)
410 return;
411
412 while (fscanf(file, "%*s %"
413 STR(MAXPATHLEN)
414 "s %99s %*s %*d %*d\n",
415 debugfs, fs_type) == 2) {
416 if (strcmp(fs_type, "debugfs") == 0)
417 break;
418 }
419 fclose(file);
420 if (strcmp(fs_type, "debugfs") == 0) {
421 strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
422 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
423 }
424} 396}
425 397
426int main(int argc, const char **argv) 398int main(int argc, const char **argv)
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 8cc4623afd6f..454d5d55f32d 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -47,6 +47,18 @@
47#define cpu_relax() asm volatile("":::"memory") 47#define cpu_relax() asm volatile("":::"memory")
48#endif 48#endif
49 49
50#ifdef __alpha__
51#include "../../arch/alpha/include/asm/unistd.h"
52#define rmb() asm volatile("mb" ::: "memory")
53#define cpu_relax() asm volatile("" ::: "memory")
54#endif
55
56#ifdef __ia64__
57#include "../../arch/ia64/include/asm/unistd.h"
58#define rmb() asm volatile ("mf" ::: "memory")
59#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
60#endif
61
50#include <time.h> 62#include <time.h>
51#include <unistd.h> 63#include <unistd.h>
52#include <sys/types.h> 64#include <sys/types.h>
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
new file mode 100644
index 000000000000..af78d9a52a7d
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -0,0 +1,134 @@
1/*
2 * This file was generated automatically by ExtUtils::ParseXS version 2.18_02 from the
3 * contents of Context.xs. Do not edit this file, edit Context.xs instead.
4 *
5 * ANY CHANGES MADE HERE WILL BE LOST!
6 *
7 */
8
9#line 1 "Context.xs"
10/*
11 * Context.xs. XS interfaces for perf trace.
12 *
13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30
31#include "EXTERN.h"
32#include "perl.h"
33#include "XSUB.h"
34#include "../../../util/trace-event-perl.h"
35
36#ifndef PERL_UNUSED_VAR
37# define PERL_UNUSED_VAR(var) if (0) var = var
38#endif
39
40#line 41 "Context.c"
41
42XS(XS_Perf__Trace__Context_common_pc); /* prototype to pass -Wmissing-prototypes */
43XS(XS_Perf__Trace__Context_common_pc)
44{
45#ifdef dVAR
46 dVAR; dXSARGS;
47#else
48 dXSARGS;
49#endif
50 if (items != 1)
51 Perl_croak(aTHX_ "Usage: %s(%s)", "Perf::Trace::Context::common_pc", "context");
52 PERL_UNUSED_VAR(cv); /* -W */
53 {
54 struct scripting_context * context = INT2PTR(struct scripting_context *,SvIV(ST(0)));
55 int RETVAL;
56 dXSTARG;
57
58 RETVAL = common_pc(context);
59 XSprePUSH; PUSHi((IV)RETVAL);
60 }
61 XSRETURN(1);
62}
63
64
65XS(XS_Perf__Trace__Context_common_flags); /* prototype to pass -Wmissing-prototypes */
66XS(XS_Perf__Trace__Context_common_flags)
67{
68#ifdef dVAR
69 dVAR; dXSARGS;
70#else
71 dXSARGS;
72#endif
73 if (items != 1)
74 Perl_croak(aTHX_ "Usage: %s(%s)", "Perf::Trace::Context::common_flags", "context");
75 PERL_UNUSED_VAR(cv); /* -W */
76 {
77 struct scripting_context * context = INT2PTR(struct scripting_context *,SvIV(ST(0)));
78 int RETVAL;
79 dXSTARG;
80
81 RETVAL = common_flags(context);
82 XSprePUSH; PUSHi((IV)RETVAL);
83 }
84 XSRETURN(1);
85}
86
87
88XS(XS_Perf__Trace__Context_common_lock_depth); /* prototype to pass -Wmissing-prototypes */
89XS(XS_Perf__Trace__Context_common_lock_depth)
90{
91#ifdef dVAR
92 dVAR; dXSARGS;
93#else
94 dXSARGS;
95#endif
96 if (items != 1)
97 Perl_croak(aTHX_ "Usage: %s(%s)", "Perf::Trace::Context::common_lock_depth", "context");
98 PERL_UNUSED_VAR(cv); /* -W */
99 {
100 struct scripting_context * context = INT2PTR(struct scripting_context *,SvIV(ST(0)));
101 int RETVAL;
102 dXSTARG;
103
104 RETVAL = common_lock_depth(context);
105 XSprePUSH; PUSHi((IV)RETVAL);
106 }
107 XSRETURN(1);
108}
109
110#ifdef __cplusplus
111extern "C"
112#endif
113XS(boot_Perf__Trace__Context); /* prototype to pass -Wmissing-prototypes */
114XS(boot_Perf__Trace__Context)
115{
116#ifdef dVAR
117 dVAR; dXSARGS;
118#else
119 dXSARGS;
120#endif
121 const char* file = __FILE__;
122
123 PERL_UNUSED_VAR(cv); /* -W */
124 PERL_UNUSED_VAR(items); /* -W */
125 XS_VERSION_BOOTCHECK ;
126
127 newXSproto("Perf::Trace::Context::common_pc", XS_Perf__Trace__Context_common_pc, file, "$");
128 newXSproto("Perf::Trace::Context::common_flags", XS_Perf__Trace__Context_common_flags, file, "$");
129 newXSproto("Perf::Trace::Context::common_lock_depth", XS_Perf__Trace__Context_common_lock_depth, file, "$");
130 if (PL_unitcheckav)
131 call_list(PL_scopestack_ix, PL_unitcheckav);
132 XSRETURN_YES;
133}
134
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
new file mode 100644
index 000000000000..fb78006c165e
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
@@ -0,0 +1,41 @@
1/*
2 * Context.xs. XS interfaces for perf trace.
3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "EXTERN.h"
23#include "perl.h"
24#include "XSUB.h"
25#include "../../../util/trace-event-perl.h"
26
27MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
28PROTOTYPES: ENABLE
29
30int
31common_pc(context)
32 struct scripting_context * context
33
34int
35common_flags(context)
36 struct scripting_context * context
37
38int
39common_lock_depth(context)
40 struct scripting_context * context
41
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL b/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL
new file mode 100644
index 000000000000..decdeb0f6789
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL
@@ -0,0 +1,17 @@
1use 5.010000;
2use ExtUtils::MakeMaker;
3# See lib/ExtUtils/MakeMaker.pm for details of how to influence
4# the contents of the Makefile that is written.
5WriteMakefile(
6 NAME => 'Perf::Trace::Context',
7 VERSION_FROM => 'lib/Perf/Trace/Context.pm', # finds $VERSION
8 PREREQ_PM => {}, # e.g., Module::Name => 1.1
9 ($] >= 5.005 ? ## Add these new keywords supported since 5.005
10 (ABSTRACT_FROM => 'lib/Perf/Trace/Context.pm', # retrieve abstract from module
11 AUTHOR => 'Tom Zanussi <tzanussi@gmail.com>') : ()),
12 LIBS => [''], # e.g., '-lm'
13 DEFINE => '-I ../..', # e.g., '-DHAVE_SOMETHING'
14 INC => '-I.', # e.g., '-I. -I/usr/include/other'
15 # Un-comment this if you add C files to link with later:
16 OBJECT => 'Context.o', # link all the C files too
17);
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/README b/tools/perf/scripts/perl/Perf-Trace-Util/README
new file mode 100644
index 000000000000..9a9707630791
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/README
@@ -0,0 +1,59 @@
1Perf-Trace-Util version 0.01
2============================
3
4This module contains utility functions for use with perf trace.
5
6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines
7that the core perf support for Perl calls on and should always be
8'used', while Util.pm contains useful but optional utility functions
9that scripts may want to use. Context.pm contains the Perl->C
10interface that allows scripts to access data in the embedding perf
11executable; scripts wishing to do that should 'use Context.pm'.
12
13The Perl->C perf interface is completely driven by Context.xs. If you
14want to add new Perl functions that end up accessing C data in the
15perf executable, you add desciptions of the new functions here.
16scripting_context is a pointer to the perf data in the perf executable
17that you want to access - it's passed as the second parameter,
18$context, to all handler functions.
19
20After you do that:
21
22 perl Makefile.PL # to create a Makefile for the next step
23 make # to create Context.c
24
25 edit Context.c to add const to the char* file = __FILE__ line in
26 XS(boot_Perf__Trace__Context) to silence a warning/error.
27
28 You can delete the Makefile, object files and anything else that was
29 generated e.g. blib and shared library, etc, except for of course
30 Context.c
31
32 You should then be able to run the normal perf make as usual.
33
34INSTALLATION
35
36Building perf with perf trace Perl scripting should install this
37module in the right place.
38
39You should make sure libperl and ExtUtils/Embed.pm are installed first
40e.g. apt-get install libperl-dev or yum install perl-ExtUtils-Embed.
41
42DEPENDENCIES
43
44This module requires these other modules and libraries:
45
46 None
47
48COPYRIGHT AND LICENCE
49
50Copyright (C) 2009 by Tom Zanussi <tzanussi@gmail.com>
51
52This library is free software; you can redistribute it and/or modify
53it under the same terms as Perl itself, either Perl version 5.10.0 or,
54at your option, any later version of Perl 5 you may have available.
55
56Alternatively, this software may be distributed under the terms of the
57GNU General Public License ("GPL") version 2 as published by the Free
58Software Foundation.
59
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
new file mode 100644
index 000000000000..6c7f3659cb17
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
@@ -0,0 +1,55 @@
1package Perf::Trace::Context;
2
3use 5.010000;
4use strict;
5use warnings;
6
7require Exporter;
8
9our @ISA = qw(Exporter);
10
11our %EXPORT_TAGS = ( 'all' => [ qw(
12) ] );
13
14our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15
16our @EXPORT = qw(
17 common_pc common_flags common_lock_depth
18);
19
20our $VERSION = '0.01';
21
22require XSLoader;
23XSLoader::load('Perf::Trace::Context', $VERSION);
24
251;
26__END__
27=head1 NAME
28
29Perf::Trace::Context - Perl extension for accessing functions in perf.
30
31=head1 SYNOPSIS
32
33 use Perf::Trace::Context;
34
35=head1 SEE ALSO
36
37Perf (trace) documentation
38
39=head1 AUTHOR
40
41Tom Zanussi, E<lt>tzanussi@gmail.com<gt>
42
43=head1 COPYRIGHT AND LICENSE
44
45Copyright (C) 2009 by Tom Zanussi
46
47This library is free software; you can redistribute it and/or modify
48it under the same terms as Perl itself, either Perl version 5.10.0 or,
49at your option, any later version of Perl 5 you may have available.
50
51Alternatively, this software may be distributed under the terms of the
52GNU General Public License ("GPL") version 2 as published by the Free
53Software Foundation.
54
55=cut
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
new file mode 100644
index 000000000000..9df376a9f629
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
@@ -0,0 +1,192 @@
1package Perf::Trace::Core;
2
3use 5.010000;
4use strict;
5use warnings;
6
7require Exporter;
8
9our @ISA = qw(Exporter);
10
11our %EXPORT_TAGS = ( 'all' => [ qw(
12) ] );
13
14our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15
16our @EXPORT = qw(
17define_flag_field define_flag_value flag_str dump_flag_fields
18define_symbolic_field define_symbolic_value symbol_str dump_symbolic_fields
19trace_flag_str
20);
21
22our $VERSION = '0.01';
23
24my %trace_flags = (0x00 => "NONE",
25 0x01 => "IRQS_OFF",
26 0x02 => "IRQS_NOSUPPORT",
27 0x04 => "NEED_RESCHED",
28 0x08 => "HARDIRQ",
29 0x10 => "SOFTIRQ");
30
31sub trace_flag_str
32{
33 my ($value) = @_;
34
35 my $string;
36
37 my $print_delim = 0;
38
39 foreach my $idx (sort {$a <=> $b} keys %trace_flags) {
40 if (!$value && !$idx) {
41 $string .= "NONE";
42 last;
43 }
44
45 if ($idx && ($value & $idx) == $idx) {
46 if ($print_delim) {
47 $string .= " | ";
48 }
49 $string .= "$trace_flags{$idx}";
50 $print_delim = 1;
51 $value &= ~$idx;
52 }
53 }
54
55 return $string;
56}
57
58my %flag_fields;
59my %symbolic_fields;
60
61sub flag_str
62{
63 my ($event_name, $field_name, $value) = @_;
64
65 my $string;
66
67 if ($flag_fields{$event_name}{$field_name}) {
68 my $print_delim = 0;
69 foreach my $idx (sort {$a <=> $b} keys %{$flag_fields{$event_name}{$field_name}{"values"}}) {
70 if (!$value && !$idx) {
71 $string .= "$flag_fields{$event_name}{$field_name}{'values'}{$idx}";
72 last;
73 }
74 if ($idx && ($value & $idx) == $idx) {
75 if ($print_delim && $flag_fields{$event_name}{$field_name}{'delim'}) {
76 $string .= " $flag_fields{$event_name}{$field_name}{'delim'} ";
77 }
78 $string .= "$flag_fields{$event_name}{$field_name}{'values'}{$idx}";
79 $print_delim = 1;
80 $value &= ~$idx;
81 }
82 }
83 }
84
85 return $string;
86}
87
88sub define_flag_field
89{
90 my ($event_name, $field_name, $delim) = @_;
91
92 $flag_fields{$event_name}{$field_name}{"delim"} = $delim;
93}
94
95sub define_flag_value
96{
97 my ($event_name, $field_name, $value, $field_str) = @_;
98
99 $flag_fields{$event_name}{$field_name}{"values"}{$value} = $field_str;
100}
101
102sub dump_flag_fields
103{
104 for my $event (keys %flag_fields) {
105 print "event $event:\n";
106 for my $field (keys %{$flag_fields{$event}}) {
107 print " field: $field:\n";
108 print " delim: $flag_fields{$event}{$field}{'delim'}\n";
109 foreach my $idx (sort {$a <=> $b} keys %{$flag_fields{$event}{$field}{"values"}}) {
110 print " value $idx: $flag_fields{$event}{$field}{'values'}{$idx}\n";
111 }
112 }
113 }
114}
115
116sub symbol_str
117{
118 my ($event_name, $field_name, $value) = @_;
119
120 if ($symbolic_fields{$event_name}{$field_name}) {
121 foreach my $idx (sort {$a <=> $b} keys %{$symbolic_fields{$event_name}{$field_name}{"values"}}) {
122 if (!$value && !$idx) {
123 return "$symbolic_fields{$event_name}{$field_name}{'values'}{$idx}";
124 last;
125 }
126 if ($value == $idx) {
127 return "$symbolic_fields{$event_name}{$field_name}{'values'}{$idx}";
128 }
129 }
130 }
131
132 return undef;
133}
134
135sub define_symbolic_field
136{
137 my ($event_name, $field_name) = @_;
138
139 # nothing to do, really
140}
141
142sub define_symbolic_value
143{
144 my ($event_name, $field_name, $value, $field_str) = @_;
145
146 $symbolic_fields{$event_name}{$field_name}{"values"}{$value} = $field_str;
147}
148
149sub dump_symbolic_fields
150{
151 for my $event (keys %symbolic_fields) {
152 print "event $event:\n";
153 for my $field (keys %{$symbolic_fields{$event}}) {
154 print " field: $field:\n";
155 foreach my $idx (sort {$a <=> $b} keys %{$symbolic_fields{$event}{$field}{"values"}}) {
156 print " value $idx: $symbolic_fields{$event}{$field}{'values'}{$idx}\n";
157 }
158 }
159 }
160}
161
1621;
163__END__
164=head1 NAME
165
166Perf::Trace::Core - Perl extension for perf trace
167
168=head1 SYNOPSIS
169
170 use Perf::Trace::Core
171
172=head1 SEE ALSO
173
174Perf (trace) documentation
175
176=head1 AUTHOR
177
178Tom Zanussi, E<lt>tzanussi@gmail.com<gt>
179
180=head1 COPYRIGHT AND LICENSE
181
182Copyright (C) 2009 by Tom Zanussi
183
184This library is free software; you can redistribute it and/or modify
185it under the same terms as Perl itself, either Perl version 5.10.0 or,
186at your option, any later version of Perl 5 you may have available.
187
188Alternatively, this software may be distributed under the terms of the
189GNU General Public License ("GPL") version 2 as published by the Free
190Software Foundation.
191
192=cut
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
new file mode 100644
index 000000000000..052f132ced24
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -0,0 +1,88 @@
1package Perf::Trace::Util;
2
3use 5.010000;
4use strict;
5use warnings;
6
7require Exporter;
8
9our @ISA = qw(Exporter);
10
11our %EXPORT_TAGS = ( 'all' => [ qw(
12) ] );
13
14our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15
16our @EXPORT = qw(
17avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs
18);
19
20our $VERSION = '0.01';
21
22sub avg
23{
24 my ($total, $n) = @_;
25
26 return $total / $n;
27}
28
29my $NSECS_PER_SEC = 1000000000;
30
31sub nsecs
32{
33 my ($secs, $nsecs) = @_;
34
35 return $secs * $NSECS_PER_SEC + $nsecs;
36}
37
38sub nsecs_secs {
39 my ($nsecs) = @_;
40
41 return $nsecs / $NSECS_PER_SEC;
42}
43
44sub nsecs_nsecs {
45 my ($nsecs) = @_;
46
47 return $nsecs - nsecs_secs($nsecs);
48}
49
50sub nsecs_str {
51 my ($nsecs) = @_;
52
53 my $str = sprintf("%5u.%09u", nsecs_secs($nsecs), nsecs_nsecs($nsecs));
54
55 return $str;
56}
57
581;
59__END__
60=head1 NAME
61
62Perf::Trace::Util - Perl extension for perf trace
63
64=head1 SYNOPSIS
65
66 use Perf::Trace::Util;
67
68=head1 SEE ALSO
69
70Perf (trace) documentation
71
72=head1 AUTHOR
73
74Tom Zanussi, E<lt>tzanussi@gmail.com<gt>
75
76=head1 COPYRIGHT AND LICENSE
77
78Copyright (C) 2009 by Tom Zanussi
79
80This library is free software; you can redistribute it and/or modify
81it under the same terms as Perl itself, either Perl version 5.10.0 or,
82at your option, any later version of Perl 5 you may have available.
83
84Alternatively, this software may be distributed under the terms of the
85GNU General Public License ("GPL") version 2 as published by the Free
86Software Foundation.
87
88=cut
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/typemap b/tools/perf/scripts/perl/Perf-Trace-Util/typemap
new file mode 100644
index 000000000000..840836804aa7
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/typemap
@@ -0,0 +1 @@
struct scripting_context * T_PTR
diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-record b/tools/perf/scripts/perl/bin/check-perf-trace-record
new file mode 100644
index 000000000000..c7ec5de2f535
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/check-perf-trace-record
@@ -0,0 +1,7 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e kmem:kmalloc -e irq:softirq_entry
3
4
5
6
7
diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-report b/tools/perf/scripts/perl/bin/check-perf-trace-report
new file mode 100644
index 000000000000..89948b015020
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/check-perf-trace-report
@@ -0,0 +1,5 @@
1#!/bin/bash
2perf trace -s ~/libexec/perf-core/scripts/perl/check-perf-trace.pl
3
4
5
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
new file mode 100644
index 000000000000..b25056ebf963
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
new file mode 100644
index 000000000000..f5dcf9cb5bd2
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -0,0 +1,5 @@
1#!/bin/bash
2perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl
3
4
5
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
new file mode 100644
index 000000000000..8903979c5b6c
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
new file mode 100644
index 000000000000..cea16f78a3a2
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -0,0 +1,5 @@
1#!/bin/bash
2perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl
3
4
5
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
new file mode 100644
index 000000000000..6abedda911a4
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -0,0 +1,6 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup
3
4
5
6
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
new file mode 100644
index 000000000000..85769dc456eb
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -0,0 +1,5 @@
1#!/bin/bash
2perf trace -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl
3
4
5
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
new file mode 100644
index 000000000000..fce6637b19ba
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
new file mode 100644
index 000000000000..aa68435be926
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -0,0 +1,6 @@
1#!/bin/bash
2perf trace -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl
3
4
5
6
diff --git a/tools/perf/scripts/perl/check-perf-trace.pl b/tools/perf/scripts/perl/check-perf-trace.pl
new file mode 100644
index 000000000000..4e7dc0a407a5
--- /dev/null
+++ b/tools/perf/scripts/perl/check-perf-trace.pl
@@ -0,0 +1,106 @@
1# perf trace event handlers, generated by perf trace -g perl
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# This script tests basic functionality such as flag and symbol
6# strings, common_xxx() calls back into perf, begin, end, unhandled
7# events, etc. Basically, if this script runs successfully and
8# displays expected results, perl scripting support should be ok.
9
10use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
11use lib "./Perf-Trace-Util/lib";
12use Perf::Trace::Core;
13use Perf::Trace::Context;
14use Perf::Trace::Util;
15
16sub trace_begin
17{
18 print "trace_begin\n";
19}
20
21sub trace_end
22{
23 print "trace_end\n";
24
25 print_unhandled();
26}
27
28sub irq::softirq_entry
29{
30 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
31 $common_pid, $common_comm,
32 $vec) = @_;
33
34 print_header($event_name, $common_cpu, $common_secs, $common_nsecs,
35 $common_pid, $common_comm);
36
37 print_uncommon($context);
38
39 printf("vec=%s\n",
40 symbol_str("irq::softirq_entry", "vec", $vec));
41}
42
43sub kmem::kmalloc
44{
45 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
46 $common_pid, $common_comm,
47 $call_site, $ptr, $bytes_req, $bytes_alloc,
48 $gfp_flags) = @_;
49
50 print_header($event_name, $common_cpu, $common_secs, $common_nsecs,
51 $common_pid, $common_comm);
52
53 print_uncommon($context);
54
55 printf("call_site=%p, ptr=%p, bytes_req=%u, bytes_alloc=%u, ".
56 "gfp_flags=%s\n",
57 $call_site, $ptr, $bytes_req, $bytes_alloc,
58
59 flag_str("kmem::kmalloc", "gfp_flags", $gfp_flags));
60}
61
62# print trace fields not included in handler args
63sub print_uncommon
64{
65 my ($context) = @_;
66
67 printf("common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, ",
68 common_pc($context), trace_flag_str(common_flags($context)),
69 common_lock_depth($context));
70
71}
72
73my %unhandled;
74
75sub print_unhandled
76{
77 if ((scalar keys %unhandled) == 0) {
78 return;
79 }
80
81 print "\nunhandled events:\n\n";
82
83 printf("%-40s %10s\n", "event", "count");
84 printf("%-40s %10s\n", "----------------------------------------",
85 "-----------");
86
87 foreach my $event_name (keys %unhandled) {
88 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
89 }
90}
91
92sub trace_unhandled
93{
94 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
95 $common_pid, $common_comm) = @_;
96
97 $unhandled{$event_name}++;
98}
99
100sub print_header
101{
102 my ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;
103
104 printf("%-20s %5u %05u.%09u %8u %-20s ",
105 $event_name, $cpu, $secs, $nsecs, $pid, $comm);
106}
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
new file mode 100644
index 000000000000..61f91561d848
--- /dev/null
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -0,0 +1,105 @@
1#!/usr/bin/perl -w
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# Display r/w activity for files read/written to for a given program
6
7# The common_* event handler fields are the most useful fields common to
8# all events. They don't necessarily correspond to the 'common_*' fields
9# in the status files. Those fields not available as handler params can
10# be retrieved via script functions of the form get_common_*().
11
12use 5.010000;
13use strict;
14use warnings;
15
16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core;
19use Perf::Trace::Util;
20
21# change this to the comm of the program you're interested in
22my $for_comm = "perf";
23
24my %reads;
25my %writes;
26
27sub syscalls::sys_enter_read
28{
29 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
30 $common_pid, $common_comm, $nr, $fd, $buf, $count) = @_;
31
32 if ($common_comm eq $for_comm) {
33 $reads{$fd}{bytes_requested} += $count;
34 $reads{$fd}{total_reads}++;
35 }
36}
37
38sub syscalls::sys_enter_write
39{
40 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
41 $common_pid, $common_comm, $nr, $fd, $buf, $count) = @_;
42
43 if ($common_comm eq $for_comm) {
44 $writes{$fd}{bytes_written} += $count;
45 $writes{$fd}{total_writes}++;
46 }
47}
48
49sub trace_end
50{
51 printf("file read counts for $for_comm:\n\n");
52
53 printf("%6s %10s %10s\n", "fd", "# reads", "bytes_requested");
54 printf("%6s %10s %10s\n", "------", "----------", "-----------");
55
56 foreach my $fd (sort {$reads{$b}{bytes_requested} <=>
57 $reads{$a}{bytes_requested}} keys %reads) {
58 my $total_reads = $reads{$fd}{total_reads};
59 my $bytes_requested = $reads{$fd}{bytes_requested};
60 printf("%6u %10u %10u\n", $fd, $total_reads, $bytes_requested);
61 }
62
63 printf("\nfile write counts for $for_comm:\n\n");
64
65 printf("%6s %10s %10s\n", "fd", "# writes", "bytes_written");
66 printf("%6s %10s %10s\n", "------", "----------", "-----------");
67
68 foreach my $fd (sort {$writes{$b}{bytes_written} <=>
69 $writes{$a}{bytes_written}} keys %writes) {
70 my $total_writes = $writes{$fd}{total_writes};
71 my $bytes_written = $writes{$fd}{bytes_written};
72 printf("%6u %10u %10u\n", $fd, $total_writes, $bytes_written);
73 }
74
75 print_unhandled();
76}
77
78my %unhandled;
79
80sub print_unhandled
81{
82 if ((scalar keys %unhandled) == 0) {
83 return;
84 }
85
86 print "\nunhandled events:\n\n";
87
88 printf("%-40s %10s\n", "event", "count");
89 printf("%-40s %10s\n", "----------------------------------------",
90 "-----------");
91
92 foreach my $event_name (keys %unhandled) {
93 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
94 }
95}
96
97sub trace_unhandled
98{
99 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
100 $common_pid, $common_comm) = @_;
101
102 $unhandled{$event_name}++;
103}
104
105
diff --git a/tools/perf/scripts/perl/rw-by-pid.pl b/tools/perf/scripts/perl/rw-by-pid.pl
new file mode 100644
index 000000000000..da601fae1a00
--- /dev/null
+++ b/tools/perf/scripts/perl/rw-by-pid.pl
@@ -0,0 +1,170 @@
1#!/usr/bin/perl -w
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# Display r/w activity for all processes
6
7# The common_* event handler fields are the most useful fields common to
8# all events. They don't necessarily correspond to the 'common_*' fields
9# in the status files. Those fields not available as handler params can
10# be retrieved via script functions of the form get_common_*().
11
12use 5.010000;
13use strict;
14use warnings;
15
16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core;
19use Perf::Trace::Util;
20
21my %reads;
22my %writes;
23
24sub syscalls::sys_exit_read
25{
26 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
27 $common_pid, $common_comm,
28 $nr, $ret) = @_;
29
30 if ($ret > 0) {
31 $reads{$common_pid}{bytes_read} += $ret;
32 } else {
33 if (!defined ($reads{$common_pid}{bytes_read})) {
34 $reads{$common_pid}{bytes_read} = 0;
35 }
36 $reads{$common_pid}{errors}{$ret}++;
37 }
38}
39
40sub syscalls::sys_enter_read
41{
42 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
43 $common_pid, $common_comm,
44 $nr, $fd, $buf, $count) = @_;
45
46 $reads{$common_pid}{bytes_requested} += $count;
47 $reads{$common_pid}{total_reads}++;
48 $reads{$common_pid}{comm} = $common_comm;
49}
50
51sub syscalls::sys_exit_write
52{
53 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
54 $common_pid, $common_comm,
55 $nr, $ret) = @_;
56
57 if ($ret <= 0) {
58 $writes{$common_pid}{errors}{$ret}++;
59 }
60}
61
62sub syscalls::sys_enter_write
63{
64 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
65 $common_pid, $common_comm,
66 $nr, $fd, $buf, $count) = @_;
67
68 $writes{$common_pid}{bytes_written} += $count;
69 $writes{$common_pid}{total_writes}++;
70 $writes{$common_pid}{comm} = $common_comm;
71}
72
73sub trace_end
74{
75 printf("read counts by pid:\n\n");
76
77 printf("%6s %20s %10s %10s %10s\n", "pid", "comm",
78 "# reads", "bytes_requested", "bytes_read");
79 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------",
80 "-----------", "----------", "----------");
81
82 foreach my $pid (sort {$reads{$b}{bytes_read} <=>
83 $reads{$a}{bytes_read}} keys %reads) {
84 my $comm = $reads{$pid}{comm};
85 my $total_reads = $reads{$pid}{total_reads};
86 my $bytes_requested = $reads{$pid}{bytes_requested};
87 my $bytes_read = $reads{$pid}{bytes_read};
88
89 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm,
90 $total_reads, $bytes_requested, $bytes_read);
91 }
92
93 printf("\nfailed reads by pid:\n\n");
94
95 printf("%6s %20s %6s %10s\n", "pid", "comm", "error #", "# errors");
96 printf("%6s %20s %6s %10s\n", "------", "--------------------",
97 "------", "----------");
98
99 foreach my $pid (keys %reads) {
100 my $comm = $reads{$pid}{comm};
101 foreach my $err (sort {$reads{$b}{comm} cmp $reads{$a}{comm}}
102 keys %{$reads{$pid}{errors}}) {
103 my $errors = $reads{$pid}{errors}{$err};
104
105 printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors);
106 }
107 }
108
109 printf("\nwrite counts by pid:\n\n");
110
111 printf("%6s %20s %10s %10s\n", "pid", "comm",
112 "# writes", "bytes_written");
113 printf("%6s %-20s %10s %10s\n", "------", "--------------------",
114 "-----------", "----------");
115
116 foreach my $pid (sort {$writes{$b}{bytes_written} <=>
117 $writes{$a}{bytes_written}} keys %writes) {
118 my $comm = $writes{$pid}{comm};
119 my $total_writes = $writes{$pid}{total_writes};
120 my $bytes_written = $writes{$pid}{bytes_written};
121
122 printf("%6s %-20s %10s %10s\n", $pid, $comm,
123 $total_writes, $bytes_written);
124 }
125
126 printf("\nfailed writes by pid:\n\n");
127
128 printf("%6s %20s %6s %10s\n", "pid", "comm", "error #", "# errors");
129 printf("%6s %20s %6s %10s\n", "------", "--------------------",
130 "------", "----------");
131
132 foreach my $pid (keys %writes) {
133 my $comm = $writes{$pid}{comm};
134 foreach my $err (sort {$writes{$b}{comm} cmp $writes{$a}{comm}}
135 keys %{$writes{$pid}{errors}}) {
136 my $errors = $writes{$pid}{errors}{$err};
137
138 printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors);
139 }
140 }
141
142 print_unhandled();
143}
144
145my %unhandled;
146
147sub print_unhandled
148{
149 if ((scalar keys %unhandled) == 0) {
150 return;
151 }
152
153 print "\nunhandled events:\n\n";
154
155 printf("%-40s %10s\n", "event", "count");
156 printf("%-40s %10s\n", "----------------------------------------",
157 "-----------");
158
159 foreach my $event_name (keys %unhandled) {
160 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
161 }
162}
163
164sub trace_unhandled
165{
166 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
167 $common_pid, $common_comm) = @_;
168
169 $unhandled{$event_name}++;
170}
diff --git a/tools/perf/scripts/perl/wakeup-latency.pl b/tools/perf/scripts/perl/wakeup-latency.pl
new file mode 100644
index 000000000000..ed58ef284e23
--- /dev/null
+++ b/tools/perf/scripts/perl/wakeup-latency.pl
@@ -0,0 +1,103 @@
1#!/usr/bin/perl -w
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# Display avg/min/max wakeup latency
6
7# The common_* event handler fields are the most useful fields common to
8# all events. They don't necessarily correspond to the 'common_*' fields
9# in the status files. Those fields not available as handler params can
10# be retrieved via script functions of the form get_common_*().
11
12use 5.010000;
13use strict;
14use warnings;
15
16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core;
19use Perf::Trace::Util;
20
21my %last_wakeup;
22
23my $max_wakeup_latency;
24my $min_wakeup_latency;
25my $total_wakeup_latency;
26my $total_wakeups;
27
28sub sched::sched_switch
29{
30 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
31 $common_pid, $common_comm,
32 $prev_comm, $prev_pid, $prev_prio, $prev_state, $next_comm, $next_pid,
33 $next_prio) = @_;
34
35 my $wakeup_ts = $last_wakeup{$common_cpu}{ts};
36 if ($wakeup_ts) {
37 my $switch_ts = nsecs($common_secs, $common_nsecs);
38 my $wakeup_latency = $switch_ts - $wakeup_ts;
39 if ($wakeup_latency > $max_wakeup_latency) {
40 $max_wakeup_latency = $wakeup_latency;
41 }
42 if ($wakeup_latency < $min_wakeup_latency) {
43 $min_wakeup_latency = $wakeup_latency;
44 }
45 $total_wakeup_latency += $wakeup_latency;
46 $total_wakeups++;
47 }
48 $last_wakeup{$common_cpu}{ts} = 0;
49}
50
51sub sched::sched_wakeup
52{
53 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
54 $common_pid, $common_comm,
55 $comm, $pid, $prio, $success, $target_cpu) = @_;
56
57 $last_wakeup{$target_cpu}{ts} = nsecs($common_secs, $common_nsecs);
58}
59
60sub trace_begin
61{
62 $min_wakeup_latency = 1000000000;
63 $max_wakeup_latency = 0;
64}
65
66sub trace_end
67{
68 printf("wakeup_latency stats:\n\n");
69 print "total_wakeups: $total_wakeups\n";
70 printf("avg_wakeup_latency (ns): %u\n",
71 avg($total_wakeup_latency, $total_wakeups));
72 printf("min_wakeup_latency (ns): %u\n", $min_wakeup_latency);
73 printf("max_wakeup_latency (ns): %u\n", $max_wakeup_latency);
74
75 print_unhandled();
76}
77
78my %unhandled;
79
80sub print_unhandled
81{
82 if ((scalar keys %unhandled) == 0) {
83 return;
84 }
85
86 print "\nunhandled events:\n\n";
87
88 printf("%-40s %10s\n", "event", "count");
89 printf("%-40s %10s\n", "----------------------------------------",
90 "-----------");
91
92 foreach my $event_name (keys %unhandled) {
93 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
94 }
95}
96
97sub trace_unhandled
98{
99 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
100 $common_pid, $common_comm) = @_;
101
102 $unhandled{$event_name}++;
103}
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
new file mode 100644
index 000000000000..511302c8a494
--- /dev/null
+++ b/tools/perf/scripts/perl/workqueue-stats.pl
@@ -0,0 +1,129 @@
1#!/usr/bin/perl -w
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# Displays workqueue stats
6#
7# Usage:
8#
9# perf record -c 1 -f -a -R -e workqueue:workqueue_creation -e
10# workqueue:workqueue_destruction -e workqueue:workqueue_execution
11# -e workqueue:workqueue_insertion
12#
13# perf trace -p -s tools/perf/scripts/perl/workqueue-stats.pl
14
15use 5.010000;
16use strict;
17use warnings;
18
19use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
20use lib "./Perf-Trace-Util/lib";
21use Perf::Trace::Core;
22use Perf::Trace::Util;
23
24my @cpus;
25
26sub workqueue::workqueue_destruction
27{
28 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
29 $common_pid, $common_comm,
30 $thread_comm, $thread_pid) = @_;
31
32 $cpus[$common_cpu]{$thread_pid}{destroyed}++;
33 $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
34}
35
36sub workqueue::workqueue_creation
37{
38 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
39 $common_pid, $common_comm,
40 $thread_comm, $thread_pid, $cpu) = @_;
41
42 $cpus[$common_cpu]{$thread_pid}{created}++;
43 $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
44}
45
46sub workqueue::workqueue_execution
47{
48 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
49 $common_pid, $common_comm,
50 $thread_comm, $thread_pid, $func) = @_;
51
52 $cpus[$common_cpu]{$thread_pid}{executed}++;
53 $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
54}
55
56sub workqueue::workqueue_insertion
57{
58 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
59 $common_pid, $common_comm,
60 $thread_comm, $thread_pid, $func) = @_;
61
62 $cpus[$common_cpu]{$thread_pid}{inserted}++;
63 $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
64}
65
66sub trace_end
67{
68 print "workqueue work stats:\n\n";
69 my $cpu = 0;
70 printf("%3s %6s %6s\t%-20s\n", "cpu", "ins", "exec", "name");
71 printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----");
72 foreach my $pidhash (@cpus) {
73 while ((my $pid, my $wqhash) = each %$pidhash) {
74 my $ins = $$wqhash{'inserted'};
75 my $exe = $$wqhash{'executed'};
76 my $comm = $$wqhash{'comm'};
77 if ($ins || $exe) {
78 printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm);
79 }
80 }
81 $cpu++;
82 }
83
84 $cpu = 0;
85 print "\nworkqueue lifecycle stats:\n\n";
86 printf("%3s %6s %6s\t%-20s\n", "cpu", "created", "destroyed", "name");
87 printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----");
88 foreach my $pidhash (@cpus) {
89 while ((my $pid, my $wqhash) = each %$pidhash) {
90 my $created = $$wqhash{'created'};
91 my $destroyed = $$wqhash{'destroyed'};
92 my $comm = $$wqhash{'comm'};
93 if ($created || $destroyed) {
94 printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed,
95 $comm);
96 }
97 }
98 $cpu++;
99 }
100
101 print_unhandled();
102}
103
104my %unhandled;
105
106sub print_unhandled
107{
108 if ((scalar keys %unhandled) == 0) {
109 return;
110 }
111
112 print "\nunhandled events:\n\n";
113
114 printf("%-40s %10s\n", "event", "count");
115 printf("%-40s %10s\n", "----------------------------------------",
116 "-----------");
117
118 foreach my $event_name (keys %unhandled) {
119 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
120 }
121}
122
123sub trace_unhandled
124{
125 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
126 $common_pid, $common_comm) = @_;
127
128 $unhandled{$event_name}++;
129}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 6f8ea9d210b6..918eb376abe3 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,10 +1,15 @@
1#ifndef CACHE_H 1#ifndef __PERF_CACHE_H
2#define CACHE_H 2#define __PERF_CACHE_H
3 3
4#include "util.h" 4#include "util.h"
5#include "strbuf.h" 5#include "strbuf.h"
6#include "../perf.h" 6#include "../perf.h"
7 7
8#define CMD_EXEC_PATH "--exec-path"
9#define CMD_PERF_DIR "--perf-dir="
10#define CMD_WORK_TREE "--work-tree="
11#define CMD_DEBUGFS_DIR "--debugfs-dir="
12
8#define PERF_DIR_ENVIRONMENT "PERF_DIR" 13#define PERF_DIR_ENVIRONMENT "PERF_DIR"
9#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 14#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
10#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 15#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
@@ -117,4 +122,4 @@ extern char *perf_pathdup(const char *fmt, ...)
117 122
118extern size_t strlcpy(char *dest, const char *src, size_t size); 123extern size_t strlcpy(char *dest, const char *src, size_t size);
119 124
120#endif /* CACHE_H */ 125#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 3b8380f1b478..b3b71258272a 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -206,7 +206,7 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain,
206 } 206 }
207 node->val_nr = chain->nr - start; 207 node->val_nr = chain->nr - start;
208 if (!node->val_nr) 208 if (!node->val_nr)
209 printf("Warning: empty node in callchain tree\n"); 209 pr_warning("Warning: empty node in callchain tree\n");
210} 210}
211 211
212static void 212static void
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 43cf3ea9e088..ad4626de4c2b 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -58,4 +58,4 @@ static inline u64 cumul_hits(struct callchain_node *node)
58int register_callchain_param(struct callchain_param *param); 58int register_callchain_param(struct callchain_param *param);
59void append_chain(struct callchain_node *root, struct ip_callchain *chain, 59void append_chain(struct callchain_node *root, struct ip_callchain *chain,
60 struct symbol **syms); 60 struct symbol **syms);
61#endif 61#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 58d597564b99..24e8809210bb 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,5 +1,5 @@
1#ifndef COLOR_H 1#ifndef __PERF_COLOR_H
2#define COLOR_H 2#define __PERF_COLOR_H
3 3
4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ 4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
5#define COLOR_MAXLEN 24 5#define COLOR_MAXLEN 24
@@ -39,4 +39,4 @@ int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *bu
39int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 39int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
40const char *get_percent_color(double percent); 40const char *get_percent_color(double percent);
41 41
42#endif /* COLOR_H */ 42#endif /* __PERF_COLOR_H */
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 0b791bd346bc..35073621e5de 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -29,3 +29,11 @@ unsigned char sane_ctype[256] = {
29 A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */ 29 A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */
30 /* Nothing in the 128.. range */ 30 /* Nothing in the 128.. range */
31}; 31};
32
33const char *graph_line =
34 "_____________________________________________________________________"
35 "_____________________________________________________________________";
36const char *graph_dotted_line =
37 "---------------------------------------------------------------------"
38 "---------------------------------------------------------------------"
39 "---------------------------------------------------------------------";
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
new file mode 100644
index 000000000000..ca0bedf637c2
--- /dev/null
+++ b/tools/perf/util/data_map.c
@@ -0,0 +1,291 @@
1#include "data_map.h"
2#include "symbol.h"
3#include "util.h"
4#include "debug.h"
5
6
7static struct perf_file_handler *curr_handler;
8static unsigned long mmap_window = 32;
9static char __cwd[PATH_MAX];
10
11static int process_event_stub(event_t *event __used)
12{
13 dump_printf(": unhandled!\n");
14 return 0;
15}
16
17void register_perf_file_handler(struct perf_file_handler *handler)
18{
19 if (!handler->process_sample_event)
20 handler->process_sample_event = process_event_stub;
21 if (!handler->process_mmap_event)
22 handler->process_mmap_event = process_event_stub;
23 if (!handler->process_comm_event)
24 handler->process_comm_event = process_event_stub;
25 if (!handler->process_fork_event)
26 handler->process_fork_event = process_event_stub;
27 if (!handler->process_exit_event)
28 handler->process_exit_event = process_event_stub;
29 if (!handler->process_lost_event)
30 handler->process_lost_event = process_event_stub;
31 if (!handler->process_read_event)
32 handler->process_read_event = process_event_stub;
33 if (!handler->process_throttle_event)
34 handler->process_throttle_event = process_event_stub;
35 if (!handler->process_unthrottle_event)
36 handler->process_unthrottle_event = process_event_stub;
37
38 curr_handler = handler;
39}
40
41static const char *event__name[] = {
42 [0] = "TOTAL",
43 [PERF_RECORD_MMAP] = "MMAP",
44 [PERF_RECORD_LOST] = "LOST",
45 [PERF_RECORD_COMM] = "COMM",
46 [PERF_RECORD_EXIT] = "EXIT",
47 [PERF_RECORD_THROTTLE] = "THROTTLE",
48 [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
49 [PERF_RECORD_FORK] = "FORK",
50 [PERF_RECORD_READ] = "READ",
51 [PERF_RECORD_SAMPLE] = "SAMPLE",
52};
53
54unsigned long event__total[PERF_RECORD_MAX];
55
56void event__print_totals(void)
57{
58 int i;
59 for (i = 0; i < PERF_RECORD_MAX; ++i)
60 pr_info("%10s events: %10ld\n",
61 event__name[i], event__total[i]);
62}
63
64static int
65process_event(event_t *event, unsigned long offset, unsigned long head)
66{
67 trace_event(event);
68
69 if (event->header.type < PERF_RECORD_MAX) {
70 dump_printf("%p [%p]: PERF_RECORD_%s",
71 (void *)(offset + head),
72 (void *)(long)(event->header.size),
73 event__name[event->header.type]);
74 ++event__total[0];
75 ++event__total[event->header.type];
76 }
77
78 switch (event->header.type) {
79 case PERF_RECORD_SAMPLE:
80 return curr_handler->process_sample_event(event);
81 case PERF_RECORD_MMAP:
82 return curr_handler->process_mmap_event(event);
83 case PERF_RECORD_COMM:
84 return curr_handler->process_comm_event(event);
85 case PERF_RECORD_FORK:
86 return curr_handler->process_fork_event(event);
87 case PERF_RECORD_EXIT:
88 return curr_handler->process_exit_event(event);
89 case PERF_RECORD_LOST:
90 return curr_handler->process_lost_event(event);
91 case PERF_RECORD_READ:
92 return curr_handler->process_read_event(event);
93 case PERF_RECORD_THROTTLE:
94 return curr_handler->process_throttle_event(event);
95 case PERF_RECORD_UNTHROTTLE:
96 return curr_handler->process_unthrottle_event(event);
97 default:
98 curr_handler->total_unknown++;
99 return -1;
100 }
101}
102
103int perf_header__read_build_ids(int input, off_t offset, off_t size)
104{
105 struct build_id_event bev;
106 char filename[PATH_MAX];
107 off_t limit = offset + size;
108 int err = -1;
109
110 while (offset < limit) {
111 struct dso *dso;
112 ssize_t len;
113
114 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
115 goto out;
116
117 len = bev.header.size - sizeof(bev);
118 if (read(input, filename, len) != len)
119 goto out;
120
121 dso = dsos__findnew(filename);
122 if (dso != NULL)
123 dso__set_build_id(dso, &bev.build_id);
124
125 offset += bev.header.size;
126 }
127 err = 0;
128out:
129 return err;
130}
131
132int mmap_dispatch_perf_file(struct perf_header **pheader,
133 const char *input_name,
134 int force,
135 int full_paths,
136 int *cwdlen,
137 char **cwd)
138{
139 int err;
140 struct perf_header *header;
141 unsigned long head, shift;
142 unsigned long offset = 0;
143 struct stat input_stat;
144 size_t page_size;
145 u64 sample_type;
146 event_t *event;
147 uint32_t size;
148 int input;
149 char *buf;
150
151 if (curr_handler == NULL) {
152 pr_debug("Forgot to register perf file handler\n");
153 return -EINVAL;
154 }
155
156 page_size = getpagesize();
157
158 input = open(input_name, O_RDONLY);
159 if (input < 0) {
160 pr_err("Failed to open file: %s", input_name);
161 if (!strcmp(input_name, "perf.data"))
162 pr_err(" (try 'perf record' first)");
163 pr_err("\n");
164 return -errno;
165 }
166
167 if (fstat(input, &input_stat) < 0) {
168 pr_err("failed to stat file");
169 err = -errno;
170 goto out_close;
171 }
172
173 err = -EACCES;
174 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
175 pr_err("file: %s not owned by current user or root\n",
176 input_name);
177 goto out_close;
178 }
179
180 if (input_stat.st_size == 0) {
181 pr_info("zero-sized file, nothing to do!\n");
182 goto done;
183 }
184
185 err = -ENOMEM;
186 header = perf_header__new();
187 if (header == NULL)
188 goto out_close;
189
190 err = perf_header__read(header, input);
191 if (err < 0)
192 goto out_delete;
193 *pheader = header;
194 head = header->data_offset;
195
196 sample_type = perf_header__sample_type(header);
197
198 err = -EINVAL;
199 if (curr_handler->sample_type_check &&
200 curr_handler->sample_type_check(sample_type) < 0)
201 goto out_delete;
202
203 if (!full_paths) {
204 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
205 pr_err("failed to get the current directory\n");
206 err = -errno;
207 goto out_delete;
208 }
209 *cwd = __cwd;
210 *cwdlen = strlen(*cwd);
211 } else {
212 *cwd = NULL;
213 *cwdlen = 0;
214 }
215
216 shift = page_size * (head / page_size);
217 offset += shift;
218 head -= shift;
219
220remap:
221 buf = mmap(NULL, page_size * mmap_window, PROT_READ,
222 MAP_SHARED, input, offset);
223 if (buf == MAP_FAILED) {
224 pr_err("failed to mmap file\n");
225 err = -errno;
226 goto out_delete;
227 }
228
229more:
230 event = (event_t *)(buf + head);
231
232 size = event->header.size;
233 if (!size)
234 size = 8;
235
236 if (head + event->header.size >= page_size * mmap_window) {
237 int munmap_ret;
238
239 shift = page_size * (head / page_size);
240
241 munmap_ret = munmap(buf, page_size * mmap_window);
242 assert(munmap_ret == 0);
243
244 offset += shift;
245 head -= shift;
246 goto remap;
247 }
248
249 size = event->header.size;
250
251 dump_printf("\n%p [%p]: event: %d\n",
252 (void *)(offset + head),
253 (void *)(long)event->header.size,
254 event->header.type);
255
256 if (!size || process_event(event, offset, head) < 0) {
257
258 dump_printf("%p [%p]: skipping unknown header type: %d\n",
259 (void *)(offset + head),
260 (void *)(long)(event->header.size),
261 event->header.type);
262
263 /*
264 * assume we lost track of the stream, check alignment, and
265 * increment a single u64 in the hope to catch on again 'soon'.
266 */
267
268 if (unlikely(head & 7))
269 head &= ~7ULL;
270
271 size = 8;
272 }
273
274 head += size;
275
276 if (offset + head >= header->data_offset + header->data_size)
277 goto done;
278
279 if (offset + head < (unsigned long)input_stat.st_size)
280 goto more;
281
282done:
283 err = 0;
284out_close:
285 close(input);
286
287 return err;
288out_delete:
289 perf_header__delete(header);
290 goto out_close;
291}
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
new file mode 100644
index 000000000000..3180ff7e3633
--- /dev/null
+++ b/tools/perf/util/data_map.h
@@ -0,0 +1,32 @@
1#ifndef __PERF_DATAMAP_H
2#define __PERF_DATAMAP_H
3
4#include "event.h"
5#include "header.h"
6
7typedef int (*event_type_handler_t)(event_t *);
8
9struct perf_file_handler {
10 event_type_handler_t process_sample_event;
11 event_type_handler_t process_mmap_event;
12 event_type_handler_t process_comm_event;
13 event_type_handler_t process_fork_event;
14 event_type_handler_t process_exit_event;
15 event_type_handler_t process_lost_event;
16 event_type_handler_t process_read_event;
17 event_type_handler_t process_throttle_event;
18 event_type_handler_t process_unthrottle_event;
19 int (*sample_type_check)(u64 sample_type);
20 unsigned long total_unknown;
21};
22
23void register_perf_file_handler(struct perf_file_handler *handler);
24int mmap_dispatch_perf_file(struct perf_header **pheader,
25 const char *input_name,
26 int force,
27 int full_paths,
28 int *cwdlen,
29 char **cwd);
30int perf_header__read_build_ids(int input, off_t offset, off_t file_size);
31
32#endif
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index e8ca98fe0bd4..28d520d5a1fb 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,12 +13,12 @@
13int verbose = 0; 13int verbose = 0;
14int dump_trace = 0; 14int dump_trace = 0;
15 15
16int eprintf(const char *fmt, ...) 16int eprintf(int level, const char *fmt, ...)
17{ 17{
18 va_list args; 18 va_list args;
19 int ret = 0; 19 int ret = 0;
20 20
21 if (verbose) { 21 if (verbose >= level) {
22 va_start(args, fmt); 22 va_start(args, fmt);
23 ret = vfprintf(stderr, fmt, args); 23 ret = vfprintf(stderr, fmt, args);
24 va_end(args); 24 va_end(args);
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 437eea58ce40..c6c24c522dea 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -1,8 +1,15 @@
1/* For debugging general purposes */ 1/* For debugging general purposes */
2#ifndef __PERF_DEBUG_H
3#define __PERF_DEBUG_H
4
5#include "event.h"
2 6
3extern int verbose; 7extern int verbose;
4extern int dump_trace; 8extern int dump_trace;
5 9
6int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 10int eprintf(int level,
11 const char *fmt, ...) __attribute__((format(printf, 2, 3)));
7int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 12int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
8void trace_event(event_t *event); 13void trace_event(event_t *event);
14
15#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
new file mode 100644
index 000000000000..06b73ee02c49
--- /dev/null
+++ b/tools/perf/util/debugfs.c
@@ -0,0 +1,241 @@
1#include "util.h"
2#include "debugfs.h"
3#include "cache.h"
4
5static int debugfs_premounted;
6static char debugfs_mountpoint[MAX_PATH+1];
7
8static const char *debugfs_known_mountpoints[] = {
9 "/sys/kernel/debug/",
10 "/debug/",
11 0,
12};
13
14/* use this to force a umount */
15void debugfs_force_cleanup(void)
16{
17 debugfs_find_mountpoint();
18 debugfs_premounted = 0;
19 debugfs_umount();
20}
21
22/* construct a full path to a debugfs element */
23int debugfs_make_path(const char *element, char *buffer, int size)
24{
25 int len;
26
27 if (strlen(debugfs_mountpoint) == 0) {
28 buffer[0] = '\0';
29 return -1;
30 }
31
32 len = strlen(debugfs_mountpoint) + strlen(element) + 1;
33 if (len >= size)
34 return len+1;
35
36 snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
37 return 0;
38}
39
40static int debugfs_found;
41
42/* find the path to the mounted debugfs */
43const char *debugfs_find_mountpoint(void)
44{
45 const char **ptr;
46 char type[100];
47 FILE *fp;
48
49 if (debugfs_found)
50 return (const char *) debugfs_mountpoint;
51
52 ptr = debugfs_known_mountpoints;
53 while (*ptr) {
54 if (debugfs_valid_mountpoint(*ptr) == 0) {
55 debugfs_found = 1;
56 strcpy(debugfs_mountpoint, *ptr);
57 return debugfs_mountpoint;
58 }
59 ptr++;
60 }
61
62 /* give up and parse /proc/mounts */
63 fp = fopen("/proc/mounts", "r");
64 if (fp == NULL)
65 die("Can't open /proc/mounts for read");
66
67 while (fscanf(fp, "%*s %"
68 STR(MAX_PATH)
69 "s %99s %*s %*d %*d\n",
70 debugfs_mountpoint, type) == 2) {
71 if (strcmp(type, "debugfs") == 0)
72 break;
73 }
74 fclose(fp);
75
76 if (strcmp(type, "debugfs") != 0)
77 return NULL;
78
79 debugfs_found = 1;
80
81 return debugfs_mountpoint;
82}
83
84/* verify that a mountpoint is actually a debugfs instance */
85
86int debugfs_valid_mountpoint(const char *debugfs)
87{
88 struct statfs st_fs;
89
90 if (statfs(debugfs, &st_fs) < 0)
91 return -ENOENT;
92 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
93 return -ENOENT;
94
95 return 0;
96}
97
98
99int debugfs_valid_entry(const char *path)
100{
101 struct stat st;
102
103 if (stat(path, &st))
104 return -errno;
105
106 return 0;
107}
108
109/* mount the debugfs somewhere */
110
111int debugfs_mount(const char *mountpoint)
112{
113 char mountcmd[128];
114
115 /* see if it's already mounted */
116 if (debugfs_find_mountpoint()) {
117 debugfs_premounted = 1;
118 return 0;
119 }
120
121 /* if not mounted and no argument */
122 if (mountpoint == NULL) {
123 /* see if environment variable set */
124 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
125 /* if no environment variable, use default */
126 if (mountpoint == NULL)
127 mountpoint = "/sys/kernel/debug";
128 }
129
130 /* save the mountpoint */
131 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
132
133 /* mount it */
134 snprintf(mountcmd, sizeof(mountcmd),
135 "/bin/mount -t debugfs debugfs %s", mountpoint);
136 return system(mountcmd);
137}
138
139/* umount the debugfs */
140
141int debugfs_umount(void)
142{
143 char umountcmd[128];
144 int ret;
145
146 /* if it was already mounted, leave it */
147 if (debugfs_premounted)
148 return 0;
149
150 /* make sure it's a valid mount point */
151 ret = debugfs_valid_mountpoint(debugfs_mountpoint);
152 if (ret)
153 return ret;
154
155 snprintf(umountcmd, sizeof(umountcmd),
156 "/bin/umount %s", debugfs_mountpoint);
157 return system(umountcmd);
158}
159
160int debugfs_write(const char *entry, const char *value)
161{
162 char path[MAX_PATH+1];
163 int ret, count;
164 int fd;
165
166 /* construct the path */
167 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
168
169 /* verify that it exists */
170 ret = debugfs_valid_entry(path);
171 if (ret)
172 return ret;
173
174 /* get how many chars we're going to write */
175 count = strlen(value);
176
177 /* open the debugfs entry */
178 fd = open(path, O_RDWR);
179 if (fd < 0)
180 return -errno;
181
182 while (count > 0) {
183 /* write it */
184 ret = write(fd, value, count);
185 if (ret <= 0) {
186 if (ret == EAGAIN)
187 continue;
188 close(fd);
189 return -errno;
190 }
191 count -= ret;
192 }
193
194 /* close it */
195 close(fd);
196
197 /* return success */
198 return 0;
199}
200
201/*
202 * read a debugfs entry
203 * returns the number of chars read or a negative errno
204 */
205int debugfs_read(const char *entry, char *buffer, size_t size)
206{
207 char path[MAX_PATH+1];
208 int ret;
209 int fd;
210
211 /* construct the path */
212 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
213
214 /* verify that it exists */
215 ret = debugfs_valid_entry(path);
216 if (ret)
217 return ret;
218
219 /* open the debugfs entry */
220 fd = open(path, O_RDONLY);
221 if (fd < 0)
222 return -errno;
223
224 do {
225 /* read it */
226 ret = read(fd, buffer, size);
227 if (ret == 0) {
228 close(fd);
229 return EOF;
230 }
231 } while (ret < 0 && errno == EAGAIN);
232
233 /* close it */
234 close(fd);
235
236 /* make *sure* there's a null character at the end */
237 buffer[ret] = '\0';
238
239 /* return the number of chars read */
240 return ret;
241}
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
new file mode 100644
index 000000000000..3cd14f9ae784
--- /dev/null
+++ b/tools/perf/util/debugfs.h
@@ -0,0 +1,25 @@
1#ifndef __DEBUGFS_H__
2#define __DEBUGFS_H__
3
4#include <sys/mount.h>
5
6#ifndef MAX_PATH
7# define MAX_PATH 256
8#endif
9
10#ifndef STR
11# define _STR(x) #x
12# define STR(x) _STR(x)
13#endif
14
15extern const char *debugfs_find_mountpoint(void);
16extern int debugfs_valid_mountpoint(const char *debugfs);
17extern int debugfs_valid_entry(const char *path);
18extern int debugfs_mount(const char *mountpoint);
19extern int debugfs_umount(void);
20extern int debugfs_write(const char *entry, const char *value);
21extern int debugfs_read(const char *entry, char *buffer, size_t size);
22extern void debugfs_force_cleanup(void);
23extern int debugfs_make_path(const char *element, char *buffer, int size);
24
25#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
new file mode 100644
index 000000000000..414b89d1bde9
--- /dev/null
+++ b/tools/perf/util/event.c
@@ -0,0 +1,312 @@
1#include <linux/types.h>
2#include "event.h"
3#include "debug.h"
4#include "string.h"
5#include "thread.h"
6
7static pid_t event__synthesize_comm(pid_t pid, int full,
8 int (*process)(event_t *event))
9{
10 event_t ev;
11 char filename[PATH_MAX];
12 char bf[BUFSIZ];
13 FILE *fp;
14 size_t size = 0;
15 DIR *tasks;
16 struct dirent dirent, *next;
17 pid_t tgid = 0;
18
19 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
20
21 fp = fopen(filename, "r");
22 if (fp == NULL) {
23out_race:
24 /*
25 * We raced with a task exiting - just return:
26 */
27 pr_debug("couldn't open %s\n", filename);
28 return 0;
29 }
30
31 memset(&ev.comm, 0, sizeof(ev.comm));
32 while (!ev.comm.comm[0] || !ev.comm.pid) {
33 if (fgets(bf, sizeof(bf), fp) == NULL)
34 goto out_failure;
35
36 if (memcmp(bf, "Name:", 5) == 0) {
37 char *name = bf + 5;
38 while (*name && isspace(*name))
39 ++name;
40 size = strlen(name) - 1;
41 memcpy(ev.comm.comm, name, size++);
42 } else if (memcmp(bf, "Tgid:", 5) == 0) {
43 char *tgids = bf + 5;
44 while (*tgids && isspace(*tgids))
45 ++tgids;
46 tgid = ev.comm.pid = atoi(tgids);
47 }
48 }
49
50 ev.comm.header.type = PERF_RECORD_COMM;
51 size = ALIGN(size, sizeof(u64));
52 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size);
53
54 if (!full) {
55 ev.comm.tid = pid;
56
57 process(&ev);
58 goto out_fclose;
59 }
60
61 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
62
63 tasks = opendir(filename);
64 if (tasks == NULL)
65 goto out_race;
66
67 while (!readdir_r(tasks, &dirent, &next) && next) {
68 char *end;
69 pid = strtol(dirent.d_name, &end, 10);
70 if (*end)
71 continue;
72
73 ev.comm.tid = pid;
74
75 process(&ev);
76 }
77 closedir(tasks);
78
79out_fclose:
80 fclose(fp);
81 return tgid;
82
83out_failure:
84 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
85 return -1;
86}
87
88static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
89 int (*process)(event_t *event))
90{
91 char filename[PATH_MAX];
92 FILE *fp;
93
94 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
95
96 fp = fopen(filename, "r");
97 if (fp == NULL) {
98 /*
99 * We raced with a task exiting - just return:
100 */
101 pr_debug("couldn't open %s\n", filename);
102 return -1;
103 }
104
105 while (1) {
106 char bf[BUFSIZ], *pbf = bf;
107 event_t ev = {
108 .header = { .type = PERF_RECORD_MMAP },
109 };
110 int n;
111 size_t size;
112 if (fgets(bf, sizeof(bf), fp) == NULL)
113 break;
114
115 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
116 n = hex2u64(pbf, &ev.mmap.start);
117 if (n < 0)
118 continue;
119 pbf += n + 1;
120 n = hex2u64(pbf, &ev.mmap.len);
121 if (n < 0)
122 continue;
123 pbf += n + 3;
124 if (*pbf == 'x') { /* vm_exec */
125 char *execname = strchr(bf, '/');
126
127 /* Catch VDSO */
128 if (execname == NULL)
129 execname = strstr(bf, "[vdso]");
130
131 if (execname == NULL)
132 continue;
133
134 size = strlen(execname);
135 execname[size - 1] = '\0'; /* Remove \n */
136 memcpy(ev.mmap.filename, execname, size);
137 size = ALIGN(size, sizeof(u64));
138 ev.mmap.len -= ev.mmap.start;
139 ev.mmap.header.size = (sizeof(ev.mmap) -
140 (sizeof(ev.mmap.filename) - size));
141 ev.mmap.pid = tgid;
142 ev.mmap.tid = pid;
143
144 process(&ev);
145 }
146 }
147
148 fclose(fp);
149 return 0;
150}
151
152int event__synthesize_thread(pid_t pid, int (*process)(event_t *event))
153{
154 pid_t tgid = event__synthesize_comm(pid, 1, process);
155 if (tgid == -1)
156 return -1;
157 return event__synthesize_mmap_events(pid, tgid, process);
158}
159
160void event__synthesize_threads(int (*process)(event_t *event))
161{
162 DIR *proc;
163 struct dirent dirent, *next;
164
165 proc = opendir("/proc");
166
167 while (!readdir_r(proc, &dirent, &next) && next) {
168 char *end;
169 pid_t pid = strtol(dirent.d_name, &end, 10);
170
171 if (*end) /* only interested in proper numerical dirents */
172 continue;
173
174 event__synthesize_thread(pid, process);
175 }
176
177 closedir(proc);
178}
179
180char *event__cwd;
181int event__cwdlen;
182
183struct events_stats event__stats;
184
185int event__process_comm(event_t *self)
186{
187 struct thread *thread = threads__findnew(self->comm.pid);
188
189 dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid);
190
191 if (thread == NULL || thread__set_comm(thread, self->comm.comm)) {
192 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
193 return -1;
194 }
195
196 return 0;
197}
198
199int event__process_lost(event_t *self)
200{
201 dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
202 event__stats.lost += self->lost.lost;
203 return 0;
204}
205
206int event__process_mmap(event_t *self)
207{
208 struct thread *thread = threads__findnew(self->mmap.pid);
209 struct map *map = map__new(&self->mmap, MAP__FUNCTION,
210 event__cwd, event__cwdlen);
211
212 dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n",
213 self->mmap.pid, self->mmap.tid,
214 (void *)(long)self->mmap.start,
215 (void *)(long)self->mmap.len,
216 (void *)(long)self->mmap.pgoff,
217 self->mmap.filename);
218
219 if (thread == NULL || map == NULL)
220 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
221 else
222 thread__insert_map(thread, map);
223
224 return 0;
225}
226
227int event__process_task(event_t *self)
228{
229 struct thread *thread = threads__findnew(self->fork.pid);
230 struct thread *parent = threads__findnew(self->fork.ppid);
231
232 dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
233 self->fork.ppid, self->fork.ptid);
234 /*
235 * A thread clone will have the same PID for both parent and child.
236 */
237 if (thread == parent)
238 return 0;
239
240 if (self->header.type == PERF_RECORD_EXIT)
241 return 0;
242
243 if (thread == NULL || parent == NULL ||
244 thread__fork(thread, parent) < 0) {
245 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
246 return -1;
247 }
248
249 return 0;
250}
251
252void thread__find_addr_location(struct thread *self, u8 cpumode,
253 enum map_type type, u64 addr,
254 struct addr_location *al,
255 symbol_filter_t filter)
256{
257 struct thread *thread = al->thread = self;
258
259 al->addr = addr;
260
261 if (cpumode & PERF_RECORD_MISC_KERNEL) {
262 al->level = 'k';
263 thread = kthread;
264 } else if (cpumode & PERF_RECORD_MISC_USER)
265 al->level = '.';
266 else {
267 al->level = 'H';
268 al->map = NULL;
269 al->sym = NULL;
270 return;
271 }
272try_again:
273 al->map = thread__find_map(thread, type, al->addr);
274 if (al->map == NULL) {
275 /*
276 * If this is outside of all known maps, and is a negative
277 * address, try to look it up in the kernel dso, as it might be
278 * a vsyscall or vdso (which executes in user-mode).
279 *
280 * XXX This is nasty, we should have a symbol list in the
281 * "[vdso]" dso, but for now lets use the old trick of looking
282 * in the whole kernel symbol list.
283 */
284 if ((long long)al->addr < 0 && thread != kthread) {
285 thread = kthread;
286 goto try_again;
287 }
288 al->sym = NULL;
289 } else {
290 al->addr = al->map->map_ip(al->map, al->addr);
291 al->sym = map__find_symbol(al->map, al->addr, filter);
292 }
293}
294
295int event__preprocess_sample(const event_t *self, struct addr_location *al,
296 symbol_filter_t filter)
297{
298 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
299 struct thread *thread = threads__findnew(self->ip.pid);
300
301 if (thread == NULL)
302 return -1;
303
304 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
305
306 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
307 self->ip.ip, al, filter);
308 dump_printf(" ...... dso: %s\n",
309 al->map ? al->map->dso->long_name :
310 al->level == 'H' ? "[hypervisor]" : "<not found>");
311 return 0;
312}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 2c9c26d6ded0..a4cc8105cf67 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,14 +1,10 @@
1#ifndef __PERF_RECORD_H 1#ifndef __PERF_RECORD_H
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3
3#include "../perf.h" 4#include "../perf.h"
4#include "util.h" 5#include "util.h"
5#include <linux/list.h> 6#include <linux/list.h>
6 7#include <linux/rbtree.h>
7enum {
8 SHOW_KERNEL = 1,
9 SHOW_USER = 2,
10 SHOW_HV = 4,
11};
12 8
13/* 9/*
14 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * 10 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
@@ -65,6 +61,13 @@ struct sample_event{
65 u64 array[]; 61 u64 array[];
66}; 62};
67 63
64#define BUILD_ID_SIZE 20
65
66struct build_id_event {
67 struct perf_event_header header;
68 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
69 char filename[];
70};
68 71
69typedef union event_union { 72typedef union event_union {
70 struct perf_event_header header; 73 struct perf_event_header header;
@@ -77,12 +80,30 @@ typedef union event_union {
77 struct sample_event sample; 80 struct sample_event sample;
78} event_t; 81} event_t;
79 82
83struct events_stats {
84 unsigned long total;
85 unsigned long lost;
86};
87
88void event__print_totals(void);
89
90enum map_type {
91 MAP__FUNCTION = 0,
92
93 MAP__NR_TYPES,
94};
95
80struct map { 96struct map {
81 struct list_head node; 97 union {
98 struct rb_node rb_node;
99 struct list_head node;
100 };
82 u64 start; 101 u64 start;
83 u64 end; 102 u64 end;
103 enum map_type type;
84 u64 pgoff; 104 u64 pgoff;
85 u64 (*map_ip)(struct map *, u64); 105 u64 (*map_ip)(struct map *, u64);
106 u64 (*unmap_ip)(struct map *, u64);
86 struct dso *dso; 107 struct dso *dso;
87}; 108};
88 109
@@ -91,14 +112,48 @@ static inline u64 map__map_ip(struct map *map, u64 ip)
91 return ip - map->start + map->pgoff; 112 return ip - map->start + map->pgoff;
92} 113}
93 114
94static inline u64 vdso__map_ip(struct map *map __used, u64 ip) 115static inline u64 map__unmap_ip(struct map *map, u64 ip)
116{
117 return ip + map->start - map->pgoff;
118}
119
120static inline u64 identity__map_ip(struct map *map __used, u64 ip)
95{ 121{
96 return ip; 122 return ip;
97} 123}
98 124
99struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); 125struct symbol;
126
127typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
128
129void map__init(struct map *self, enum map_type type,
130 u64 start, u64 end, u64 pgoff, struct dso *dso);
131struct map *map__new(struct mmap_event *event, enum map_type,
132 char *cwd, int cwdlen);
133void map__delete(struct map *self);
100struct map *map__clone(struct map *self); 134struct map *map__clone(struct map *self);
101int map__overlap(struct map *l, struct map *r); 135int map__overlap(struct map *l, struct map *r);
102size_t map__fprintf(struct map *self, FILE *fp); 136size_t map__fprintf(struct map *self, FILE *fp);
137struct symbol *map__find_symbol(struct map *self, u64 addr,
138 symbol_filter_t filter);
139void map__fixup_start(struct map *self);
140void map__fixup_end(struct map *self);
141
142int event__synthesize_thread(pid_t pid, int (*process)(event_t *event));
143void event__synthesize_threads(int (*process)(event_t *event));
144
145extern char *event__cwd;
146extern int event__cwdlen;
147extern struct events_stats event__stats;
148extern unsigned long event__total[PERF_RECORD_MAX];
149
150int event__process_comm(event_t *self);
151int event__process_lost(event_t *self);
152int event__process_mmap(event_t *self);
153int event__process_task(event_t *self);
154
155struct addr_location;
156int event__preprocess_sample(const event_t *self, struct addr_location *al,
157 symbol_filter_t filter);
103 158
104#endif 159#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index effe25eb1545..31647ac92ed1 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -1,5 +1,5 @@
1#ifndef PERF_EXEC_CMD_H 1#ifndef __PERF_EXEC_CMD_H
2#define PERF_EXEC_CMD_H 2#define __PERF_EXEC_CMD_H
3 3
4extern void perf_set_argv_exec_path(const char *exec_path); 4extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path); 5extern const char *perf_extract_argv0_path(const char *path);
@@ -10,4 +10,4 @@ extern int execv_perf_cmd(const char **argv); /* NULL terminated */
10extern int execl_perf_cmd(const char *cmd, ...); 10extern int execl_perf_cmd(const char *cmd, ...);
11extern const char *system_path(const char *path); 11extern const char *system_path(const char *path);
12 12
13#endif /* PERF_EXEC_CMD_H */ 13#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e306857b2c2b..4805e6dfd23c 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2,9 +2,15 @@
2#include <unistd.h> 2#include <unistd.h>
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5#include <linux/list.h>
5 6
6#include "util.h" 7#include "util.h"
7#include "header.h" 8#include "header.h"
9#include "../perf.h"
10#include "trace-event.h"
11#include "symbol.h"
12#include "data_map.h"
13#include "debug.h"
8 14
9/* 15/*
10 * Create new perf.data header attribute: 16 * Create new perf.data header attribute:
@@ -13,32 +19,43 @@ struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr)
13{ 19{
14 struct perf_header_attr *self = malloc(sizeof(*self)); 20 struct perf_header_attr *self = malloc(sizeof(*self));
15 21
16 if (!self) 22 if (self != NULL) {
17 die("nomem"); 23 self->attr = *attr;
18 24 self->ids = 0;
19 self->attr = *attr; 25 self->size = 1;
20 self->ids = 0; 26 self->id = malloc(sizeof(u64));
21 self->size = 1; 27 if (self->id == NULL) {
22 self->id = malloc(sizeof(u64)); 28 free(self);
23 29 self = NULL;
24 if (!self->id) 30 }
25 die("nomem"); 31 }
26 32
27 return self; 33 return self;
28} 34}
29 35
30void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) 36void perf_header_attr__delete(struct perf_header_attr *self)
37{
38 free(self->id);
39 free(self);
40}
41
42int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
31{ 43{
32 int pos = self->ids; 44 int pos = self->ids;
33 45
34 self->ids++; 46 self->ids++;
35 if (self->ids > self->size) { 47 if (self->ids > self->size) {
36 self->size *= 2; 48 int nsize = self->size * 2;
37 self->id = realloc(self->id, self->size * sizeof(u64)); 49 u64 *nid = realloc(self->id, nsize * sizeof(u64));
38 if (!self->id) 50
39 die("nomem"); 51 if (nid == NULL)
52 return -1;
53
54 self->size = nsize;
55 self->id = nid;
40 } 56 }
41 self->id[pos] = id; 57 self->id[pos] = id;
58 return 0;
42} 59}
43 60
44/* 61/*
@@ -46,42 +63,52 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
46 */ 63 */
47struct perf_header *perf_header__new(void) 64struct perf_header *perf_header__new(void)
48{ 65{
49 struct perf_header *self = malloc(sizeof(*self)); 66 struct perf_header *self = zalloc(sizeof(*self));
50 67
51 if (!self) 68 if (self != NULL) {
52 die("nomem"); 69 self->size = 1;
70 self->attr = malloc(sizeof(void *));
53 71
54 self->frozen = 0; 72 if (self->attr == NULL) {
73 free(self);
74 self = NULL;
75 }
76 }
55 77
56 self->attrs = 0; 78 return self;
57 self->size = 1; 79}
58 self->attr = malloc(sizeof(void *));
59 80
60 if (!self->attr) 81void perf_header__delete(struct perf_header *self)
61 die("nomem"); 82{
83 int i;
62 84
63 self->data_offset = 0; 85 for (i = 0; i < self->attrs; ++i)
64 self->data_size = 0; 86 perf_header_attr__delete(self->attr[i]);
65 87
66 return self; 88 free(self->attr);
89 free(self);
67} 90}
68 91
69void perf_header__add_attr(struct perf_header *self, 92int perf_header__add_attr(struct perf_header *self,
70 struct perf_header_attr *attr) 93 struct perf_header_attr *attr)
71{ 94{
72 int pos = self->attrs;
73
74 if (self->frozen) 95 if (self->frozen)
75 die("frozen"); 96 return -1;
76 97
77 self->attrs++; 98 if (self->attrs == self->size) {
78 if (self->attrs > self->size) { 99 int nsize = self->size * 2;
79 self->size *= 2; 100 struct perf_header_attr **nattr;
80 self->attr = realloc(self->attr, self->size * sizeof(void *)); 101
81 if (!self->attr) 102 nattr = realloc(self->attr, nsize * sizeof(void *));
82 die("nomem"); 103 if (nattr == NULL)
104 return -1;
105
106 self->size = nsize;
107 self->attr = nattr;
83 } 108 }
84 self->attr[pos] = attr; 109
110 self->attr[self->attrs++] = attr;
111 return 0;
85} 112}
86 113
87#define MAX_EVENT_NAME 64 114#define MAX_EVENT_NAME 64
@@ -97,7 +124,7 @@ static struct perf_trace_event_type *events;
97void perf_header__push_event(u64 id, const char *name) 124void perf_header__push_event(u64 id, const char *name)
98{ 125{
99 if (strlen(name) > MAX_EVENT_NAME) 126 if (strlen(name) > MAX_EVENT_NAME)
100 printf("Event %s will be truncated\n", name); 127 pr_warning("Event %s will be truncated\n", name);
101 128
102 if (!events) { 129 if (!events) {
103 events = malloc(sizeof(struct perf_trace_event_type)); 130 events = malloc(sizeof(struct perf_trace_event_type));
@@ -128,44 +155,137 @@ static const char *__perf_magic = "PERFFILE";
128 155
129#define PERF_MAGIC (*(u64 *)__perf_magic) 156#define PERF_MAGIC (*(u64 *)__perf_magic)
130 157
131struct perf_file_section {
132 u64 offset;
133 u64 size;
134};
135
136struct perf_file_attr { 158struct perf_file_attr {
137 struct perf_event_attr attr; 159 struct perf_event_attr attr;
138 struct perf_file_section ids; 160 struct perf_file_section ids;
139}; 161};
140 162
141struct perf_file_header { 163void perf_header__set_feat(struct perf_header *self, int feat)
142 u64 magic; 164{
143 u64 size; 165 set_bit(feat, self->adds_features);
144 u64 attr_size; 166}
145 struct perf_file_section attrs;
146 struct perf_file_section data;
147 struct perf_file_section event_types;
148};
149 167
150static void do_write(int fd, void *buf, size_t size) 168bool perf_header__has_feat(const struct perf_header *self, int feat)
169{
170 return test_bit(feat, self->adds_features);
171}
172
173static int do_write(int fd, const void *buf, size_t size)
151{ 174{
152 while (size) { 175 while (size) {
153 int ret = write(fd, buf, size); 176 int ret = write(fd, buf, size);
154 177
155 if (ret < 0) 178 if (ret < 0)
156 die("failed to write"); 179 return -errno;
157 180
158 size -= ret; 181 size -= ret;
159 buf += ret; 182 buf += ret;
160 } 183 }
184
185 return 0;
186}
187
188static int __dsos__write_buildid_table(struct list_head *head, int fd)
189{
190 struct dso *pos;
191
192 list_for_each_entry(pos, head, node) {
193 int err;
194 struct build_id_event b;
195 size_t len;
196
197 if (!pos->has_build_id)
198 continue;
199 len = pos->long_name_len + 1;
200 len = ALIGN(len, 64);
201 memset(&b, 0, sizeof(b));
202 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
203 b.header.size = sizeof(b) + len;
204 err = do_write(fd, &b, sizeof(b));
205 if (err < 0)
206 return err;
207 err = do_write(fd, pos->long_name, len);
208 if (err < 0)
209 return err;
210 }
211
212 return 0;
161} 213}
162 214
163void perf_header__write(struct perf_header *self, int fd) 215static int dsos__write_buildid_table(int fd)
216{
217 int err = __dsos__write_buildid_table(&dsos__kernel, fd);
218 if (err == 0)
219 err = __dsos__write_buildid_table(&dsos__user, fd);
220 return err;
221}
222
223static int perf_header__adds_write(struct perf_header *self, int fd)
224{
225 int nr_sections;
226 struct perf_file_section *feat_sec;
227 int sec_size;
228 u64 sec_start;
229 int idx = 0, err;
230
231 if (dsos__read_build_ids())
232 perf_header__set_feat(self, HEADER_BUILD_ID);
233
234 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
235 if (!nr_sections)
236 return 0;
237
238 feat_sec = calloc(sizeof(*feat_sec), nr_sections);
239 if (feat_sec == NULL)
240 return -ENOMEM;
241
242 sec_size = sizeof(*feat_sec) * nr_sections;
243
244 sec_start = self->data_offset + self->data_size;
245 lseek(fd, sec_start + sec_size, SEEK_SET);
246
247 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
248 struct perf_file_section *trace_sec;
249
250 trace_sec = &feat_sec[idx++];
251
252 /* Write trace info */
253 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
254 read_tracing_data(fd, attrs, nr_counters);
255 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
256 }
257
258
259 if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
260 struct perf_file_section *buildid_sec;
261
262 buildid_sec = &feat_sec[idx++];
263
264 /* Write build-ids */
265 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
266 err = dsos__write_buildid_table(fd);
267 if (err < 0) {
268 pr_debug("failed to write buildid table\n");
269 goto out_free;
270 }
271 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset;
272 }
273
274 lseek(fd, sec_start, SEEK_SET);
275 err = do_write(fd, feat_sec, sec_size);
276 if (err < 0)
277 pr_debug("failed to write feature section\n");
278out_free:
279 free(feat_sec);
280 return err;
281}
282
283int perf_header__write(struct perf_header *self, int fd, bool at_exit)
164{ 284{
165 struct perf_file_header f_header; 285 struct perf_file_header f_header;
166 struct perf_file_attr f_attr; 286 struct perf_file_attr f_attr;
167 struct perf_header_attr *attr; 287 struct perf_header_attr *attr;
168 int i; 288 int i, err;
169 289
170 lseek(fd, sizeof(f_header), SEEK_SET); 290 lseek(fd, sizeof(f_header), SEEK_SET);
171 291
@@ -174,7 +294,11 @@ void perf_header__write(struct perf_header *self, int fd)
174 attr = self->attr[i]; 294 attr = self->attr[i];
175 295
176 attr->id_offset = lseek(fd, 0, SEEK_CUR); 296 attr->id_offset = lseek(fd, 0, SEEK_CUR);
177 do_write(fd, attr->id, attr->ids * sizeof(u64)); 297 err = do_write(fd, attr->id, attr->ids * sizeof(u64));
298 if (err < 0) {
299 pr_debug("failed to write perf header\n");
300 return err;
301 }
178 } 302 }
179 303
180 304
@@ -190,17 +314,31 @@ void perf_header__write(struct perf_header *self, int fd)
190 .size = attr->ids * sizeof(u64), 314 .size = attr->ids * sizeof(u64),
191 } 315 }
192 }; 316 };
193 do_write(fd, &f_attr, sizeof(f_attr)); 317 err = do_write(fd, &f_attr, sizeof(f_attr));
318 if (err < 0) {
319 pr_debug("failed to write perf header attribute\n");
320 return err;
321 }
194 } 322 }
195 323
196 self->event_offset = lseek(fd, 0, SEEK_CUR); 324 self->event_offset = lseek(fd, 0, SEEK_CUR);
197 self->event_size = event_count * sizeof(struct perf_trace_event_type); 325 self->event_size = event_count * sizeof(struct perf_trace_event_type);
198 if (events) 326 if (events) {
199 do_write(fd, events, self->event_size); 327 err = do_write(fd, events, self->event_size);
200 328 if (err < 0) {
329 pr_debug("failed to write perf header events\n");
330 return err;
331 }
332 }
201 333
202 self->data_offset = lseek(fd, 0, SEEK_CUR); 334 self->data_offset = lseek(fd, 0, SEEK_CUR);
203 335
336 if (at_exit) {
337 err = perf_header__adds_write(self, fd);
338 if (err < 0)
339 return err;
340 }
341
204 f_header = (struct perf_file_header){ 342 f_header = (struct perf_file_header){
205 .magic = PERF_MAGIC, 343 .magic = PERF_MAGIC,
206 .size = sizeof(f_header), 344 .size = sizeof(f_header),
@@ -219,11 +357,18 @@ void perf_header__write(struct perf_header *self, int fd)
219 }, 357 },
220 }; 358 };
221 359
360 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
361
222 lseek(fd, 0, SEEK_SET); 362 lseek(fd, 0, SEEK_SET);
223 do_write(fd, &f_header, sizeof(f_header)); 363 err = do_write(fd, &f_header, sizeof(f_header));
364 if (err < 0) {
365 pr_debug("failed to write perf header\n");
366 return err;
367 }
224 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 368 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
225 369
226 self->frozen = 1; 370 self->frozen = 1;
371 return 0;
227} 372}
228 373
229static void do_read(int fd, void *buf, size_t size) 374static void do_read(int fd, void *buf, size_t size)
@@ -241,22 +386,109 @@ static void do_read(int fd, void *buf, size_t size)
241 } 386 }
242} 387}
243 388
244struct perf_header *perf_header__read(int fd) 389int perf_header__process_sections(struct perf_header *self, int fd,
390 int (*process)(struct perf_file_section *self,
391 int feat, int fd))
392{
393 struct perf_file_section *feat_sec;
394 int nr_sections;
395 int sec_size;
396 int idx = 0;
397 int err = 0, feat = 1;
398
399 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
400 if (!nr_sections)
401 return 0;
402
403 feat_sec = calloc(sizeof(*feat_sec), nr_sections);
404 if (!feat_sec)
405 return -1;
406
407 sec_size = sizeof(*feat_sec) * nr_sections;
408
409 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
410
411 do_read(fd, feat_sec, sec_size);
412
413 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
414 if (perf_header__has_feat(self, feat)) {
415 struct perf_file_section *sec = &feat_sec[idx++];
416
417 err = process(sec, feat, fd);
418 if (err < 0)
419 break;
420 }
421 ++feat;
422 }
423
424 free(feat_sec);
425 return err;
426};
427
428int perf_file_header__read(struct perf_file_header *self,
429 struct perf_header *ph, int fd)
430{
431 lseek(fd, 0, SEEK_SET);
432 do_read(fd, self, sizeof(*self));
433
434 if (self->magic != PERF_MAGIC ||
435 self->attr_size != sizeof(struct perf_file_attr))
436 return -1;
437
438 if (self->size != sizeof(*self)) {
439 /* Support the previous format */
440 if (self->size == offsetof(typeof(*self), adds_features))
441 bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
442 else
443 return -1;
444 }
445
446 memcpy(&ph->adds_features, &self->adds_features,
447 sizeof(self->adds_features));
448
449 ph->event_offset = self->event_types.offset;
450 ph->event_size = self->event_types.size;
451 ph->data_offset = self->data.offset;
452 ph->data_size = self->data.size;
453 return 0;
454}
455
456static int perf_file_section__process(struct perf_file_section *self,
457 int feat, int fd)
458{
459 if (lseek(fd, self->offset, SEEK_SET) < 0) {
460 pr_debug("Failed to lseek to %Ld offset for feature %d, "
461 "continuing...\n", self->offset, feat);
462 return 0;
463 }
464
465 switch (feat) {
466 case HEADER_TRACE_INFO:
467 trace_report(fd);
468 break;
469
470 case HEADER_BUILD_ID:
471 if (perf_header__read_build_ids(fd, self->offset, self->size))
472 pr_debug("Failed to read buildids, continuing...\n");
473 break;
474 default:
475 pr_debug("unknown feature %d, continuing...\n", feat);
476 }
477
478 return 0;
479}
480
481int perf_header__read(struct perf_header *self, int fd)
245{ 482{
246 struct perf_header *self = perf_header__new();
247 struct perf_file_header f_header; 483 struct perf_file_header f_header;
248 struct perf_file_attr f_attr; 484 struct perf_file_attr f_attr;
249 u64 f_id; 485 u64 f_id;
250
251 int nr_attrs, nr_ids, i, j; 486 int nr_attrs, nr_ids, i, j;
252 487
253 lseek(fd, 0, SEEK_SET); 488 if (perf_file_header__read(&f_header, self, fd) < 0) {
254 do_read(fd, &f_header, sizeof(f_header)); 489 pr_debug("incompatible file format\n");
255 490 return -EINVAL;
256 if (f_header.magic != PERF_MAGIC || 491 }
257 f_header.size != sizeof(f_header) ||
258 f_header.attr_size != sizeof(f_attr))
259 die("incompatible file format");
260 492
261 nr_attrs = f_header.attrs.size / sizeof(f_attr); 493 nr_attrs = f_header.attrs.size / sizeof(f_attr);
262 lseek(fd, f_header.attrs.offset, SEEK_SET); 494 lseek(fd, f_header.attrs.offset, SEEK_SET);
@@ -269,6 +501,8 @@ struct perf_header *perf_header__read(int fd)
269 tmp = lseek(fd, 0, SEEK_CUR); 501 tmp = lseek(fd, 0, SEEK_CUR);
270 502
271 attr = perf_header_attr__new(&f_attr.attr); 503 attr = perf_header_attr__new(&f_attr.attr);
504 if (attr == NULL)
505 return -ENOMEM;
272 506
273 nr_ids = f_attr.ids.size / sizeof(u64); 507 nr_ids = f_attr.ids.size / sizeof(u64);
274 lseek(fd, f_attr.ids.offset, SEEK_SET); 508 lseek(fd, f_attr.ids.offset, SEEK_SET);
@@ -276,31 +510,34 @@ struct perf_header *perf_header__read(int fd)
276 for (j = 0; j < nr_ids; j++) { 510 for (j = 0; j < nr_ids; j++) {
277 do_read(fd, &f_id, sizeof(f_id)); 511 do_read(fd, &f_id, sizeof(f_id));
278 512
279 perf_header_attr__add_id(attr, f_id); 513 if (perf_header_attr__add_id(attr, f_id) < 0) {
514 perf_header_attr__delete(attr);
515 return -ENOMEM;
516 }
280 } 517 }
281 perf_header__add_attr(self, attr); 518 if (perf_header__add_attr(self, attr) < 0) {
519 perf_header_attr__delete(attr);
520 return -ENOMEM;
521 }
522
282 lseek(fd, tmp, SEEK_SET); 523 lseek(fd, tmp, SEEK_SET);
283 } 524 }
284 525
285 if (f_header.event_types.size) { 526 if (f_header.event_types.size) {
286 lseek(fd, f_header.event_types.offset, SEEK_SET); 527 lseek(fd, f_header.event_types.offset, SEEK_SET);
287 events = malloc(f_header.event_types.size); 528 events = malloc(f_header.event_types.size);
288 if (!events) 529 if (events == NULL)
289 die("nomem"); 530 return -ENOMEM;
290 do_read(fd, events, f_header.event_types.size); 531 do_read(fd, events, f_header.event_types.size);
291 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 532 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
292 } 533 }
293 self->event_offset = f_header.event_types.offset;
294 self->event_size = f_header.event_types.size;
295 534
296 self->data_offset = f_header.data.offset; 535 perf_header__process_sections(self, fd, perf_file_section__process);
297 self->data_size = f_header.data.size;
298 536
299 lseek(fd, self->data_offset, SEEK_SET); 537 lseek(fd, self->data_offset, SEEK_SET);
300 538
301 self->frozen = 1; 539 self->frozen = 1;
302 540 return 0;
303 return self;
304} 541}
305 542
306u64 perf_header__sample_type(struct perf_header *header) 543u64 perf_header__sample_type(struct perf_header *header)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a0761bc7863c..d1dbe2b79c42 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,10 +1,13 @@
1#ifndef _PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define _PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include <stdbool.h>
6#include "types.h" 7#include "types.h"
7 8
9#include <linux/bitmap.h>
10
8struct perf_header_attr { 11struct perf_header_attr {
9 struct perf_event_attr attr; 12 struct perf_event_attr attr;
10 int ids, size; 13 int ids, size;
@@ -12,36 +15,71 @@ struct perf_header_attr {
12 off_t id_offset; 15 off_t id_offset;
13}; 16};
14 17
18enum {
19 HEADER_TRACE_INFO = 1,
20 HEADER_BUILD_ID,
21 HEADER_LAST_FEATURE,
22};
23
24#define HEADER_FEAT_BITS 256
25
26struct perf_file_section {
27 u64 offset;
28 u64 size;
29};
30
31struct perf_file_header {
32 u64 magic;
33 u64 size;
34 u64 attr_size;
35 struct perf_file_section attrs;
36 struct perf_file_section data;
37 struct perf_file_section event_types;
38 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
39};
40
41struct perf_header;
42
43int perf_file_header__read(struct perf_file_header *self,
44 struct perf_header *ph, int fd);
45
15struct perf_header { 46struct perf_header {
16 int frozen; 47 int frozen;
17 int attrs, size; 48 int attrs, size;
18 struct perf_header_attr **attr; 49 struct perf_header_attr **attr;
19 s64 attr_offset; 50 s64 attr_offset;
20 u64 data_offset; 51 u64 data_offset;
21 u64 data_size; 52 u64 data_size;
22 u64 event_offset; 53 u64 event_offset;
23 u64 event_size; 54 u64 event_size;
55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
24}; 56};
25 57
26struct perf_header *perf_header__read(int fd); 58struct perf_header *perf_header__new(void);
27void perf_header__write(struct perf_header *self, int fd); 59void perf_header__delete(struct perf_header *self);
28 60
29void perf_header__add_attr(struct perf_header *self, 61int perf_header__read(struct perf_header *self, int fd);
30 struct perf_header_attr *attr); 62int perf_header__write(struct perf_header *self, int fd, bool at_exit);
63
64int perf_header__add_attr(struct perf_header *self,
65 struct perf_header_attr *attr);
31 66
32void perf_header__push_event(u64 id, const char *name); 67void perf_header__push_event(u64 id, const char *name);
33char *perf_header__find_event(u64 id); 68char *perf_header__find_event(u64 id);
34 69
70struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr);
71void perf_header_attr__delete(struct perf_header_attr *self);
35 72
36struct perf_header_attr * 73int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
37perf_header_attr__new(struct perf_event_attr *attr);
38void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
39 74
40u64 perf_header__sample_type(struct perf_header *header); 75u64 perf_header__sample_type(struct perf_header *header);
41struct perf_event_attr * 76struct perf_event_attr *
42perf_header__find_attr(u64 id, struct perf_header *header); 77perf_header__find_attr(u64 id, struct perf_header *header);
78void perf_header__set_feat(struct perf_header *self, int feat);
79bool perf_header__has_feat(const struct perf_header *self, int feat);
43 80
81int perf_header__process_sections(struct perf_header *self, int fd,
82 int (*process)(struct perf_file_section *self,
83 int feat, int fd));
44 84
45struct perf_header *perf_header__new(void); 85#endif /* __PERF_HEADER_H */
46
47#endif /* _PERF_HEADER_H */
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 7128783637b4..7f5c6dedd714 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -1,5 +1,5 @@
1#ifndef HELP_H 1#ifndef __PERF_HELP_H
2#define HELP_H 2#define __PERF_HELP_H
3 3
4struct cmdnames { 4struct cmdnames {
5 size_t alloc; 5 size_t alloc;
@@ -26,4 +26,4 @@ int is_in_cmdlist(struct cmdnames *c, const char *s);
26void list_commands(const char *title, struct cmdnames *main_cmds, 26void list_commands(const char *title, struct cmdnames *main_cmds,
27 struct cmdnames *other_cmds); 27 struct cmdnames *other_cmds);
28 28
29#endif /* HELP_H */ 29#endif /* __PERF_HELP_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
new file mode 100644
index 000000000000..0ebf6ee16caa
--- /dev/null
+++ b/tools/perf/util/hist.c
@@ -0,0 +1,202 @@
1#include "hist.h"
2
3struct rb_root hist;
4struct rb_root collapse_hists;
5struct rb_root output_hists;
6int callchain;
7
8struct callchain_param callchain_param = {
9 .mode = CHAIN_GRAPH_REL,
10 .min_percent = 0.5
11};
12
13/*
14 * histogram, sorted on item, collects counts
15 */
16
17struct hist_entry *__hist_entry__add(struct addr_location *al,
18 struct symbol *sym_parent,
19 u64 count, bool *hit)
20{
21 struct rb_node **p = &hist.rb_node;
22 struct rb_node *parent = NULL;
23 struct hist_entry *he;
24 struct hist_entry entry = {
25 .thread = al->thread,
26 .map = al->map,
27 .sym = al->sym,
28 .ip = al->addr,
29 .level = al->level,
30 .count = count,
31 .parent = sym_parent,
32 };
33 int cmp;
34
35 while (*p != NULL) {
36 parent = *p;
37 he = rb_entry(parent, struct hist_entry, rb_node);
38
39 cmp = hist_entry__cmp(&entry, he);
40
41 if (!cmp) {
42 *hit = true;
43 return he;
44 }
45
46 if (cmp < 0)
47 p = &(*p)->rb_left;
48 else
49 p = &(*p)->rb_right;
50 }
51
52 he = malloc(sizeof(*he));
53 if (!he)
54 return NULL;
55 *he = entry;
56 rb_link_node(&he->rb_node, parent, p);
57 rb_insert_color(&he->rb_node, &hist);
58 *hit = false;
59 return he;
60}
61
62int64_t
63hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
64{
65 struct sort_entry *se;
66 int64_t cmp = 0;
67
68 list_for_each_entry(se, &hist_entry__sort_list, list) {
69 cmp = se->cmp(left, right);
70 if (cmp)
71 break;
72 }
73
74 return cmp;
75}
76
77int64_t
78hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
79{
80 struct sort_entry *se;
81 int64_t cmp = 0;
82
83 list_for_each_entry(se, &hist_entry__sort_list, list) {
84 int64_t (*f)(struct hist_entry *, struct hist_entry *);
85
86 f = se->collapse ?: se->cmp;
87
88 cmp = f(left, right);
89 if (cmp)
90 break;
91 }
92
93 return cmp;
94}
95
96void hist_entry__free(struct hist_entry *he)
97{
98 free(he);
99}
100
101/*
102 * collapse the histogram
103 */
104
105void collapse__insert_entry(struct hist_entry *he)
106{
107 struct rb_node **p = &collapse_hists.rb_node;
108 struct rb_node *parent = NULL;
109 struct hist_entry *iter;
110 int64_t cmp;
111
112 while (*p != NULL) {
113 parent = *p;
114 iter = rb_entry(parent, struct hist_entry, rb_node);
115
116 cmp = hist_entry__collapse(iter, he);
117
118 if (!cmp) {
119 iter->count += he->count;
120 hist_entry__free(he);
121 return;
122 }
123
124 if (cmp < 0)
125 p = &(*p)->rb_left;
126 else
127 p = &(*p)->rb_right;
128 }
129
130 rb_link_node(&he->rb_node, parent, p);
131 rb_insert_color(&he->rb_node, &collapse_hists);
132}
133
134void collapse__resort(void)
135{
136 struct rb_node *next;
137 struct hist_entry *n;
138
139 if (!sort__need_collapse)
140 return;
141
142 next = rb_first(&hist);
143 while (next) {
144 n = rb_entry(next, struct hist_entry, rb_node);
145 next = rb_next(&n->rb_node);
146
147 rb_erase(&n->rb_node, &hist);
148 collapse__insert_entry(n);
149 }
150}
151
152/*
153 * reverse the map, sort on count.
154 */
155
156void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
157{
158 struct rb_node **p = &output_hists.rb_node;
159 struct rb_node *parent = NULL;
160 struct hist_entry *iter;
161
162 if (callchain)
163 callchain_param.sort(&he->sorted_chain, &he->callchain,
164 min_callchain_hits, &callchain_param);
165
166 while (*p != NULL) {
167 parent = *p;
168 iter = rb_entry(parent, struct hist_entry, rb_node);
169
170 if (he->count > iter->count)
171 p = &(*p)->rb_left;
172 else
173 p = &(*p)->rb_right;
174 }
175
176 rb_link_node(&he->rb_node, parent, p);
177 rb_insert_color(&he->rb_node, &output_hists);
178}
179
180void output__resort(u64 total_samples)
181{
182 struct rb_node *next;
183 struct hist_entry *n;
184 struct rb_root *tree = &hist;
185 u64 min_callchain_hits;
186
187 min_callchain_hits =
188 total_samples * (callchain_param.min_percent / 100);
189
190 if (sort__need_collapse)
191 tree = &collapse_hists;
192
193 next = rb_first(tree);
194
195 while (next) {
196 n = rb_entry(next, struct hist_entry, rb_node);
197 next = rb_next(&n->rb_node);
198
199 rb_erase(&n->rb_node, tree);
200 output__insert_entry(n, min_callchain_hits);
201 }
202}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
new file mode 100644
index 000000000000..3020db0c9292
--- /dev/null
+++ b/tools/perf/util/hist.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_HIST_H
2#define __PERF_HIST_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern struct rb_root hist;
28extern struct rb_root collapse_hists;
29extern struct rb_root output_hists;
30extern int callchain;
31extern struct callchain_param callchain_param;
32extern unsigned long total;
33extern unsigned long total_mmap;
34extern unsigned long total_comm;
35extern unsigned long total_fork;
36extern unsigned long total_unknown;
37extern unsigned long total_lost;
38
39struct hist_entry *__hist_entry__add(struct addr_location *al,
40 struct symbol *parent,
41 u64 count, bool *hit);
42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
44extern void hist_entry__free(struct hist_entry *);
45extern void collapse__insert_entry(struct hist_entry *);
46extern void collapse__resort(void);
47extern void output__insert_entry(struct hist_entry *, u64);
48extern void output__resort(u64);
49
50#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/asm/asm-offsets.h b/tools/perf/util/include/asm/asm-offsets.h
new file mode 100644
index 000000000000..ed538942523d
--- /dev/null
+++ b/tools/perf/util/include/asm/asm-offsets.h
@@ -0,0 +1 @@
/* stub */
diff --git a/tools/perf/util/include/asm/bitops.h b/tools/perf/util/include/asm/bitops.h
new file mode 100644
index 000000000000..58e9817ffae0
--- /dev/null
+++ b/tools/perf/util/include/asm/bitops.h
@@ -0,0 +1,18 @@
1#ifndef _PERF_ASM_BITOPS_H_
2#define _PERF_ASM_BITOPS_H_
3
4#include <sys/types.h>
5#include "../../types.h"
6#include <linux/compiler.h>
7
8/* CHECKME: Not sure both always match */
9#define BITS_PER_LONG __WORDSIZE
10
11#include "../../../../include/asm-generic/bitops/__fls.h"
12#include "../../../../include/asm-generic/bitops/fls.h"
13#include "../../../../include/asm-generic/bitops/fls64.h"
14#include "../../../../include/asm-generic/bitops/__ffs.h"
15#include "../../../../include/asm-generic/bitops/ffz.h"
16#include "../../../../include/asm-generic/bitops/hweight.h"
17
18#endif
diff --git a/tools/perf/util/include/asm/bug.h b/tools/perf/util/include/asm/bug.h
new file mode 100644
index 000000000000..7fcc6810adc2
--- /dev/null
+++ b/tools/perf/util/include/asm/bug.h
@@ -0,0 +1,22 @@
1#ifndef _PERF_ASM_GENERIC_BUG_H
2#define _PERF_ASM_GENERIC_BUG_H
3
4#define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0)
5
6#define WARN(condition, format...) ({ \
7 int __ret_warn_on = !!(condition); \
8 if (unlikely(__ret_warn_on)) \
9 __WARN_printf(format); \
10 unlikely(__ret_warn_on); \
11})
12
13#define WARN_ONCE(condition, format...) ({ \
14 static int __warned; \
15 int __ret_warn_once = !!(condition); \
16 \
17 if (unlikely(__ret_warn_once)) \
18 if (WARN(!__warned, format)) \
19 __warned = 1; \
20 unlikely(__ret_warn_once); \
21})
22#endif
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
new file mode 100644
index 000000000000..b722abe3a626
--- /dev/null
+++ b/tools/perf/util/include/asm/byteorder.h
@@ -0,0 +1,2 @@
1#include <asm/types.h>
2#include "../../../../include/linux/swab.h"
diff --git a/tools/perf/util/include/asm/swab.h b/tools/perf/util/include/asm/swab.h
new file mode 100644
index 000000000000..ed538942523d
--- /dev/null
+++ b/tools/perf/util/include/asm/swab.h
@@ -0,0 +1 @@
/* stub */
diff --git a/tools/perf/util/include/asm/uaccess.h b/tools/perf/util/include/asm/uaccess.h
new file mode 100644
index 000000000000..d0f72b8fcc35
--- /dev/null
+++ b/tools/perf/util/include/asm/uaccess.h
@@ -0,0 +1,14 @@
1#ifndef _PERF_ASM_UACCESS_H_
2#define _PERF_ASM_UACCESS_H_
3
4#define __get_user(src, dest) \
5({ \
6 (src) = *dest; \
7 0; \
8})
9
10#define get_user __get_user
11
12#define access_ok(type, addr, size) 1
13
14#endif
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
new file mode 100644
index 000000000000..94507639a8c4
--- /dev/null
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -0,0 +1,3 @@
1#include "../../../../include/linux/bitmap.h"
2#include "../../../../include/asm-generic/bitops/find.h"
3#include <linux/errno.h>
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
new file mode 100644
index 000000000000..8d63116e9435
--- /dev/null
+++ b/tools/perf/util/include/linux/bitops.h
@@ -0,0 +1,29 @@
1#ifndef _PERF_LINUX_BITOPS_H_
2#define _PERF_LINUX_BITOPS_H_
3
4#define __KERNEL__
5
6#define CONFIG_GENERIC_FIND_NEXT_BIT
7#define CONFIG_GENERIC_FIND_FIRST_BIT
8#include "../../../../include/linux/bitops.h"
9
10#undef __KERNEL__
11
12static inline void set_bit(int nr, unsigned long *addr)
13{
14 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
15}
16
17static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
18{
19 return ((1UL << (nr % BITS_PER_LONG)) &
20 (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
21}
22
23unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned
24 long size, unsigned long offset);
25
26unsigned long generic_find_next_le_bit(const unsigned long *addr, unsigned
27 long size, unsigned long offset);
28
29#endif
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
new file mode 100644
index 000000000000..dfb0713ed47f
--- /dev/null
+++ b/tools/perf/util/include/linux/compiler.h
@@ -0,0 +1,10 @@
1#ifndef _PERF_LINUX_COMPILER_H_
2#define _PERF_LINUX_COMPILER_H_
3
4#ifndef __always_inline
5#define __always_inline inline
6#endif
7#define __user
8#define __attribute_const__
9
10#endif
diff --git a/tools/perf/util/include/linux/ctype.h b/tools/perf/util/include/linux/ctype.h
new file mode 100644
index 000000000000..a53d4ee1e0b7
--- /dev/null
+++ b/tools/perf/util/include/linux/ctype.h
@@ -0,0 +1 @@
#include "../util.h"
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index a6b87390cb52..21c0274c02fa 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -1,6 +1,16 @@
1#ifndef PERF_LINUX_KERNEL_H_ 1#ifndef PERF_LINUX_KERNEL_H_
2#define PERF_LINUX_KERNEL_H_ 2#define PERF_LINUX_KERNEL_H_
3 3
4#include <stdarg.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <assert.h>
8
9#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
10
11#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
12#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
13
4#ifndef offsetof 14#ifndef offsetof
5#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 15#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
6#endif 16#endif
@@ -26,4 +36,70 @@
26 _max1 > _max2 ? _max1 : _max2; }) 36 _max1 > _max2 ? _max1 : _max2; })
27#endif 37#endif
28 38
39#ifndef min
40#define min(x, y) ({ \
41 typeof(x) _min1 = (x); \
42 typeof(y) _min2 = (y); \
43 (void) (&_min1 == &_min2); \
44 _min1 < _min2 ? _min1 : _min2; })
45#endif
46
47#ifndef BUG_ON
48#define BUG_ON(cond) assert(!(cond))
49#endif
50
51/*
52 * Both need more care to handle endianness
53 * (Don't use bitmap_copy_le() for now)
54 */
55#define cpu_to_le64(x) (x)
56#define cpu_to_le32(x) (x)
57
58static inline int
59vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
60{
61 int i;
62 ssize_t ssize = size;
63
64 i = vsnprintf(buf, size, fmt, args);
65
66 return (i >= ssize) ? (ssize - 1) : i;
67}
68
69static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
70{
71 va_list args;
72 ssize_t ssize = size;
73 int i;
74
75 va_start(args, fmt);
76 i = vsnprintf(buf, size, fmt, args);
77 va_end(args);
78
79 return (i >= ssize) ? (ssize - 1) : i;
80}
81
82static inline unsigned long
83simple_strtoul(const char *nptr, char **endptr, int base)
84{
85 return strtoul(nptr, endptr, base);
86}
87
88#ifndef pr_fmt
89#define pr_fmt(fmt) fmt
90#endif
91
92#define pr_err(fmt, ...) \
93 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
94#define pr_warning(fmt, ...) \
95 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
96#define pr_info(fmt, ...) \
97 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
98#define pr_debug(fmt, ...) \
99 eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
100#define pr_debugN(n, fmt, ...) \
101 eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)
102#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
103#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
104
29#endif 105#endif
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
new file mode 100644
index 000000000000..3b2f5900276f
--- /dev/null
+++ b/tools/perf/util/include/linux/string.h
@@ -0,0 +1 @@
#include <string.h>
diff --git a/tools/perf/util/include/linux/types.h b/tools/perf/util/include/linux/types.h
new file mode 100644
index 000000000000..196862a81a21
--- /dev/null
+++ b/tools/perf/util/include/linux/types.h
@@ -0,0 +1,9 @@
1#ifndef _PERF_LINUX_TYPES_H_
2#define _PERF_LINUX_TYPES_H_
3
4#include <asm/types.h>
5
6#define DECLARE_BITMAP(name,bits) \
7 unsigned long name[BITS_TO_LONGS(bits)]
8
9#endif
diff --git a/tools/perf/util/levenshtein.h b/tools/perf/util/levenshtein.h
index 0173abeef52c..b0fcb6d8a881 100644
--- a/tools/perf/util/levenshtein.h
+++ b/tools/perf/util/levenshtein.h
@@ -1,8 +1,8 @@
1#ifndef LEVENSHTEIN_H 1#ifndef __PERF_LEVENSHTEIN_H
2#define LEVENSHTEIN_H 2#define __PERF_LEVENSHTEIN_H
3 3
4int levenshtein(const char *string1, const char *string2, 4int levenshtein(const char *string1, const char *string2,
5 int swap_penalty, int substition_penalty, 5 int swap_penalty, int substition_penalty,
6 int insertion_penalty, int deletion_penalty); 6 int insertion_penalty, int deletion_penalty);
7 7
8#endif 8#endif /* __PERF_LEVENSHTEIN_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 804e02382739..69f94fe9db20 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -3,6 +3,7 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
5#include <stdio.h> 5#include <stdio.h>
6#include "debug.h"
6 7
7static inline int is_anon_memory(const char *filename) 8static inline int is_anon_memory(const char *filename)
8{ 9{
@@ -19,13 +20,28 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
19 return n; 20 return n;
20} 21}
21 22
22 struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) 23void map__init(struct map *self, enum map_type type,
24 u64 start, u64 end, u64 pgoff, struct dso *dso)
25{
26 self->type = type;
27 self->start = start;
28 self->end = end;
29 self->pgoff = pgoff;
30 self->dso = dso;
31 self->map_ip = map__map_ip;
32 self->unmap_ip = map__unmap_ip;
33 RB_CLEAR_NODE(&self->rb_node);
34}
35
36struct map *map__new(struct mmap_event *event, enum map_type type,
37 char *cwd, int cwdlen)
23{ 38{
24 struct map *self = malloc(sizeof(*self)); 39 struct map *self = malloc(sizeof(*self));
25 40
26 if (self != NULL) { 41 if (self != NULL) {
27 const char *filename = event->filename; 42 const char *filename = event->filename;
28 char newfilename[PATH_MAX]; 43 char newfilename[PATH_MAX];
44 struct dso *dso;
29 int anon; 45 int anon;
30 46
31 if (cwd) { 47 if (cwd) {
@@ -45,18 +61,15 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
45 filename = newfilename; 61 filename = newfilename;
46 } 62 }
47 63
48 self->start = event->start; 64 dso = dsos__findnew(filename);
49 self->end = event->start + event->len; 65 if (dso == NULL)
50 self->pgoff = event->pgoff;
51
52 self->dso = dsos__findnew(filename);
53 if (self->dso == NULL)
54 goto out_delete; 66 goto out_delete;
55 67
68 map__init(self, type, event->start, event->start + event->len,
69 event->pgoff, dso);
70
56 if (self->dso == vdso || anon) 71 if (self->dso == vdso || anon)
57 self->map_ip = vdso__map_ip; 72 self->map_ip = self->unmap_ip = identity__map_ip;
58 else
59 self->map_ip = map__map_ip;
60 } 73 }
61 return self; 74 return self;
62out_delete: 75out_delete:
@@ -64,6 +77,72 @@ out_delete:
64 return NULL; 77 return NULL;
65} 78}
66 79
80void map__delete(struct map *self)
81{
82 free(self);
83}
84
85void map__fixup_start(struct map *self)
86{
87 struct rb_root *symbols = &self->dso->symbols[self->type];
88 struct rb_node *nd = rb_first(symbols);
89 if (nd != NULL) {
90 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
91 self->start = sym->start;
92 }
93}
94
95void map__fixup_end(struct map *self)
96{
97 struct rb_root *symbols = &self->dso->symbols[self->type];
98 struct rb_node *nd = rb_last(symbols);
99 if (nd != NULL) {
100 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
101 self->end = sym->end;
102 }
103}
104
105#define DSO__DELETED "(deleted)"
106
107struct symbol *map__find_symbol(struct map *self, u64 addr,
108 symbol_filter_t filter)
109{
110 if (!dso__loaded(self->dso, self->type)) {
111 int nr = dso__load(self->dso, self, filter);
112
113 if (nr < 0) {
114 if (self->dso->has_build_id) {
115 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
116
117 build_id__sprintf(self->dso->build_id,
118 sizeof(self->dso->build_id),
119 sbuild_id);
120 pr_warning("%s with build id %s not found",
121 self->dso->long_name, sbuild_id);
122 } else
123 pr_warning("Failed to open %s",
124 self->dso->long_name);
125 pr_warning(", continuing without symbols\n");
126 return NULL;
127 } else if (nr == 0) {
128 const char *name = self->dso->long_name;
129 const size_t len = strlen(name);
130 const size_t real_len = len - sizeof(DSO__DELETED);
131
132 if (len > sizeof(DSO__DELETED) &&
133 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
134 pr_warning("%.*s was updated, restart the long running apps that use it!\n",
135 (int)real_len, name);
136 } else {
137 pr_warning("no symbols found in %s, maybe install a debug package?\n", name);
138 }
139 return NULL;
140 }
141 }
142
143 return self->dso->find_symbol(self->dso, self->type, addr);
144}
145
67struct map *map__clone(struct map *self) 146struct map *map__clone(struct map *self)
68{ 147{
69 struct map *map = malloc(sizeof(*self)); 148 struct map *map = malloc(sizeof(*self));
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
deleted file mode 100644
index 0d8c85defcd2..000000000000
--- a/tools/perf/util/module.c
+++ /dev/null
@@ -1,545 +0,0 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <libgen.h>
8#include <gelf.h>
9#include <elf.h>
10#include <dirent.h>
11#include <sys/utsname.h>
12
13static unsigned int crc32(const char *p, unsigned int len)
14{
15 int i;
16 unsigned int crc = 0;
17
18 while (len--) {
19 crc ^= *p++;
20 for (i = 0; i < 8; i++)
21 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
22 }
23 return crc;
24}
25
26/* module section methods */
27
28struct sec_dso *sec_dso__new_dso(const char *name)
29{
30 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
31
32 if (self != NULL) {
33 strcpy(self->name, name);
34 self->secs = RB_ROOT;
35 self->find_section = sec_dso__find_section;
36 }
37
38 return self;
39}
40
41static void sec_dso__delete_section(struct section *self)
42{
43 free(((void *)self));
44}
45
46void sec_dso__delete_sections(struct sec_dso *self)
47{
48 struct section *pos;
49 struct rb_node *next = rb_first(&self->secs);
50
51 while (next) {
52 pos = rb_entry(next, struct section, rb_node);
53 next = rb_next(&pos->rb_node);
54 rb_erase(&pos->rb_node, &self->secs);
55 sec_dso__delete_section(pos);
56 }
57}
58
59void sec_dso__delete_self(struct sec_dso *self)
60{
61 sec_dso__delete_sections(self);
62 free(self);
63}
64
65static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
66{
67 struct rb_node **p = &self->secs.rb_node;
68 struct rb_node *parent = NULL;
69 const u64 hash = sec->hash;
70 struct section *s;
71
72 while (*p != NULL) {
73 parent = *p;
74 s = rb_entry(parent, struct section, rb_node);
75 if (hash < s->hash)
76 p = &(*p)->rb_left;
77 else
78 p = &(*p)->rb_right;
79 }
80 rb_link_node(&sec->rb_node, parent, p);
81 rb_insert_color(&sec->rb_node, &self->secs);
82}
83
84struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
85{
86 struct rb_node *n;
87 u64 hash;
88 int len;
89
90 if (self == NULL)
91 return NULL;
92
93 len = strlen(name);
94 hash = crc32(name, len);
95
96 n = self->secs.rb_node;
97
98 while (n) {
99 struct section *s = rb_entry(n, struct section, rb_node);
100
101 if (hash < s->hash)
102 n = n->rb_left;
103 else if (hash > s->hash)
104 n = n->rb_right;
105 else {
106 if (!strcmp(name, s->name))
107 return s;
108 else
109 n = rb_next(&s->rb_node);
110 }
111 }
112
113 return NULL;
114}
115
116static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
117{
118 return fprintf(fp, "name:%s vma:%llx path:%s\n",
119 self->name, self->vma, self->path);
120}
121
122size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
123{
124 size_t ret = fprintf(fp, "dso: %s\n", self->name);
125
126 struct rb_node *nd;
127 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
128 struct section *pos = rb_entry(nd, struct section, rb_node);
129 ret += sec_dso__fprintf_section(pos, fp);
130 }
131
132 return ret;
133}
134
135static struct section *section__new(const char *name, const char *path)
136{
137 struct section *self = calloc(1, sizeof(*self));
138
139 if (!self)
140 goto out_failure;
141
142 self->name = calloc(1, strlen(name) + 1);
143 if (!self->name)
144 goto out_failure;
145
146 self->path = calloc(1, strlen(path) + 1);
147 if (!self->path)
148 goto out_failure;
149
150 strcpy(self->name, name);
151 strcpy(self->path, path);
152 self->hash = crc32(self->name, strlen(name));
153
154 return self;
155
156out_failure:
157 if (self) {
158 if (self->name)
159 free(self->name);
160 if (self->path)
161 free(self->path);
162 free(self);
163 }
164
165 return NULL;
166}
167
168/* module methods */
169
170struct mod_dso *mod_dso__new_dso(const char *name)
171{
172 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
173
174 if (self != NULL) {
175 strcpy(self->name, name);
176 self->mods = RB_ROOT;
177 self->find_module = mod_dso__find_module;
178 }
179
180 return self;
181}
182
183static void mod_dso__delete_module(struct module *self)
184{
185 free(((void *)self));
186}
187
188void mod_dso__delete_modules(struct mod_dso *self)
189{
190 struct module *pos;
191 struct rb_node *next = rb_first(&self->mods);
192
193 while (next) {
194 pos = rb_entry(next, struct module, rb_node);
195 next = rb_next(&pos->rb_node);
196 rb_erase(&pos->rb_node, &self->mods);
197 mod_dso__delete_module(pos);
198 }
199}
200
201void mod_dso__delete_self(struct mod_dso *self)
202{
203 mod_dso__delete_modules(self);
204 free(self);
205}
206
207static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
208{
209 struct rb_node **p = &self->mods.rb_node;
210 struct rb_node *parent = NULL;
211 const u64 hash = mod->hash;
212 struct module *m;
213
214 while (*p != NULL) {
215 parent = *p;
216 m = rb_entry(parent, struct module, rb_node);
217 if (hash < m->hash)
218 p = &(*p)->rb_left;
219 else
220 p = &(*p)->rb_right;
221 }
222 rb_link_node(&mod->rb_node, parent, p);
223 rb_insert_color(&mod->rb_node, &self->mods);
224}
225
226struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
227{
228 struct rb_node *n;
229 u64 hash;
230 int len;
231
232 if (self == NULL)
233 return NULL;
234
235 len = strlen(name);
236 hash = crc32(name, len);
237
238 n = self->mods.rb_node;
239
240 while (n) {
241 struct module *m = rb_entry(n, struct module, rb_node);
242
243 if (hash < m->hash)
244 n = n->rb_left;
245 else if (hash > m->hash)
246 n = n->rb_right;
247 else {
248 if (!strcmp(name, m->name))
249 return m;
250 else
251 n = rb_next(&m->rb_node);
252 }
253 }
254
255 return NULL;
256}
257
258static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
259{
260 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
261}
262
263size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
264{
265 struct rb_node *nd;
266 size_t ret;
267
268 ret = fprintf(fp, "dso: %s\n", self->name);
269
270 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
271 struct module *pos = rb_entry(nd, struct module, rb_node);
272
273 ret += mod_dso__fprintf_module(pos, fp);
274 }
275
276 return ret;
277}
278
279static struct module *module__new(const char *name, const char *path)
280{
281 struct module *self = calloc(1, sizeof(*self));
282
283 if (!self)
284 goto out_failure;
285
286 self->name = calloc(1, strlen(name) + 1);
287 if (!self->name)
288 goto out_failure;
289
290 self->path = calloc(1, strlen(path) + 1);
291 if (!self->path)
292 goto out_failure;
293
294 strcpy(self->name, name);
295 strcpy(self->path, path);
296 self->hash = crc32(self->name, strlen(name));
297
298 return self;
299
300out_failure:
301 if (self) {
302 if (self->name)
303 free(self->name);
304 if (self->path)
305 free(self->path);
306 free(self);
307 }
308
309 return NULL;
310}
311
312static int mod_dso__load_sections(struct module *mod)
313{
314 int count = 0, path_len;
315 struct dirent *entry;
316 char *line = NULL;
317 char *dir_path;
318 DIR *dir;
319 size_t n;
320
321 path_len = strlen("/sys/module/");
322 path_len += strlen(mod->name);
323 path_len += strlen("/sections/");
324
325 dir_path = calloc(1, path_len + 1);
326 if (dir_path == NULL)
327 goto out_failure;
328
329 strcat(dir_path, "/sys/module/");
330 strcat(dir_path, mod->name);
331 strcat(dir_path, "/sections/");
332
333 dir = opendir(dir_path);
334 if (dir == NULL)
335 goto out_free;
336
337 while ((entry = readdir(dir))) {
338 struct section *section;
339 char *path, *vma;
340 int line_len;
341 FILE *file;
342
343 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
344 continue;
345
346 path = calloc(1, path_len + strlen(entry->d_name) + 1);
347 if (path == NULL)
348 break;
349 strcat(path, dir_path);
350 strcat(path, entry->d_name);
351
352 file = fopen(path, "r");
353 if (file == NULL) {
354 free(path);
355 break;
356 }
357
358 line_len = getline(&line, &n, file);
359 if (line_len < 0) {
360 free(path);
361 fclose(file);
362 break;
363 }
364
365 if (!line) {
366 free(path);
367 fclose(file);
368 break;
369 }
370
371 line[--line_len] = '\0'; /* \n */
372
373 vma = strstr(line, "0x");
374 if (!vma) {
375 free(path);
376 fclose(file);
377 break;
378 }
379 vma += 2;
380
381 section = section__new(entry->d_name, path);
382 if (!section) {
383 fprintf(stderr, "load_sections: allocation error\n");
384 free(path);
385 fclose(file);
386 break;
387 }
388
389 hex2u64(vma, &section->vma);
390 sec_dso__insert_section(mod->sections, section);
391
392 free(path);
393 fclose(file);
394 count++;
395 }
396
397 closedir(dir);
398 free(line);
399 free(dir_path);
400
401 return count;
402
403out_free:
404 free(dir_path);
405
406out_failure:
407 return count;
408}
409
410static int mod_dso__load_module_paths(struct mod_dso *self)
411{
412 struct utsname uts;
413 int count = 0, len, err = -1;
414 char *line = NULL;
415 FILE *file;
416 char *dpath, *dir;
417 size_t n;
418
419 if (uname(&uts) < 0)
420 return err;
421
422 len = strlen("/lib/modules/");
423 len += strlen(uts.release);
424 len += strlen("/modules.dep");
425
426 dpath = calloc(1, len + 1);
427 if (dpath == NULL)
428 return err;
429
430 strcat(dpath, "/lib/modules/");
431 strcat(dpath, uts.release);
432 strcat(dpath, "/modules.dep");
433
434 file = fopen(dpath, "r");
435 if (file == NULL)
436 goto out_failure;
437
438 dir = dirname(dpath);
439 if (!dir)
440 goto out_failure;
441 strcat(dir, "/");
442
443 while (!feof(file)) {
444 struct module *module;
445 char *name, *path, *tmp;
446 FILE *modfile;
447 int line_len;
448
449 line_len = getline(&line, &n, file);
450 if (line_len < 0)
451 break;
452
453 if (!line)
454 break;
455
456 line[--line_len] = '\0'; /* \n */
457
458 path = strchr(line, ':');
459 if (!path)
460 break;
461 *path = '\0';
462
463 path = strdup(line);
464 if (!path)
465 break;
466
467 if (!strstr(path, dir)) {
468 if (strncmp(path, "kernel/", 7))
469 break;
470
471 free(path);
472 path = calloc(1, strlen(dir) + strlen(line) + 1);
473 if (!path)
474 break;
475 strcat(path, dir);
476 strcat(path, line);
477 }
478
479 modfile = fopen(path, "r");
480 if (modfile == NULL)
481 break;
482 fclose(modfile);
483
484 name = strdup(path);
485 if (!name)
486 break;
487
488 name = strtok(name, "/");
489 tmp = name;
490
491 while (tmp) {
492 tmp = strtok(NULL, "/");
493 if (tmp)
494 name = tmp;
495 }
496
497 name = strsep(&name, ".");
498 if (!name)
499 break;
500
501 /* Quirk: replace '-' with '_' in all modules */
502 for (len = strlen(name); len; len--) {
503 if (*(name+len) == '-')
504 *(name+len) = '_';
505 }
506
507 module = module__new(name, path);
508 if (!module)
509 break;
510 mod_dso__insert_module(self, module);
511
512 module->sections = sec_dso__new_dso("sections");
513 if (!module->sections)
514 break;
515
516 module->active = mod_dso__load_sections(module);
517
518 if (module->active > 0)
519 count++;
520 }
521
522 if (feof(file))
523 err = count;
524 else
525 fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n");
526
527out_failure:
528 if (dpath)
529 free(dpath);
530 if (file)
531 fclose(file);
532 if (line)
533 free(line);
534
535 return err;
536}
537
538int mod_dso__load_modules(struct mod_dso *dso)
539{
540 int err;
541
542 err = mod_dso__load_module_paths(dso);
543
544 return err;
545}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
deleted file mode 100644
index 8a592ef641ca..000000000000
--- a/tools/perf/util/module.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _PERF_MODULE_
2#define _PERF_MODULE_ 1
3
4#include <linux/types.h>
5#include "../types.h"
6#include <linux/list.h>
7#include <linux/rbtree.h>
8
9struct section {
10 struct rb_node rb_node;
11 u64 hash;
12 u64 vma;
13 char *name;
14 char *path;
15};
16
17struct sec_dso {
18 struct list_head node;
19 struct rb_root secs;
20 struct section *(*find_section)(struct sec_dso *, const char *name);
21 char name[0];
22};
23
24struct module {
25 struct rb_node rb_node;
26 u64 hash;
27 char *name;
28 char *path;
29 struct sec_dso *sections;
30 int active;
31};
32
33struct mod_dso {
34 struct list_head node;
35 struct rb_root mods;
36 struct module *(*find_module)(struct mod_dso *, const char *name);
37 char name[0];
38};
39
40struct sec_dso *sec_dso__new_dso(const char *name);
41void sec_dso__delete_sections(struct sec_dso *self);
42void sec_dso__delete_self(struct sec_dso *self);
43size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
44struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
45
46struct mod_dso *mod_dso__new_dso(const char *name);
47void mod_dso__delete_modules(struct mod_dso *self);
48void mod_dso__delete_self(struct mod_dso *self);
49size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
50struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
51int mod_dso__load_modules(struct mod_dso *dso);
52
53#endif /* _PERF_MODULE_ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 8cfb48cbbea0..9e5dbd66d34d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,4 @@
1 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "parse-options.h" 4#include "parse-options.h"
@@ -7,10 +7,12 @@
7#include "string.h" 7#include "string.h"
8#include "cache.h" 8#include "cache.h"
9#include "header.h" 9#include "header.h"
10#include "debugfs.h"
10 11
11int nr_counters; 12int nr_counters;
12 13
13struct perf_event_attr attrs[MAX_COUNTERS]; 14struct perf_event_attr attrs[MAX_COUNTERS];
15char *filters[MAX_COUNTERS];
14 16
15struct event_symbol { 17struct event_symbol {
16 u8 type; 18 u8 type;
@@ -46,6 +48,8 @@ static struct event_symbol event_symbols[] = {
46 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 48 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
47 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 49 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
48 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 50 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
51 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
52 { CSW(EMULATION_FAULTS), "emulation-faults", "" },
49}; 53};
50 54
51#define __PERF_EVENT_FIELD(config, name) \ 55#define __PERF_EVENT_FIELD(config, name) \
@@ -74,6 +78,8 @@ static const char *sw_event_names[] = {
74 "CPU-migrations", 78 "CPU-migrations",
75 "minor-faults", 79 "minor-faults",
76 "major-faults", 80 "major-faults",
81 "alignment-faults",
82 "emulation-faults",
77}; 83};
78 84
79#define MAX_ALIASES 8 85#define MAX_ALIASES 8
@@ -148,16 +154,6 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
148 154
149#define MAX_EVENT_LENGTH 512 155#define MAX_EVENT_LENGTH 512
150 156
151int valid_debugfs_mount(const char *debugfs)
152{
153 struct statfs st_fs;
154
155 if (statfs(debugfs, &st_fs) < 0)
156 return -ENOENT;
157 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
158 return -ENOENT;
159 return 0;
160}
161 157
162struct tracepoint_path *tracepoint_id_to_path(u64 config) 158struct tracepoint_path *tracepoint_id_to_path(u64 config)
163{ 159{
@@ -170,7 +166,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
170 char evt_path[MAXPATHLEN]; 166 char evt_path[MAXPATHLEN];
171 char dir_path[MAXPATHLEN]; 167 char dir_path[MAXPATHLEN];
172 168
173 if (valid_debugfs_mount(debugfs_path)) 169 if (debugfs_valid_mountpoint(debugfs_path))
174 return NULL; 170 return NULL;
175 171
176 sys_dir = opendir(debugfs_path); 172 sys_dir = opendir(debugfs_path);
@@ -201,7 +197,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
201 if (id == config) { 197 if (id == config) {
202 closedir(evt_dir); 198 closedir(evt_dir);
203 closedir(sys_dir); 199 closedir(sys_dir);
204 path = calloc(1, sizeof(path)); 200 path = zalloc(sizeof(path));
205 path->system = malloc(MAX_EVENT_LENGTH); 201 path->system = malloc(MAX_EVENT_LENGTH);
206 if (!path->system) { 202 if (!path->system) {
207 free(path); 203 free(path);
@@ -509,7 +505,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
509 char sys_name[MAX_EVENT_LENGTH]; 505 char sys_name[MAX_EVENT_LENGTH];
510 unsigned int sys_length, evt_length; 506 unsigned int sys_length, evt_length;
511 507
512 if (valid_debugfs_mount(debugfs_path)) 508 if (debugfs_valid_mountpoint(debugfs_path))
513 return 0; 509 return 0;
514 510
515 evt_name = strchr(*strp, ':'); 511 evt_name = strchr(*strp, ':');
@@ -544,6 +540,81 @@ static enum event_result parse_tracepoint_event(const char **strp,
544 attr, strp); 540 attr, strp);
545} 541}
546 542
543static enum event_result
544parse_breakpoint_type(const char *type, const char **strp,
545 struct perf_event_attr *attr)
546{
547 int i;
548
549 for (i = 0; i < 3; i++) {
550 if (!type[i])
551 break;
552
553 switch (type[i]) {
554 case 'r':
555 attr->bp_type |= HW_BREAKPOINT_R;
556 break;
557 case 'w':
558 attr->bp_type |= HW_BREAKPOINT_W;
559 break;
560 case 'x':
561 attr->bp_type |= HW_BREAKPOINT_X;
562 break;
563 default:
564 return EVT_FAILED;
565 }
566 }
567 if (!attr->bp_type) /* Default */
568 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
569
570 *strp = type + i;
571
572 return EVT_HANDLED;
573}
574
575static enum event_result
576parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
577{
578 const char *target;
579 const char *type;
580 char *endaddr;
581 u64 addr;
582 enum event_result err;
583
584 target = strchr(*strp, ':');
585 if (!target)
586 return EVT_FAILED;
587
588 if (strncmp(*strp, "mem", target - *strp) != 0)
589 return EVT_FAILED;
590
591 target++;
592
593 addr = strtoull(target, &endaddr, 0);
594 if (target == endaddr)
595 return EVT_FAILED;
596
597 attr->bp_addr = addr;
598 *strp = endaddr;
599
600 type = strchr(target, ':');
601
602 /* If no type is defined, just rw as default */
603 if (!type) {
604 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
605 } else {
606 err = parse_breakpoint_type(++type, strp, attr);
607 if (err == EVT_FAILED)
608 return EVT_FAILED;
609 }
610
611 /* We should find a nice way to override the access type */
612 attr->bp_len = HW_BREAKPOINT_LEN_4;
613 attr->type = PERF_TYPE_BREAKPOINT;
614
615 return EVT_HANDLED;
616}
617
547static int check_events(const char *str, unsigned int i) 618static int check_events(const char *str, unsigned int i)
548{ 619{
549 int n; 620 int n;
@@ -677,6 +748,12 @@ parse_event_symbols(const char **str, struct perf_event_attr *attr)
677 if (ret != EVT_FAILED) 748 if (ret != EVT_FAILED)
678 goto modifier; 749 goto modifier;
679 750
751 ret = parse_breakpoint_event(str, attr);
752 if (ret != EVT_FAILED)
753 goto modifier;
754
755 fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
756 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
680 return EVT_FAILED; 757 return EVT_FAILED;
681 758
682modifier: 759modifier:
@@ -708,7 +785,6 @@ static void store_event_type(const char *orgname)
708 perf_header__push_event(id, orgname); 785 perf_header__push_event(id, orgname);
709} 786}
710 787
711
712int parse_events(const struct option *opt __used, const char *str, int unset __used) 788int parse_events(const struct option *opt __used, const char *str, int unset __used)
713{ 789{
714 struct perf_event_attr attr; 790 struct perf_event_attr attr;
@@ -745,6 +821,28 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
745 return 0; 821 return 0;
746} 822}
747 823
824int parse_filter(const struct option *opt __used, const char *str,
825 int unset __used)
826{
827 int i = nr_counters - 1;
828 int len = strlen(str);
829
830 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
831 fprintf(stderr,
832 "-F option should follow a -e tracepoint option\n");
833 return -1;
834 }
835
836 filters[i] = malloc(len + 1);
837 if (!filters[i]) {
838 fprintf(stderr, "not enough memory to hold filter string\n");
839 return -1;
840 }
841 strcpy(filters[i], str);
842
843 return 0;
844}
845
748static const char * const event_type_descriptors[] = { 846static const char * const event_type_descriptors[] = {
749 "", 847 "",
750 "Hardware event", 848 "Hardware event",
@@ -764,7 +862,7 @@ static void print_tracepoint_events(void)
764 char evt_path[MAXPATHLEN]; 862 char evt_path[MAXPATHLEN];
765 char dir_path[MAXPATHLEN]; 863 char dir_path[MAXPATHLEN];
766 864
767 if (valid_debugfs_mount(debugfs_path)) 865 if (debugfs_valid_mountpoint(debugfs_path))
768 return; 866 return;
769 867
770 sys_dir = opendir(debugfs_path); 868 sys_dir = opendir(debugfs_path);
@@ -782,7 +880,7 @@ static void print_tracepoint_events(void)
782 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 880 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
783 snprintf(evt_path, MAXPATHLEN, "%s:%s", 881 snprintf(evt_path, MAXPATHLEN, "%s:%s",
784 sys_dirent.d_name, evt_dirent.d_name); 882 sys_dirent.d_name, evt_dirent.d_name);
785 fprintf(stderr, " %-42s [%s]\n", evt_path, 883 printf(" %-42s [%s]\n", evt_path,
786 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); 884 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
787 } 885 }
788 closedir(evt_dir); 886 closedir(evt_dir);
@@ -799,8 +897,8 @@ void print_events(void)
799 unsigned int i, type, op, prev_type = -1; 897 unsigned int i, type, op, prev_type = -1;
800 char name[40]; 898 char name[40];
801 899
802 fprintf(stderr, "\n"); 900 printf("\n");
803 fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 901 printf("List of pre-defined events (to be used in -e):\n");
804 902
805 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 903 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
806 type = syms->type + 1; 904 type = syms->type + 1;
@@ -808,19 +906,19 @@ void print_events(void)
808 type = 0; 906 type = 0;
809 907
810 if (type != prev_type) 908 if (type != prev_type)
811 fprintf(stderr, "\n"); 909 printf("\n");
812 910
813 if (strlen(syms->alias)) 911 if (strlen(syms->alias))
814 sprintf(name, "%s OR %s", syms->symbol, syms->alias); 912 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
815 else 913 else
816 strcpy(name, syms->symbol); 914 strcpy(name, syms->symbol);
817 fprintf(stderr, " %-42s [%s]\n", name, 915 printf(" %-42s [%s]\n", name,
818 event_type_descriptors[type]); 916 event_type_descriptors[type]);
819 917
820 prev_type = type; 918 prev_type = type;
821 } 919 }
822 920
823 fprintf(stderr, "\n"); 921 printf("\n");
824 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 922 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
825 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 923 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
826 /* skip invalid cache type */ 924 /* skip invalid cache type */
@@ -828,17 +926,20 @@ void print_events(void)
828 continue; 926 continue;
829 927
830 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 928 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
831 fprintf(stderr, " %-42s [%s]\n", 929 printf(" %-42s [%s]\n",
832 event_cache_name(type, op, i), 930 event_cache_name(type, op, i),
833 event_type_descriptors[4]); 931 event_type_descriptors[4]);
834 } 932 }
835 } 933 }
836 } 934 }
837 935
838 fprintf(stderr, "\n"); 936 printf("\n");
839 fprintf(stderr, " %-42s [raw hardware event descriptor]\n", 937 printf(" %-42s [raw hardware event descriptor]\n",
840 "rNNN"); 938 "rNNN");
841 fprintf(stderr, "\n"); 939 printf("\n");
940
941 printf(" %-42s [hardware breakpoint]\n", "mem:<addr>[:access]");
942 printf("\n");
842 943
843 print_tracepoint_events(); 944 print_tracepoint_events();
844 945
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 30c608112845..b8c1f64bc935 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -1,5 +1,5 @@
1#ifndef _PARSE_EVENTS_H 1#ifndef __PERF_PARSE_EVENTS_H
2#define _PARSE_EVENTS_H 2#define __PERF_PARSE_EVENTS_H
3/* 3/*
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
@@ -17,11 +17,13 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
17extern int nr_counters; 17extern int nr_counters;
18 18
19extern struct perf_event_attr attrs[MAX_COUNTERS]; 19extern struct perf_event_attr attrs[MAX_COUNTERS];
20extern char *filters[MAX_COUNTERS];
20 21
21extern const char *event_name(int ctr); 22extern const char *event_name(int ctr);
22extern const char *__event_name(int type, u64 config); 23extern const char *__event_name(int type, u64 config);
23 24
24extern int parse_events(const struct option *opt, const char *str, int unset); 25extern int parse_events(const struct option *opt, const char *str, int unset);
26extern int parse_filter(const struct option *opt, const char *str, int unset);
25 27
26#define EVENTS_HELP_MAX (128*1024) 28#define EVENTS_HELP_MAX (128*1024)
27 29
@@ -31,4 +33,4 @@ extern char debugfs_path[];
31extern int valid_debugfs_mount(const char *debugfs); 33extern int valid_debugfs_mount(const char *debugfs);
32 34
33 35
34#endif /* _PARSE_EVENTS_H */ 36#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 2ee248ff27e5..948805af43c2 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -1,5 +1,5 @@
1#ifndef PARSE_OPTIONS_H 1#ifndef __PERF_PARSE_OPTIONS_H
2#define PARSE_OPTIONS_H 2#define __PERF_PARSE_OPTIONS_H
3 3
4enum parse_opt_type { 4enum parse_opt_type {
5 /* special types */ 5 /* special types */
@@ -174,4 +174,4 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
174 174
175extern const char *parse_options_fix_filename(const char *prefix, const char *file); 175extern const char *parse_options_fix_filename(const char *prefix, const char *file);
176 176
177#endif 177#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
new file mode 100644
index 000000000000..cd7fbda5e2a5
--- /dev/null
+++ b/tools/perf/util/probe-event.c
@@ -0,0 +1,484 @@
1/*
2 * probe-event.c : perf-probe definition to kprobe_events format converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#define _GNU_SOURCE
23#include <sys/utsname.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <errno.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdarg.h>
33#include <limits.h>
34
35#undef _GNU_SOURCE
36#include "event.h"
37#include "string.h"
38#include "strlist.h"
39#include "debug.h"
40#include "parse-events.h" /* For debugfs_path */
41#include "probe-event.h"
42
43#define MAX_CMDLEN 256
44#define MAX_PROBE_ARGS 128
45#define PERFPROBE_GROUP "probe"
46
47#define semantic_error(msg ...) die("Semantic error :" msg)
48
49/* If there is no space to write, returns -E2BIG. */
50static int e_snprintf(char *str, size_t size, const char *format, ...)
51{
52 int ret;
53 va_list ap;
54 va_start(ap, format);
55 ret = vsnprintf(str, size, format, ap);
56 va_end(ap);
57 if (ret >= (int)size)
58 ret = -E2BIG;
59 return ret;
60}
61
62/* Parse probepoint definition. */
63static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
64{
65 char *ptr, *tmp;
66 char c, nc = 0;
67 /*
68 * <Syntax>
69 * perf probe SRC:LN
70 * perf probe FUNC[+OFFS|%return][@SRC]
71 */
72
73 ptr = strpbrk(arg, ":+@%");
74 if (ptr) {
75 nc = *ptr;
76 *ptr++ = '\0';
77 }
78
79 /* Check arg is function or file and copy it */
80 if (strchr(arg, '.')) /* File */
81 pp->file = strdup(arg);
82 else /* Function */
83 pp->function = strdup(arg);
84 DIE_IF(pp->file == NULL && pp->function == NULL);
85
86 /* Parse other options */
87 while (ptr) {
88 arg = ptr;
89 c = nc;
90 ptr = strpbrk(arg, ":+@%");
91 if (ptr) {
92 nc = *ptr;
93 *ptr++ = '\0';
94 }
95 switch (c) {
96 case ':': /* Line number */
97 pp->line = strtoul(arg, &tmp, 0);
98 if (*tmp != '\0')
99 semantic_error("There is non-digit charactor"
100 " in line number.");
101 break;
102 case '+': /* Byte offset from a symbol */
103 pp->offset = strtoul(arg, &tmp, 0);
104 if (*tmp != '\0')
105 semantic_error("There is non-digit charactor"
106 " in offset.");
107 break;
108 case '@': /* File name */
109 if (pp->file)
110 semantic_error("SRC@SRC is not allowed.");
111 pp->file = strdup(arg);
112 DIE_IF(pp->file == NULL);
113 if (ptr)
114 semantic_error("@SRC must be the last "
115 "option.");
116 break;
117 case '%': /* Probe places */
118 if (strcmp(arg, "return") == 0) {
119 pp->retprobe = 1;
120 } else /* Others not supported yet */
121 semantic_error("%%%s is not supported.", arg);
122 break;
123 default:
124 DIE_IF("Program has a bug.");
125 break;
126 }
127 }
128
129 /* Exclusion check */
130 if (pp->line && pp->offset)
131 semantic_error("Offset can't be used with line number.");
132
133 if (!pp->line && pp->file && !pp->function)
134 semantic_error("File always requires line number.");
135
136 if (pp->offset && !pp->function)
137 semantic_error("Offset requires an entry function.");
138
139 if (pp->retprobe && !pp->function)
140 semantic_error("Return probe requires an entry function.");
141
142 if ((pp->offset || pp->line) && pp->retprobe)
143 semantic_error("Offset/Line can't be used with return probe.");
144
145 pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
146 pp->function, pp->file, pp->line, pp->offset, pp->retprobe);
147}
148
149/* Parse perf-probe event definition */
150int parse_perf_probe_event(const char *str, struct probe_point *pp)
151{
152 char **argv;
153 int argc, i, need_dwarf = 0;
154
155 argv = argv_split(str, &argc);
156 if (!argv)
157 die("argv_split failed.");
158 if (argc > MAX_PROBE_ARGS + 1)
159 semantic_error("Too many arguments");
160
161 /* Parse probe point */
162 parse_perf_probe_probepoint(argv[0], pp);
163 if (pp->file || pp->line)
164 need_dwarf = 1;
165
166 /* Copy arguments and ensure return probe has no C argument */
167 pp->nr_args = argc - 1;
168 pp->args = zalloc(sizeof(char *) * pp->nr_args);
169 for (i = 0; i < pp->nr_args; i++) {
170 pp->args[i] = strdup(argv[i + 1]);
171 if (!pp->args[i])
172 die("Failed to copy argument.");
173 if (is_c_varname(pp->args[i])) {
174 if (pp->retprobe)
175 semantic_error("You can't specify local"
176 " variable for kretprobe");
177 need_dwarf = 1;
178 }
179 }
180
181 argv_free(argv);
182 return need_dwarf;
183}
184
185/* Parse kprobe_events event into struct probe_point */
186void parse_trace_kprobe_event(const char *str, char **group, char **event,
187 struct probe_point *pp)
188{
189 char pr;
190 char *p;
191 int ret, i, argc;
192 char **argv;
193
194 pr_debug("Parsing kprobe_events: %s\n", str);
195 argv = argv_split(str, &argc);
196 if (!argv)
197 die("argv_split failed.");
198 if (argc < 2)
199 semantic_error("Too less arguments.");
200
201 /* Scan event and group name. */
202 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
203 &pr, (float *)(void *)group, (float *)(void *)event);
204 if (ret != 3)
205 semantic_error("Failed to parse event name: %s", argv[0]);
206 pr_debug("Group:%s Event:%s probe:%c\n", *group, *event, pr);
207
208 if (!pp)
209 goto end;
210
211 pp->retprobe = (pr == 'r');
212
213 /* Scan function name and offset */
214 ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, &pp->offset);
215 if (ret == 1)
216 pp->offset = 0;
217
218 /* kprobe_events doesn't have this information */
219 pp->line = 0;
220 pp->file = NULL;
221
222 pp->nr_args = argc - 2;
223 pp->args = zalloc(sizeof(char *) * pp->nr_args);
224 for (i = 0; i < pp->nr_args; i++) {
225 p = strchr(argv[i + 2], '=');
226 if (p) /* We don't need which register is assigned. */
227 *p = '\0';
228 pp->args[i] = strdup(argv[i + 2]);
229 if (!pp->args[i])
230 die("Failed to copy argument.");
231 }
232
233end:
234 argv_free(argv);
235}
236
237int synthesize_perf_probe_event(struct probe_point *pp)
238{
239 char *buf;
240 char offs[64] = "", line[64] = "";
241 int i, len, ret;
242
243 pp->probes[0] = buf = zalloc(MAX_CMDLEN);
244 if (!buf)
245 die("Failed to allocate memory by zalloc.");
246 if (pp->offset) {
247 ret = e_snprintf(offs, 64, "+%d", pp->offset);
248 if (ret <= 0)
249 goto error;
250 }
251 if (pp->line) {
252 ret = e_snprintf(line, 64, ":%d", pp->line);
253 if (ret <= 0)
254 goto error;
255 }
256
257 if (pp->function)
258 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
259 offs, pp->retprobe ? "%return" : "", line);
260 else
261 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->file, line);
262 if (ret <= 0)
263 goto error;
264 len = ret;
265
266 for (i = 0; i < pp->nr_args; i++) {
267 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
268 pp->args[i]);
269 if (ret <= 0)
270 goto error;
271 len += ret;
272 }
273 pp->found = 1;
274
275 return pp->found;
276error:
277 free(pp->probes[0]);
278
279 return ret;
280}
281
282int synthesize_trace_kprobe_event(struct probe_point *pp)
283{
284 char *buf;
285 int i, len, ret;
286
287 pp->probes[0] = buf = zalloc(MAX_CMDLEN);
288 if (!buf)
289 die("Failed to allocate memory by zalloc.");
290 ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
291 if (ret <= 0)
292 goto error;
293 len = ret;
294
295 for (i = 0; i < pp->nr_args; i++) {
296 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
297 pp->args[i]);
298 if (ret <= 0)
299 goto error;
300 len += ret;
301 }
302 pp->found = 1;
303
304 return pp->found;
305error:
306 free(pp->probes[0]);
307
308 return ret;
309}
310
311static int open_kprobe_events(int flags, int mode)
312{
313 char buf[PATH_MAX];
314 int ret;
315
316 ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
317 if (ret < 0)
318 die("Failed to make kprobe_events path.");
319
320 ret = open(buf, flags, mode);
321 if (ret < 0) {
322 if (errno == ENOENT)
323 die("kprobe_events file does not exist -"
324 " please rebuild with CONFIG_KPROBE_TRACER.");
325 else
326 die("Could not open kprobe_events file: %s",
327 strerror(errno));
328 }
329 return ret;
330}
331
332/* Get raw string list of current kprobe_events */
333static struct strlist *get_trace_kprobe_event_rawlist(int fd)
334{
335 int ret, idx;
336 FILE *fp;
337 char buf[MAX_CMDLEN];
338 char *p;
339 struct strlist *sl;
340
341 sl = strlist__new(true, NULL);
342
343 fp = fdopen(dup(fd), "r");
344 while (!feof(fp)) {
345 p = fgets(buf, MAX_CMDLEN, fp);
346 if (!p)
347 break;
348
349 idx = strlen(p) - 1;
350 if (p[idx] == '\n')
351 p[idx] = '\0';
352 ret = strlist__add(sl, buf);
353 if (ret < 0)
354 die("strlist__add failed: %s", strerror(-ret));
355 }
356 fclose(fp);
357
358 return sl;
359}
360
361/* Free and zero clear probe_point */
362static void clear_probe_point(struct probe_point *pp)
363{
364 int i;
365
366 if (pp->function)
367 free(pp->function);
368 if (pp->file)
369 free(pp->file);
370 for (i = 0; i < pp->nr_args; i++)
371 free(pp->args[i]);
372 if (pp->args)
373 free(pp->args);
374 for (i = 0; i < pp->found; i++)
375 free(pp->probes[i]);
376 memset(pp, 0, sizeof(pp));
377}
378
379/* List up current perf-probe events */
380void show_perf_probe_events(void)
381{
382 unsigned int i;
383 int fd;
384 char *group, *event;
385 struct probe_point pp;
386 struct strlist *rawlist;
387 struct str_node *ent;
388
389 fd = open_kprobe_events(O_RDONLY, 0);
390 rawlist = get_trace_kprobe_event_rawlist(fd);
391 close(fd);
392
393 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
394 ent = strlist__entry(rawlist, i);
395 parse_trace_kprobe_event(ent->s, &group, &event, &pp);
396 synthesize_perf_probe_event(&pp);
397 printf("[%s:%s]\t%s\n", group, event, pp.probes[0]);
398 free(group);
399 free(event);
400 clear_probe_point(&pp);
401 }
402
403 strlist__delete(rawlist);
404}
405
406/* Get current perf-probe event names */
407static struct strlist *get_perf_event_names(int fd)
408{
409 unsigned int i;
410 char *group, *event;
411 struct strlist *sl, *rawlist;
412 struct str_node *ent;
413
414 rawlist = get_trace_kprobe_event_rawlist(fd);
415
416 sl = strlist__new(false, NULL);
417 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
418 ent = strlist__entry(rawlist, i);
419 parse_trace_kprobe_event(ent->s, &group, &event, NULL);
420 strlist__add(sl, event);
421 free(group);
422 }
423
424 strlist__delete(rawlist);
425
426 return sl;
427}
428
429static int write_trace_kprobe_event(int fd, const char *buf)
430{
431 int ret;
432
433 ret = write(fd, buf, strlen(buf));
434 if (ret <= 0)
435 die("Failed to create event.");
436 else
437 printf("Added new event: %s\n", buf);
438
439 return ret;
440}
441
442static void get_new_event_name(char *buf, size_t len, const char *base,
443 struct strlist *namelist)
444{
445 int i, ret;
446 for (i = 0; i < MAX_EVENT_INDEX; i++) {
447 ret = e_snprintf(buf, len, "%s_%d", base, i);
448 if (ret < 0)
449 die("snprintf() failed: %s", strerror(-ret));
450 if (!strlist__has_entry(namelist, buf))
451 break;
452 }
453 if (i == MAX_EVENT_INDEX)
454 die("Too many events are on the same function.");
455}
456
457void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
458{
459 int i, j, fd;
460 struct probe_point *pp;
461 char buf[MAX_CMDLEN];
462 char event[64];
463 struct strlist *namelist;
464
465 fd = open_kprobe_events(O_RDWR, O_APPEND);
466 /* Get current event names */
467 namelist = get_perf_event_names(fd);
468
469 for (j = 0; j < nr_probes; j++) {
470 pp = probes + j;
471 for (i = 0; i < pp->found; i++) {
472 /* Get an unused new event name */
473 get_new_event_name(event, 64, pp->function, namelist);
474 snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
475 pp->retprobe ? 'r' : 'p',
476 PERFPROBE_GROUP, event,
477 pp->probes[i]);
478 write_trace_kprobe_event(fd, buf);
479 /* Add added event name to namelist */
480 strlist__add(namelist, event);
481 }
482 }
483 close(fd);
484}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
new file mode 100644
index 000000000000..0c6fe56fe38a
--- /dev/null
+++ b/tools/perf/util/probe-event.h
@@ -0,0 +1,18 @@
1#ifndef _PROBE_EVENT_H
2#define _PROBE_EVENT_H
3
4#include "probe-finder.h"
5#include "strlist.h"
6
7extern int parse_perf_probe_event(const char *str, struct probe_point *pp);
8extern int synthesize_perf_probe_event(struct probe_point *pp);
9extern void parse_trace_kprobe_event(const char *str, char **group,
10 char **event, struct probe_point *pp);
11extern int synthesize_trace_kprobe_event(struct probe_point *pp);
12extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes);
13extern void show_perf_probe_events(void);
14
15/* Maximum index number of event-name postfix */
16#define MAX_EVENT_INDEX 1024
17
18#endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
new file mode 100644
index 000000000000..293cdfc1b8ca
--- /dev/null
+++ b/tools/perf/util/probe-finder.c
@@ -0,0 +1,732 @@
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <sys/utsname.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <getopt.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdarg.h>
33#include <ctype.h>
34
35#include "event.h"
36#include "debug.h"
37#include "util.h"
38#include "probe-finder.h"
39
40
41/* Dwarf_Die Linkage to parent Die */
42struct die_link {
43 struct die_link *parent; /* Parent die */
44 Dwarf_Die die; /* Current die */
45};
46
47static Dwarf_Debug __dw_debug;
48static Dwarf_Error __dw_error;
49
50/*
51 * Generic dwarf analysis helpers
52 */
53
54#define X86_32_MAX_REGS 8
55const char *x86_32_regs_table[X86_32_MAX_REGS] = {
56 "%ax",
57 "%cx",
58 "%dx",
59 "%bx",
60 "$stack", /* Stack address instead of %sp */
61 "%bp",
62 "%si",
63 "%di",
64};
65
66#define X86_64_MAX_REGS 16
67const char *x86_64_regs_table[X86_64_MAX_REGS] = {
68 "%ax",
69 "%dx",
70 "%cx",
71 "%bx",
72 "%si",
73 "%di",
74 "%bp",
75 "%sp",
76 "%r8",
77 "%r9",
78 "%r10",
79 "%r11",
80 "%r12",
81 "%r13",
82 "%r14",
83 "%r15",
84};
85
86/* TODO: switching by dwarf address size */
87#ifdef __x86_64__
88#define ARCH_MAX_REGS X86_64_MAX_REGS
89#define arch_regs_table x86_64_regs_table
90#else
91#define ARCH_MAX_REGS X86_32_MAX_REGS
92#define arch_regs_table x86_32_regs_table
93#endif
94
95/* Return architecture dependent register string (for kprobe-tracer) */
96static const char *get_arch_regstr(unsigned int n)
97{
98 return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
99}
100
101/*
102 * Compare the tail of two strings.
103 * Return 0 if whole of either string is same as another's tail part.
104 */
105static int strtailcmp(const char *s1, const char *s2)
106{
107 int i1 = strlen(s1);
108 int i2 = strlen(s2);
109 while (--i1 > 0 && --i2 > 0) {
110 if (s1[i1] != s2[i2])
111 return s1[i1] - s2[i2];
112 }
113 return 0;
114}
115
116/* Find the fileno of the target file. */
117static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname)
118{
119 Dwarf_Signed cnt, i;
120 Dwarf_Unsigned found = 0;
121 char **srcs;
122 int ret;
123
124 if (!fname)
125 return 0;
126
127 ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
128 if (ret == DW_DLV_OK) {
129 for (i = 0; i < cnt && !found; i++) {
130 if (strtailcmp(srcs[i], fname) == 0)
131 found = i + 1;
132 dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
133 }
134 for (; i < cnt; i++)
135 dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
136 dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
137 }
138 if (found)
139 pr_debug("found fno: %d\n", (int)found);
140 return found;
141}
142
143/* Compare diename and tname */
144static int die_compare_name(Dwarf_Die dw_die, const char *tname)
145{
146 char *name;
147 int ret;
148 ret = dwarf_diename(dw_die, &name, &__dw_error);
149 DIE_IF(ret == DW_DLV_ERROR);
150 if (ret == DW_DLV_OK) {
151 ret = strcmp(tname, name);
152 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
153 } else
154 ret = -1;
155 return ret;
156}
157
158/* Check the address is in the subprogram(function). */
159static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
160 Dwarf_Signed *offs)
161{
162 Dwarf_Addr lopc, hipc;
163 int ret;
164
165 /* TODO: check ranges */
166 ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
167 DIE_IF(ret == DW_DLV_ERROR);
168 if (ret == DW_DLV_NO_ENTRY)
169 return 0;
170 ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
171 DIE_IF(ret != DW_DLV_OK);
172 if (lopc <= addr && addr < hipc) {
173 *offs = addr - lopc;
174 return 1;
175 } else
176 return 0;
177}
178
179/* Check the die is inlined function */
180static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
181{
182 /* TODO: check strictly */
183 Dwarf_Bool inl;
184 int ret;
185
186 ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
187 DIE_IF(ret == DW_DLV_ERROR);
188 return inl;
189}
190
191/* Get the offset of abstruct_origin */
192static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
193{
194 Dwarf_Attribute attr;
195 Dwarf_Off cu_offs;
196 int ret;
197
198 ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
199 DIE_IF(ret != DW_DLV_OK);
200 ret = dwarf_formref(attr, &cu_offs, &__dw_error);
201 DIE_IF(ret != DW_DLV_OK);
202 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
203 return cu_offs;
204}
205
206/* Get entry pc(or low pc, 1st entry of ranges) of the die */
207static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
208{
209 Dwarf_Attribute attr;
210 Dwarf_Addr addr;
211 Dwarf_Off offs;
212 Dwarf_Ranges *ranges;
213 Dwarf_Signed cnt;
214 int ret;
215
216 /* Try to get entry pc */
217 ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
218 DIE_IF(ret == DW_DLV_ERROR);
219 if (ret == DW_DLV_OK) {
220 ret = dwarf_formaddr(attr, &addr, &__dw_error);
221 DIE_IF(ret != DW_DLV_OK);
222 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
223 return addr;
224 }
225
226 /* Try to get low pc */
227 ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
228 DIE_IF(ret == DW_DLV_ERROR);
229 if (ret == DW_DLV_OK)
230 return addr;
231
232 /* Try to get ranges */
233 ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
234 DIE_IF(ret != DW_DLV_OK);
235 ret = dwarf_formref(attr, &offs, &__dw_error);
236 DIE_IF(ret != DW_DLV_OK);
237 ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
238 &__dw_error);
239 DIE_IF(ret != DW_DLV_OK);
240 addr = ranges[0].dwr_addr1;
241 dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
242 return addr;
243}
244
245/*
246 * Search a Die from Die tree.
247 * Note: cur_link->die should be deallocated in this function.
248 */
249static int __search_die_tree(struct die_link *cur_link,
250 int (*die_cb)(struct die_link *, void *),
251 void *data)
252{
253 Dwarf_Die new_die;
254 struct die_link new_link;
255 int ret;
256
257 if (!die_cb)
258 return 0;
259
260 /* Check current die */
261 while (!(ret = die_cb(cur_link, data))) {
262 /* Check child die */
263 ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
264 DIE_IF(ret == DW_DLV_ERROR);
265 if (ret == DW_DLV_OK) {
266 new_link.parent = cur_link;
267 new_link.die = new_die;
268 ret = __search_die_tree(&new_link, die_cb, data);
269 if (ret)
270 break;
271 }
272
273 /* Move to next sibling */
274 ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
275 &__dw_error);
276 DIE_IF(ret == DW_DLV_ERROR);
277 dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
278 cur_link->die = new_die;
279 if (ret == DW_DLV_NO_ENTRY)
280 return 0;
281 }
282 dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
283 return ret;
284}
285
286/* Search a die in its children's die tree */
287static int search_die_from_children(Dwarf_Die parent_die,
288 int (*die_cb)(struct die_link *, void *),
289 void *data)
290{
291 struct die_link new_link;
292 int ret;
293
294 new_link.parent = NULL;
295 ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
296 DIE_IF(ret == DW_DLV_ERROR);
297 if (ret == DW_DLV_OK)
298 return __search_die_tree(&new_link, die_cb, data);
299 else
300 return 0;
301}
302
303/* Find a locdesc corresponding to the address */
304static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
305 Dwarf_Addr addr)
306{
307 Dwarf_Signed lcnt;
308 Dwarf_Locdesc **llbuf;
309 int ret, i;
310
311 ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
312 DIE_IF(ret != DW_DLV_OK);
313 ret = DW_DLV_NO_ENTRY;
314 for (i = 0; i < lcnt; ++i) {
315 if (llbuf[i]->ld_lopc <= addr &&
316 llbuf[i]->ld_hipc > addr) {
317 memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
318 desc->ld_s =
319 malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
320 DIE_IF(desc->ld_s == NULL);
321 memcpy(desc->ld_s, llbuf[i]->ld_s,
322 sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
323 ret = DW_DLV_OK;
324 break;
325 }
326 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
327 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
328 }
329 /* Releasing loop */
330 for (; i < lcnt; ++i) {
331 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
332 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
333 }
334 dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
335 return ret;
336}
337
338/* Get decl_file attribute value (file number) */
339static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die)
340{
341 Dwarf_Attribute attr;
342 Dwarf_Unsigned fno;
343 int ret;
344
345 ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error);
346 DIE_IF(ret != DW_DLV_OK);
347 dwarf_formudata(attr, &fno, &__dw_error);
348 DIE_IF(ret != DW_DLV_OK);
349 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
350 return fno;
351}
352
353/* Get decl_line attribute value (line number) */
354static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die)
355{
356 Dwarf_Attribute attr;
357 Dwarf_Unsigned lno;
358 int ret;
359
360 ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error);
361 DIE_IF(ret != DW_DLV_OK);
362 dwarf_formudata(attr, &lno, &__dw_error);
363 DIE_IF(ret != DW_DLV_OK);
364 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
365 return lno;
366}
367
368/*
369 * Probe finder related functions
370 */
371
372/* Show a location */
373static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
374{
375 Dwarf_Small op;
376 Dwarf_Unsigned regn;
377 Dwarf_Signed offs;
378 int deref = 0, ret;
379 const char *regs;
380
381 op = loc->lr_atom;
382
383 /* If this is based on frame buffer, set the offset */
384 if (op == DW_OP_fbreg) {
385 deref = 1;
386 offs = (Dwarf_Signed)loc->lr_number;
387 op = pf->fbloc.ld_s[0].lr_atom;
388 loc = &pf->fbloc.ld_s[0];
389 } else
390 offs = 0;
391
392 if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
393 regn = op - DW_OP_breg0;
394 offs += (Dwarf_Signed)loc->lr_number;
395 deref = 1;
396 } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
397 regn = op - DW_OP_reg0;
398 } else if (op == DW_OP_bregx) {
399 regn = loc->lr_number;
400 offs += (Dwarf_Signed)loc->lr_number2;
401 deref = 1;
402 } else if (op == DW_OP_regx) {
403 regn = loc->lr_number;
404 } else
405 die("Dwarf_OP %d is not supported.\n", op);
406
407 regs = get_arch_regstr(regn);
408 if (!regs)
409 die("%lld exceeds max register number.\n", regn);
410
411 if (deref)
412 ret = snprintf(pf->buf, pf->len,
413 " %s=%+lld(%s)", pf->var, offs, regs);
414 else
415 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
416 DIE_IF(ret < 0);
417 DIE_IF(ret >= pf->len);
418}
419
420/* Show a variables in kprobe event format */
421static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
422{
423 Dwarf_Attribute attr;
424 Dwarf_Locdesc ld;
425 int ret;
426
427 ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
428 if (ret != DW_DLV_OK)
429 goto error;
430 ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
431 if (ret != DW_DLV_OK)
432 goto error;
433 /* TODO? */
434 DIE_IF(ld.ld_cents != 1);
435 show_location(&ld.ld_s[0], pf);
436 free(ld.ld_s);
437 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
438 return ;
439error:
440 die("Failed to find the location of %s at this address.\n"
441 " Perhaps, it has been optimized out.\n", pf->var);
442}
443
444static int variable_callback(struct die_link *dlink, void *data)
445{
446 struct probe_finder *pf = (struct probe_finder *)data;
447 Dwarf_Half tag;
448 int ret;
449
450 ret = dwarf_tag(dlink->die, &tag, &__dw_error);
451 DIE_IF(ret == DW_DLV_ERROR);
452 if ((tag == DW_TAG_formal_parameter ||
453 tag == DW_TAG_variable) &&
454 (die_compare_name(dlink->die, pf->var) == 0)) {
455 show_variable(dlink->die, pf);
456 return 1;
457 }
458 /* TODO: Support struct members and arrays */
459 return 0;
460}
461
462/* Find a variable in a subprogram die */
463static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
464{
465 int ret;
466
467 if (!is_c_varname(pf->var)) {
468 /* Output raw parameters */
469 ret = snprintf(pf->buf, pf->len, " %s", pf->var);
470 DIE_IF(ret < 0);
471 DIE_IF(ret >= pf->len);
472 return ;
473 }
474
475 pr_debug("Searching '%s' variable in context.\n", pf->var);
476 /* Search child die for local variables and parameters. */
477 ret = search_die_from_children(sp_die, variable_callback, pf);
478 if (!ret)
479 die("Failed to find '%s' in this function.\n", pf->var);
480}
481
482/* Get a frame base on the address */
483static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
484{
485 Dwarf_Attribute attr;
486 int ret;
487
488 ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
489 DIE_IF(ret != DW_DLV_OK);
490 ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
491 DIE_IF(ret != DW_DLV_OK);
492 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
493}
494
495static void free_current_frame_base(struct probe_finder *pf)
496{
497 free(pf->fbloc.ld_s);
498 memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
499}
500
501/* Show a probe point to output buffer */
502static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs,
503 struct probe_finder *pf)
504{
505 struct probe_point *pp = pf->pp;
506 char *name;
507 char tmp[MAX_PROBE_BUFFER];
508 int ret, i, len;
509
510 /* Output name of probe point */
511 ret = dwarf_diename(sp_die, &name, &__dw_error);
512 DIE_IF(ret == DW_DLV_ERROR);
513 if (ret == DW_DLV_OK) {
514 ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
515 (unsigned int)offs);
516 /* Copy the function name if possible */
517 if (!pp->function) {
518 pp->function = strdup(name);
519 pp->offset = offs;
520 }
521 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
522 } else {
523 /* This function has no name. */
524 ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
525 if (!pp->function) {
526 /* TODO: Use _stext */
527 pp->function = strdup("");
528 pp->offset = (int)pf->addr;
529 }
530 }
531 DIE_IF(ret < 0);
532 DIE_IF(ret >= MAX_PROBE_BUFFER);
533 len = ret;
534 pr_debug("Probe point found: %s\n", tmp);
535
536 /* Find each argument */
537 get_current_frame_base(sp_die, pf);
538 for (i = 0; i < pp->nr_args; i++) {
539 pf->var = pp->args[i];
540 pf->buf = &tmp[len];
541 pf->len = MAX_PROBE_BUFFER - len;
542 find_variable(sp_die, pf);
543 len += strlen(pf->buf);
544 }
545 free_current_frame_base(pf);
546
547 pp->probes[pp->found] = strdup(tmp);
548 pp->found++;
549}
550
551static int probeaddr_callback(struct die_link *dlink, void *data)
552{
553 struct probe_finder *pf = (struct probe_finder *)data;
554 Dwarf_Half tag;
555 Dwarf_Signed offs;
556 int ret;
557
558 ret = dwarf_tag(dlink->die, &tag, &__dw_error);
559 DIE_IF(ret == DW_DLV_ERROR);
560 /* Check the address is in this subprogram */
561 if (tag == DW_TAG_subprogram &&
562 die_within_subprogram(dlink->die, pf->addr, &offs)) {
563 show_probepoint(dlink->die, offs, pf);
564 return 1;
565 }
566 return 0;
567}
568
569/* Find probe point from its line number */
570static void find_by_line(struct probe_finder *pf)
571{
572 Dwarf_Signed cnt, i, clm;
573 Dwarf_Line *lines;
574 Dwarf_Unsigned lineno = 0;
575 Dwarf_Addr addr;
576 Dwarf_Unsigned fno;
577 int ret;
578
579 ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error);
580 DIE_IF(ret != DW_DLV_OK);
581
582 for (i = 0; i < cnt; i++) {
583 ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
584 DIE_IF(ret != DW_DLV_OK);
585 if (fno != pf->fno)
586 continue;
587
588 ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
589 DIE_IF(ret != DW_DLV_OK);
590 if (lineno != pf->lno)
591 continue;
592
593 ret = dwarf_lineoff(lines[i], &clm, &__dw_error);
594 DIE_IF(ret != DW_DLV_OK);
595
596 ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
597 DIE_IF(ret != DW_DLV_OK);
598 pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n",
599 (int)i, (unsigned)lineno, (int)clm, addr);
600 pf->addr = addr;
601 /* Search a real subprogram including this line, */
602 ret = search_die_from_children(pf->cu_die,
603 probeaddr_callback, pf);
604 if (ret == 0)
605 die("Probe point is not found in subprograms.\n");
606 /* Continuing, because target line might be inlined. */
607 }
608 dwarf_srclines_dealloc(__dw_debug, lines, cnt);
609}
610
611/* Search function from function name */
612static int probefunc_callback(struct die_link *dlink, void *data)
613{
614 struct probe_finder *pf = (struct probe_finder *)data;
615 struct probe_point *pp = pf->pp;
616 struct die_link *lk;
617 Dwarf_Signed offs;
618 Dwarf_Half tag;
619 int ret;
620
621 ret = dwarf_tag(dlink->die, &tag, &__dw_error);
622 DIE_IF(ret == DW_DLV_ERROR);
623 if (tag == DW_TAG_subprogram) {
624 if (die_compare_name(dlink->die, pp->function) == 0) {
625 if (pp->line) { /* Function relative line */
626 pf->fno = die_get_decl_file(dlink->die);
627 pf->lno = die_get_decl_line(dlink->die)
628 + pp->line;
629 find_by_line(pf);
630 return 1;
631 }
632 if (die_inlined_subprogram(dlink->die)) {
633 /* Inlined function, save it. */
634 ret = dwarf_die_CU_offset(dlink->die,
635 &pf->inl_offs,
636 &__dw_error);
637 DIE_IF(ret != DW_DLV_OK);
638 pr_debug("inline definition offset %lld\n",
639 pf->inl_offs);
640 return 0; /* Continue to search */
641 }
642 /* Get probe address */
643 pf->addr = die_get_entrypc(dlink->die);
644 pf->addr += pp->offset;
645 /* TODO: Check the address in this function */
646 show_probepoint(dlink->die, pp->offset, pf);
647 return 1; /* Exit; no same symbol in this CU. */
648 }
649 } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
650 if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
651 /* Get probe address */
652 pf->addr = die_get_entrypc(dlink->die);
653 pf->addr += pp->offset;
654 pr_debug("found inline addr: 0x%llx\n", pf->addr);
655 /* Inlined function. Get a real subprogram */
656 for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
657 tag = 0;
658 dwarf_tag(lk->die, &tag, &__dw_error);
659 DIE_IF(ret == DW_DLV_ERROR);
660 if (tag == DW_TAG_subprogram &&
661 !die_inlined_subprogram(lk->die))
662 goto found;
663 }
664 die("Failed to find real subprogram.\n");
665found:
666 /* Get offset from subprogram */
667 ret = die_within_subprogram(lk->die, pf->addr, &offs);
668 DIE_IF(!ret);
669 show_probepoint(lk->die, offs, pf);
670 /* Continue to search */
671 }
672 }
673 return 0;
674}
675
676static void find_by_func(struct probe_finder *pf)
677{
678 search_die_from_children(pf->cu_die, probefunc_callback, pf);
679}
680
681/* Find a probe point */
682int find_probepoint(int fd, struct probe_point *pp)
683{
684 Dwarf_Half addr_size = 0;
685 Dwarf_Unsigned next_cuh = 0;
686 int cu_number = 0, ret;
687 struct probe_finder pf = {.pp = pp};
688
689 ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
690 if (ret != DW_DLV_OK) {
691 pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO.\n");
692 return -ENOENT;
693 }
694
695 pp->found = 0;
696 while (++cu_number) {
697 /* Search CU (Compilation Unit) */
698 ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
699 &addr_size, &next_cuh, &__dw_error);
700 DIE_IF(ret == DW_DLV_ERROR);
701 if (ret == DW_DLV_NO_ENTRY)
702 break;
703
704 /* Get the DIE(Debugging Information Entry) of this CU */
705 ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error);
706 DIE_IF(ret != DW_DLV_OK);
707
708 /* Check if target file is included. */
709 if (pp->file)
710 pf.fno = cu_find_fileno(pf.cu_die, pp->file);
711
712 if (!pp->file || pf.fno) {
713 /* Save CU base address (for frame_base) */
714 ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error);
715 DIE_IF(ret == DW_DLV_ERROR);
716 if (ret == DW_DLV_NO_ENTRY)
717 pf.cu_base = 0;
718 if (pp->function)
719 find_by_func(&pf);
720 else {
721 pf.lno = pp->line;
722 find_by_line(&pf);
723 }
724 }
725 dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE);
726 }
727 ret = dwarf_finish(__dw_debug, &__dw_error);
728 DIE_IF(ret != DW_DLV_OK);
729
730 return pp->found;
731}
732
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
new file mode 100644
index 000000000000..bdebca6697d2
--- /dev/null
+++ b/tools/perf/util/probe-finder.h
@@ -0,0 +1,57 @@
1#ifndef _PROBE_FINDER_H
2#define _PROBE_FINDER_H
3
4#define MAX_PATH_LEN 256
5#define MAX_PROBE_BUFFER 1024
6#define MAX_PROBES 128
7
8static inline int is_c_varname(const char *name)
9{
10 /* TODO */
11 return isalpha(name[0]) || name[0] == '_';
12}
13
14struct probe_point {
15 /* Inputs */
16 char *file; /* File name */
17 int line; /* Line number */
18
19 char *function; /* Function name */
20 int offset; /* Offset bytes */
21
22 int nr_args; /* Number of arguments */
23 char **args; /* Arguments */
24
25 int retprobe; /* Return probe */
26
27 /* Output */
28 int found; /* Number of found probe points */
29 char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/
30};
31
32#ifndef NO_LIBDWARF
33extern int find_probepoint(int fd, struct probe_point *pp);
34
35#include <libdwarf/dwarf.h>
36#include <libdwarf/libdwarf.h>
37
38struct probe_finder {
39 struct probe_point *pp; /* Target probe point */
40
41 /* For function searching */
42 Dwarf_Addr addr; /* Address */
43 Dwarf_Unsigned fno; /* File number */
44 Dwarf_Unsigned lno; /* Line number */
45 Dwarf_Off inl_offs; /* Inline offset */
46 Dwarf_Die cu_die; /* Current CU */
47
48 /* For variable searching */
49 Dwarf_Addr cu_base; /* Current CU base address */
50 Dwarf_Locdesc fbloc; /* Location of Current Frame Base */
51 const char *var; /* Current variable name */
52 char *buf; /* Current output buffer */
53 int len; /* Length of output buffer */
54};
55#endif /* NO_LIBDWARF */
56
57#endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index a5454a1d1c13..b6a019733919 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -1,5 +1,5 @@
1#ifndef QUOTE_H 1#ifndef __PERF_QUOTE_H
2#define QUOTE_H 2#define __PERF_QUOTE_H
3 3
4#include <stddef.h> 4#include <stddef.h>
5#include <stdio.h> 5#include <stdio.h>
@@ -65,4 +65,4 @@ extern void perl_quote_print(FILE *stream, const char *src);
65extern void python_quote_print(FILE *stream, const char *src); 65extern void python_quote_print(FILE *stream, const char *src);
66extern void tcl_quote_print(FILE *stream, const char *src); 66extern void tcl_quote_print(FILE *stream, const char *src);
67 67
68#endif 68#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index cc1837deba88..d79028727ce2 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -1,5 +1,5 @@
1#ifndef RUN_COMMAND_H 1#ifndef __PERF_RUN_COMMAND_H
2#define RUN_COMMAND_H 2#define __PERF_RUN_COMMAND_H
3 3
4enum { 4enum {
5 ERR_RUN_COMMAND_FORK = 10000, 5 ERR_RUN_COMMAND_FORK = 10000,
@@ -85,4 +85,4 @@ struct async {
85int start_async(struct async *async); 85int start_async(struct async *async);
86int finish_async(struct async *async); 86int finish_async(struct async *async);
87 87
88#endif 88#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
index 618083bce0c6..1a53c11265fd 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/perf/util/sigchain.h
@@ -1,5 +1,5 @@
1#ifndef SIGCHAIN_H 1#ifndef __PERF_SIGCHAIN_H
2#define SIGCHAIN_H 2#define __PERF_SIGCHAIN_H
3 3
4typedef void (*sigchain_fun)(int); 4typedef void (*sigchain_fun)(int);
5 5
@@ -8,4 +8,4 @@ int sigchain_pop(int sig);
8 8
9void sigchain_push_common(sigchain_fun f); 9void sigchain_push_common(sigchain_fun f);
10 10
11#endif /* SIGCHAIN_H */ 11#endif /* __PERF_SIGCHAIN_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
new file mode 100644
index 000000000000..b490354d1b23
--- /dev/null
+++ b/tools/perf/util/sort.c
@@ -0,0 +1,290 @@
1#include "sort.h"
2
3regex_t parent_regex;
4char default_parent_pattern[] = "^sys_|^do_page_fault";
5char *parent_pattern = default_parent_pattern;
6char default_sort_order[] = "comm,dso,symbol";
7char *sort_order = default_sort_order;
8int sort__need_collapse = 0;
9int sort__has_parent = 0;
10
11enum sort_type sort__first_dimension;
12
13unsigned int dsos__col_width;
14unsigned int comms__col_width;
15unsigned int threads__col_width;
16static unsigned int parent_symbol__col_width;
17char * field_sep;
18
19LIST_HEAD(hist_entry__sort_list);
20
21struct sort_entry sort_thread = {
22 .header = "Command: Pid",
23 .cmp = sort__thread_cmp,
24 .print = sort__thread_print,
25 .width = &threads__col_width,
26};
27
28struct sort_entry sort_comm = {
29 .header = "Command",
30 .cmp = sort__comm_cmp,
31 .collapse = sort__comm_collapse,
32 .print = sort__comm_print,
33 .width = &comms__col_width,
34};
35
36struct sort_entry sort_dso = {
37 .header = "Shared Object",
38 .cmp = sort__dso_cmp,
39 .print = sort__dso_print,
40 .width = &dsos__col_width,
41};
42
43struct sort_entry sort_sym = {
44 .header = "Symbol",
45 .cmp = sort__sym_cmp,
46 .print = sort__sym_print,
47};
48
49struct sort_entry sort_parent = {
50 .header = "Parent symbol",
51 .cmp = sort__parent_cmp,
52 .print = sort__parent_print,
53 .width = &parent_symbol__col_width,
54};
55
56struct sort_dimension {
57 const char *name;
58 struct sort_entry *entry;
59 int taken;
60};
61
62static struct sort_dimension sort_dimensions[] = {
63 { .name = "pid", .entry = &sort_thread, },
64 { .name = "comm", .entry = &sort_comm, },
65 { .name = "dso", .entry = &sort_dso, },
66 { .name = "symbol", .entry = &sort_sym, },
67 { .name = "parent", .entry = &sort_parent, },
68};
69
70int64_t cmp_null(void *l, void *r)
71{
72 if (!l && !r)
73 return 0;
74 else if (!l)
75 return -1;
76 else
77 return 1;
78}
79
80/* --sort pid */
81
82int64_t
83sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
84{
85 return right->thread->pid - left->thread->pid;
86}
87
88int repsep_fprintf(FILE *fp, const char *fmt, ...)
89{
90 int n;
91 va_list ap;
92
93 va_start(ap, fmt);
94 if (!field_sep)
95 n = vfprintf(fp, fmt, ap);
96 else {
97 char *bf = NULL;
98 n = vasprintf(&bf, fmt, ap);
99 if (n > 0) {
100 char *sep = bf;
101
102 while (1) {
103 sep = strchr(sep, *field_sep);
104 if (sep == NULL)
105 break;
106 *sep = '.';
107 }
108 }
109 fputs(bf, fp);
110 free(bf);
111 }
112 va_end(ap);
113 return n;
114}
115
116size_t
117sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
118{
119 return repsep_fprintf(fp, "%*s:%5d", width - 6,
120 self->thread->comm ?: "", self->thread->pid);
121}
122
123size_t
124sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
125{
126 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
127}
128
129/* --sort dso */
130
131int64_t
132sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
133{
134 struct dso *dso_l = left->map ? left->map->dso : NULL;
135 struct dso *dso_r = right->map ? right->map->dso : NULL;
136 const char *dso_name_l, *dso_name_r;
137
138 if (!dso_l || !dso_r)
139 return cmp_null(dso_l, dso_r);
140
141 if (verbose) {
142 dso_name_l = dso_l->long_name;
143 dso_name_r = dso_r->long_name;
144 } else {
145 dso_name_l = dso_l->short_name;
146 dso_name_r = dso_r->short_name;
147 }
148
149 return strcmp(dso_name_l, dso_name_r);
150}
151
152size_t
153sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
154{
155 if (self->map && self->map->dso) {
156 const char *dso_name = !verbose ? self->map->dso->short_name :
157 self->map->dso->long_name;
158 return repsep_fprintf(fp, "%-*s", width, dso_name);
159 }
160
161 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
162}
163
164/* --sort symbol */
165
166int64_t
167sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
168{
169 u64 ip_l, ip_r;
170
171 if (left->sym == right->sym)
172 return 0;
173
174 ip_l = left->sym ? left->sym->start : left->ip;
175 ip_r = right->sym ? right->sym->start : right->ip;
176
177 return (int64_t)(ip_r - ip_l);
178}
179
180
181size_t
182sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
183{
184 size_t ret = 0;
185
186 if (verbose) {
187 char o = self->map ? dso__symtab_origin(self->map->dso) : '!';
188 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
189 }
190
191 ret += repsep_fprintf(fp, "[%c] ", self->level);
192 if (self->sym)
193 ret += repsep_fprintf(fp, "%s", self->sym->name);
194 else
195 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
196
197 return ret;
198}
199
200/* --sort comm */
201
202int64_t
203sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
204{
205 return right->thread->pid - left->thread->pid;
206}
207
208int64_t
209sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
210{
211 char *comm_l = left->thread->comm;
212 char *comm_r = right->thread->comm;
213
214 if (!comm_l || !comm_r)
215 return cmp_null(comm_l, comm_r);
216
217 return strcmp(comm_l, comm_r);
218}
219
220/* --sort parent */
221
222int64_t
223sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
224{
225 struct symbol *sym_l = left->parent;
226 struct symbol *sym_r = right->parent;
227
228 if (!sym_l || !sym_r)
229 return cmp_null(sym_l, sym_r);
230
231 return strcmp(sym_l->name, sym_r->name);
232}
233
234size_t
235sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
236{
237 return repsep_fprintf(fp, "%-*s", width,
238 self->parent ? self->parent->name : "[other]");
239}
240
241int sort_dimension__add(const char *tok)
242{
243 unsigned int i;
244
245 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
246 struct sort_dimension *sd = &sort_dimensions[i];
247
248 if (sd->taken)
249 continue;
250
251 if (strncasecmp(tok, sd->name, strlen(tok)))
252 continue;
253
254 if (sd->entry->collapse)
255 sort__need_collapse = 1;
256
257 if (sd->entry == &sort_parent) {
258 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
259 if (ret) {
260 char err[BUFSIZ];
261
262 regerror(ret, &parent_regex, err, sizeof(err));
263 fprintf(stderr, "Invalid regex: %s\n%s",
264 parent_pattern, err);
265 exit(-1);
266 }
267 sort__has_parent = 1;
268 }
269
270 if (list_empty(&hist_entry__sort_list)) {
271 if (!strcmp(sd->name, "pid"))
272 sort__first_dimension = SORT_PID;
273 else if (!strcmp(sd->name, "comm"))
274 sort__first_dimension = SORT_COMM;
275 else if (!strcmp(sd->name, "dso"))
276 sort__first_dimension = SORT_DSO;
277 else if (!strcmp(sd->name, "symbol"))
278 sort__first_dimension = SORT_SYM;
279 else if (!strcmp(sd->name, "parent"))
280 sort__first_dimension = SORT_PARENT;
281 }
282
283 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
284 sd->taken = 1;
285
286 return 0;
287 }
288
289 return -ESRCH;
290}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
new file mode 100644
index 000000000000..333e664ff45f
--- /dev/null
+++ b/tools/perf/util/sort.h
@@ -0,0 +1,99 @@
1#ifndef __PERF_SORT_H
2#define __PERF_SORT_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern regex_t parent_regex;
28extern char *sort_order;
29extern char default_parent_pattern[];
30extern char *parent_pattern;
31extern char default_sort_order[];
32extern int sort__need_collapse;
33extern int sort__has_parent;
34extern char *field_sep;
35extern struct sort_entry sort_comm;
36extern struct sort_entry sort_dso;
37extern struct sort_entry sort_sym;
38extern struct sort_entry sort_parent;
39extern unsigned int dsos__col_width;
40extern unsigned int comms__col_width;
41extern unsigned int threads__col_width;
42extern enum sort_type sort__first_dimension;
43
44struct hist_entry {
45 struct rb_node rb_node;
46 u64 count;
47 struct thread *thread;
48 struct map *map;
49 struct symbol *sym;
50 u64 ip;
51 char level;
52 struct symbol *parent;
53 struct callchain_node callchain;
54 struct rb_root sorted_chain;
55};
56
57enum sort_type {
58 SORT_PID,
59 SORT_COMM,
60 SORT_DSO,
61 SORT_SYM,
62 SORT_PARENT
63};
64
65/*
66 * configurable sorting bits
67 */
68
69struct sort_entry {
70 struct list_head list;
71
72 const char *header;
73
74 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
75 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
76 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
77 unsigned int *width;
78 bool elide;
79};
80
81extern struct sort_entry sort_thread;
82extern struct list_head hist_entry__sort_list;
83
84extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
85extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
86extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
87extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
88extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used);
89extern int64_t cmp_null(void *, void *);
90extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *);
91extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *);
92extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
93extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
94extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
95extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
96extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
97extern int sort_dimension__add(const char *);
98
99#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index d2aa86c014c1..a3d121d6c83e 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -1,5 +1,5 @@
1#ifndef STRBUF_H 1#ifndef __PERF_STRBUF_H
2#define STRBUF_H 2#define __PERF_STRBUF_H
3 3
4/* 4/*
5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary 5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
@@ -134,4 +134,4 @@ extern int launch_editor(const char *path, struct strbuf *buffer, const char *co
134extern int strbuf_branchname(struct strbuf *sb, const char *name); 134extern int strbuf_branchname(struct strbuf *sb, const char *name);
135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name); 135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
136 136
137#endif /* STRBUF_H */ 137#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index c93eca9a7be3..f24a8cc933d5 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,4 +1,5 @@
1#include "string.h" 1#include "string.h"
2#include "util.h"
2 3
3static int hex(char ch) 4static int hex(char ch)
4{ 5{
@@ -32,3 +33,196 @@ int hex2u64(const char *ptr, u64 *long_val)
32 33
33 return p - ptr; 34 return p - ptr;
34} 35}
36
37char *strxfrchar(char *s, char from, char to)
38{
39 char *p = s;
40
41 while ((p = strchr(p, from)) != NULL)
42 *p++ = to;
43
44 return s;
45}
46
47#define K 1024LL
48/*
49 * perf_atoll()
50 * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
51 * and return its numeric value
52 */
53s64 perf_atoll(const char *str)
54{
55 unsigned int i;
56 s64 length = -1, unit = 1;
57
58 if (!isdigit(str[0]))
59 goto out_err;
60
61 for (i = 1; i < strlen(str); i++) {
62 switch (str[i]) {
63 case 'B':
64 case 'b':
65 break;
66 case 'K':
67 if (str[i + 1] != 'B')
68 goto out_err;
69 else
70 goto kilo;
71 case 'k':
72 if (str[i + 1] != 'b')
73 goto out_err;
74kilo:
75 unit = K;
76 break;
77 case 'M':
78 if (str[i + 1] != 'B')
79 goto out_err;
80 else
81 goto mega;
82 case 'm':
83 if (str[i + 1] != 'b')
84 goto out_err;
85mega:
86 unit = K * K;
87 break;
88 case 'G':
89 if (str[i + 1] != 'B')
90 goto out_err;
91 else
92 goto giga;
93 case 'g':
94 if (str[i + 1] != 'b')
95 goto out_err;
96giga:
97 unit = K * K * K;
98 break;
99 case 'T':
100 if (str[i + 1] != 'B')
101 goto out_err;
102 else
103 goto tera;
104 case 't':
105 if (str[i + 1] != 'b')
106 goto out_err;
107tera:
108 unit = K * K * K * K;
109 break;
110 case '\0': /* only specified figures */
111 unit = 1;
112 break;
113 default:
114 if (!isdigit(str[i]))
115 goto out_err;
116 break;
117 }
118 }
119
120 length = atoll(str) * unit;
121 goto out;
122
123out_err:
124 length = -1;
125out:
126 return length;
127}
128
129/*
130 * Helper function for splitting a string into an argv-like array.
131 * originaly copied from lib/argv_split.c
132 */
133static const char *skip_sep(const char *cp)
134{
135 while (*cp && isspace(*cp))
136 cp++;
137
138 return cp;
139}
140
141static const char *skip_arg(const char *cp)
142{
143 while (*cp && !isspace(*cp))
144 cp++;
145
146 return cp;
147}
148
149static int count_argc(const char *str)
150{
151 int count = 0;
152
153 while (*str) {
154 str = skip_sep(str);
155 if (*str) {
156 count++;
157 str = skip_arg(str);
158 }
159 }
160
161 return count;
162}
163
164/**
165 * argv_free - free an argv
166 * @argv - the argument vector to be freed
167 *
168 * Frees an argv and the strings it points to.
169 */
170void argv_free(char **argv)
171{
172 char **p;
173 for (p = argv; *p; p++)
174 free(*p);
175
176 free(argv);
177}
178
179/**
180 * argv_split - split a string at whitespace, returning an argv
181 * @str: the string to be split
182 * @argcp: returned argument count
183 *
184 * Returns an array of pointers to strings which are split out from
185 * @str. This is performed by strictly splitting on white-space; no
186 * quote processing is performed. Multiple whitespace characters are
187 * considered to be a single argument separator. The returned array
188 * is always NULL-terminated. Returns NULL on memory allocation
189 * failure.
190 */
191char **argv_split(const char *str, int *argcp)
192{
193 int argc = count_argc(str);
194 char **argv = zalloc(sizeof(*argv) * (argc+1));
195 char **argvp;
196
197 if (argv == NULL)
198 goto out;
199
200 if (argcp)
201 *argcp = argc;
202
203 argvp = argv;
204
205 while (*str) {
206 str = skip_sep(str);
207
208 if (*str) {
209 const char *p = str;
210 char *t;
211
212 str = skip_arg(str);
213
214 t = strndup(p, str-p);
215 if (t == NULL)
216 goto fail;
217 *argvp++ = t;
218 }
219 }
220 *argvp = NULL;
221
222out:
223 return argv;
224
225fail:
226 argv_free(argv);
227 return NULL;
228}
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index bf39dfadfd24..bfecec265a1a 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,11 +1,15 @@
1#ifndef _PERF_STRING_H_ 1#ifndef __PERF_STRING_H_
2#define _PERF_STRING_H_ 2#define __PERF_STRING_H_
3 3
4#include "types.h" 4#include "types.h"
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7char *strxfrchar(char *s, char from, char to);
8s64 perf_atoll(const char *str);
9char **argv_split(const char *str, int *argcp);
10void argv_free(char **argv);
7 11
8#define _STR(x) #x 12#define _STR(x) #x
9#define STR(x) _STR(x) 13#define STR(x) _STR(x)
10 14
11#endif 15#endif /* __PERF_STRING_H */
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 921818e44a54..cb4659306d7b 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,5 +1,5 @@
1#ifndef STRLIST_H_ 1#ifndef __PERF_STRLIST_H
2#define STRLIST_H_ 2#define __PERF_STRLIST_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
@@ -36,4 +36,4 @@ static inline unsigned int strlist__nr_entries(const struct strlist *self)
36} 36}
37 37
38int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
39#endif /* STRLIST_H_ */ 39#endif /* __PERF_STRLIST_H */
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index cd93195aedb3..e0781989cc31 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -1,5 +1,5 @@
1#ifndef _INCLUDE_GUARD_SVG_HELPER_ 1#ifndef __PERF_SVGHELPER_H
2#define _INCLUDE_GUARD_SVG_HELPER_ 2#define __PERF_SVGHELPER_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -25,4 +25,4 @@ extern void svg_close(void);
25 25
26extern int svg_page_width; 26extern int svg_page_width;
27 27
28#endif 28#endif /* __PERF_SVGHELPER_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 226f44a2357d..fffcb937cdcb 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2,14 +2,20 @@
2#include "../perf.h" 2#include "../perf.h"
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5#include "thread.h"
5 6
6#include "debug.h" 7#include "debug.h"
7 8
9#include <asm/bug.h>
8#include <libelf.h> 10#include <libelf.h>
9#include <gelf.h> 11#include <gelf.h>
10#include <elf.h> 12#include <elf.h>
13#include <limits.h>
14#include <sys/utsname.h>
11 15
12const char *sym_hist_filter; 16#ifndef NT_GNU_BUILD_ID
17#define NT_GNU_BUILD_ID 3
18#endif
13 19
14enum dso_origin { 20enum dso_origin {
15 DSO__ORIG_KERNEL = 0, 21 DSO__ORIG_KERNEL = 0,
@@ -18,94 +24,189 @@ enum dso_origin {
18 DSO__ORIG_UBUNTU, 24 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID, 25 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO, 26 DSO__ORIG_DSO,
27 DSO__ORIG_KMODULE,
21 DSO__ORIG_NOT_FOUND, 28 DSO__ORIG_NOT_FOUND,
22}; 29};
23 30
24static struct symbol *symbol__new(u64 start, u64 len, 31static void dsos__add(struct list_head *head, struct dso *dso);
25 const char *name, unsigned int priv_size, 32static struct map *thread__find_map_by_name(struct thread *self, char *name);
26 u64 obj_start, int v) 33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
34struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
35static int dso__load_kernel_sym(struct dso *self, struct map *map,
36 struct thread *thread, symbol_filter_t filter);
37unsigned int symbol__priv_size;
38static int vmlinux_path__nr_entries;
39static char **vmlinux_path;
40
41static struct symbol_conf symbol_conf__defaults = {
42 .use_modules = true,
43 .try_vmlinux_path = true,
44};
45
46static struct thread kthread_mem;
47struct thread *kthread = &kthread_mem;
48
49bool dso__loaded(const struct dso *self, enum map_type type)
27{ 50{
28 size_t namelen = strlen(name) + 1; 51 return self->loaded & (1 << type);
29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 52}
30 53
31 if (!self) 54static void dso__set_loaded(struct dso *self, enum map_type type)
32 return NULL; 55{
56 self->loaded |= (1 << type);
57}
33 58
34 if (v >= 2) 59static void symbols__fixup_end(struct rb_root *self)
35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 60{
36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 61 struct rb_node *nd, *prevnd = rb_first(self);
62 struct symbol *curr, *prev;
63
64 if (prevnd == NULL)
65 return;
37 66
38 self->obj_start= obj_start; 67 curr = rb_entry(prevnd, struct symbol, rb_node);
39 self->hist = NULL;
40 self->hist_sum = 0;
41 68
42 if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 69 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
43 self->hist = calloc(sizeof(u64), len); 70 prev = curr;
71 curr = rb_entry(nd, struct symbol, rb_node);
44 72
45 if (priv_size) { 73 if (prev->end == prev->start)
46 memset(self, 0, priv_size); 74 prev->end = curr->start - 1;
47 self = ((void *)self) + priv_size;
48 } 75 }
76
77 /* Last entry */
78 if (curr->end == curr->start)
79 curr->end = roundup(curr->start, 4096);
80}
81
82static void __thread__fixup_maps_end(struct thread *self, enum map_type type)
83{
84 struct map *prev, *curr;
85 struct rb_node *nd, *prevnd = rb_first(&self->maps[type]);
86
87 if (prevnd == NULL)
88 return;
89
90 curr = rb_entry(prevnd, struct map, rb_node);
91
92 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
93 prev = curr;
94 curr = rb_entry(nd, struct map, rb_node);
95 prev->end = curr->start - 1;
96 }
97
98 /*
99 * We still haven't the actual symbols, so guess the
100 * last map final address.
101 */
102 curr->end = ~0UL;
103}
104
105static void thread__fixup_maps_end(struct thread *self)
106{
107 int i;
108 for (i = 0; i < MAP__NR_TYPES; ++i)
109 __thread__fixup_maps_end(self, i);
110}
111
112static struct symbol *symbol__new(u64 start, u64 len, const char *name)
113{
114 size_t namelen = strlen(name) + 1;
115 struct symbol *self = zalloc(symbol__priv_size +
116 sizeof(*self) + namelen);
117 if (self == NULL)
118 return NULL;
119
120 if (symbol__priv_size)
121 self = ((void *)self) + symbol__priv_size;
122
49 self->start = start; 123 self->start = start;
50 self->end = len ? start + len - 1 : start; 124 self->end = len ? start + len - 1 : start;
125
126 pr_debug3("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);
127
51 memcpy(self->name, name, namelen); 128 memcpy(self->name, name, namelen);
52 129
53 return self; 130 return self;
54} 131}
55 132
56static void symbol__delete(struct symbol *self, unsigned int priv_size) 133static void symbol__delete(struct symbol *self)
57{ 134{
58 free(((void *)self) - priv_size); 135 free(((void *)self) - symbol__priv_size);
59} 136}
60 137
61static size_t symbol__fprintf(struct symbol *self, FILE *fp) 138static size_t symbol__fprintf(struct symbol *self, FILE *fp)
62{ 139{
63 if (!self->module) 140 return fprintf(fp, " %llx-%llx %s\n",
64 return fprintf(fp, " %llx-%llx %s\n",
65 self->start, self->end, self->name); 141 self->start, self->end, self->name);
66 else
67 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
68 self->start, self->end, self->name, self->module->name);
69} 142}
70 143
71struct dso *dso__new(const char *name, unsigned int sym_priv_size) 144static void dso__set_long_name(struct dso *self, char *name)
145{
146 if (name == NULL)
147 return;
148 self->long_name = name;
149 self->long_name_len = strlen(name);
150}
151
152static void dso__set_basename(struct dso *self)
153{
154 self->short_name = basename(self->long_name);
155}
156
157struct dso *dso__new(const char *name)
72{ 158{
73 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 159 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
74 160
75 if (self != NULL) { 161 if (self != NULL) {
162 int i;
76 strcpy(self->name, name); 163 strcpy(self->name, name);
77 self->syms = RB_ROOT; 164 dso__set_long_name(self, self->name);
78 self->sym_priv_size = sym_priv_size; 165 self->short_name = self->name;
166 for (i = 0; i < MAP__NR_TYPES; ++i)
167 self->symbols[i] = RB_ROOT;
79 self->find_symbol = dso__find_symbol; 168 self->find_symbol = dso__find_symbol;
80 self->slen_calculated = 0; 169 self->slen_calculated = 0;
81 self->origin = DSO__ORIG_NOT_FOUND; 170 self->origin = DSO__ORIG_NOT_FOUND;
171 self->loaded = 0;
172 self->has_build_id = 0;
82 } 173 }
83 174
84 return self; 175 return self;
85} 176}
86 177
87static void dso__delete_symbols(struct dso *self) 178static void symbols__delete(struct rb_root *self)
88{ 179{
89 struct symbol *pos; 180 struct symbol *pos;
90 struct rb_node *next = rb_first(&self->syms); 181 struct rb_node *next = rb_first(self);
91 182
92 while (next) { 183 while (next) {
93 pos = rb_entry(next, struct symbol, rb_node); 184 pos = rb_entry(next, struct symbol, rb_node);
94 next = rb_next(&pos->rb_node); 185 next = rb_next(&pos->rb_node);
95 rb_erase(&pos->rb_node, &self->syms); 186 rb_erase(&pos->rb_node, self);
96 symbol__delete(pos, self->sym_priv_size); 187 symbol__delete(pos);
97 } 188 }
98} 189}
99 190
100void dso__delete(struct dso *self) 191void dso__delete(struct dso *self)
101{ 192{
102 dso__delete_symbols(self); 193 int i;
194 for (i = 0; i < MAP__NR_TYPES; ++i)
195 symbols__delete(&self->symbols[i]);
196 if (self->long_name != self->name)
197 free(self->long_name);
103 free(self); 198 free(self);
104} 199}
105 200
106static void dso__insert_symbol(struct dso *self, struct symbol *sym) 201void dso__set_build_id(struct dso *self, void *build_id)
107{ 202{
108 struct rb_node **p = &self->syms.rb_node; 203 memcpy(self->build_id, build_id, sizeof(self->build_id));
204 self->has_build_id = 1;
205}
206
207static void symbols__insert(struct rb_root *self, struct symbol *sym)
208{
209 struct rb_node **p = &self->rb_node;
109 struct rb_node *parent = NULL; 210 struct rb_node *parent = NULL;
110 const u64 ip = sym->start; 211 const u64 ip = sym->start;
111 struct symbol *s; 212 struct symbol *s;
@@ -119,17 +220,17 @@ static void dso__insert_symbol(struct dso *self, struct symbol *sym)
119 p = &(*p)->rb_right; 220 p = &(*p)->rb_right;
120 } 221 }
121 rb_link_node(&sym->rb_node, parent, p); 222 rb_link_node(&sym->rb_node, parent, p);
122 rb_insert_color(&sym->rb_node, &self->syms); 223 rb_insert_color(&sym->rb_node, self);
123} 224}
124 225
125struct symbol *dso__find_symbol(struct dso *self, u64 ip) 226static struct symbol *symbols__find(struct rb_root *self, u64 ip)
126{ 227{
127 struct rb_node *n; 228 struct rb_node *n;
128 229
129 if (self == NULL) 230 if (self == NULL)
130 return NULL; 231 return NULL;
131 232
132 n = self->syms.rb_node; 233 n = self->rb_node;
133 234
134 while (n) { 235 while (n) {
135 struct symbol *s = rb_entry(n, struct symbol, rb_node); 236 struct symbol *s = rb_entry(n, struct symbol, rb_node);
@@ -145,12 +246,42 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
145 return NULL; 246 return NULL;
146} 247}
147 248
148size_t dso__fprintf(struct dso *self, FILE *fp) 249struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr)
149{ 250{
150 size_t ret = fprintf(fp, "dso: %s\n", self->name); 251 return symbols__find(&self->symbols[type], addr);
252}
253
254int build_id__sprintf(u8 *self, int len, char *bf)
255{
256 char *bid = bf;
257 u8 *raw = self;
258 int i;
259
260 for (i = 0; i < len; ++i) {
261 sprintf(bid, "%02x", *raw);
262 ++raw;
263 bid += 2;
264 }
265
266 return raw - self;
267}
268
269size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
270{
271 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
272
273 build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
274 return fprintf(fp, "%s", sbuild_id);
275}
151 276
277size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
278{
152 struct rb_node *nd; 279 struct rb_node *nd;
153 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 280 size_t ret = fprintf(fp, "dso: %s (", self->short_name);
281
282 ret += dso__fprintf_buildid(self, fp);
283 ret += fprintf(fp, ")\n");
284 for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) {
154 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 285 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
155 ret += symbol__fprintf(pos, fp); 286 ret += symbol__fprintf(pos, fp);
156 } 287 }
@@ -158,13 +289,17 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
158 return ret; 289 return ret;
159} 290}
160 291
161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) 292/*
293 * Loads the function entries in /proc/kallsyms into kernel_map->dso,
294 * so that we can in the next step set the symbol ->end address and then
295 * call kernel_maps__split_kallsyms.
296 */
297static int dso__load_all_kallsyms(struct dso *self, struct map *map)
162{ 298{
163 struct rb_node *nd, *prevnd;
164 char *line = NULL; 299 char *line = NULL;
165 size_t n; 300 size_t n;
301 struct rb_root *root = &self->symbols[map->type];
166 FILE *file = fopen("/proc/kallsyms", "r"); 302 FILE *file = fopen("/proc/kallsyms", "r");
167 int count = 0;
168 303
169 if (file == NULL) 304 if (file == NULL)
170 goto out_failure; 305 goto out_failure;
@@ -174,6 +309,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
174 struct symbol *sym; 309 struct symbol *sym;
175 int line_len, len; 310 int line_len, len;
176 char symbol_type; 311 char symbol_type;
312 char *symbol_name;
177 313
178 line_len = getline(&line, &n, file); 314 line_len = getline(&line, &n, file);
179 if (line_len < 0) 315 if (line_len < 0)
@@ -196,44 +332,26 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
196 */ 332 */
197 if (symbol_type != 'T' && symbol_type != 'W') 333 if (symbol_type != 'T' && symbol_type != 'W')
198 continue; 334 continue;
335
336 symbol_name = line + len + 2;
199 /* 337 /*
200 * Well fix up the end later, when we have all sorted. 338 * Will fix up the end later, when we have all symbols sorted.
201 */ 339 */
202 sym = symbol__new(start, 0xdead, line + len + 2, 340 sym = symbol__new(start, 0, symbol_name);
203 self->sym_priv_size, 0, v);
204 341
205 if (sym == NULL) 342 if (sym == NULL)
206 goto out_delete_line; 343 goto out_delete_line;
207 344 /*
208 if (filter && filter(self, sym)) 345 * We will pass the symbols to the filter later, in
209 symbol__delete(sym, self->sym_priv_size); 346 * map__split_kallsyms, when we have split the maps per module
210 else { 347 */
211 dso__insert_symbol(self, sym); 348 symbols__insert(root, sym);
212 count++;
213 }
214 }
215
216 /*
217 * Now that we have all sorted out, just set the ->end of all
218 * symbols
219 */
220 prevnd = rb_first(&self->syms);
221
222 if (prevnd == NULL)
223 goto out_delete_line;
224
225 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
226 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
227 *curr = rb_entry(nd, struct symbol, rb_node);
228
229 prev->end = curr->start - 1;
230 prevnd = nd;
231 } 349 }
232 350
233 free(line); 351 free(line);
234 fclose(file); 352 fclose(file);
235 353
236 return count; 354 return 0;
237 355
238out_delete_line: 356out_delete_line:
239 free(line); 357 free(line);
@@ -241,14 +359,114 @@ out_failure:
241 return -1; 359 return -1;
242} 360}
243 361
244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) 362/*
363 * Split the symbols into maps, making sure there are no overlaps, i.e. the
364 * kernel range is broken in several maps, named [kernel].N, as we don't have
365 * the original ELF section names vmlinux have.
366 */
367static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread,
368 symbol_filter_t filter)
369{
370 struct map *curr_map = map;
371 struct symbol *pos;
372 int count = 0;
373 struct rb_root *root = &self->symbols[map->type];
374 struct rb_node *next = rb_first(root);
375 int kernel_range = 0;
376
377 while (next) {
378 char *module;
379
380 pos = rb_entry(next, struct symbol, rb_node);
381 next = rb_next(&pos->rb_node);
382
383 module = strchr(pos->name, '\t');
384 if (module) {
385 if (!thread->use_modules)
386 goto discard_symbol;
387
388 *module++ = '\0';
389
390 if (strcmp(self->name, module)) {
391 curr_map = thread__find_map_by_name(thread, module);
392 if (curr_map == NULL) {
393 pr_debug("/proc/{kallsyms,modules} "
394 "inconsistency!\n");
395 return -1;
396 }
397 }
398 /*
399 * So that we look just like we get from .ko files,
400 * i.e. not prelinked, relative to map->start.
401 */
402 pos->start = curr_map->map_ip(curr_map, pos->start);
403 pos->end = curr_map->map_ip(curr_map, pos->end);
404 } else if (curr_map != map) {
405 char dso_name[PATH_MAX];
406 struct dso *dso;
407
408 snprintf(dso_name, sizeof(dso_name), "[kernel].%d",
409 kernel_range++);
410
411 dso = dso__new(dso_name);
412 if (dso == NULL)
413 return -1;
414
415 curr_map = map__new2(pos->start, dso, map->type);
416 if (map == NULL) {
417 dso__delete(dso);
418 return -1;
419 }
420
421 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
422 __thread__insert_map(thread, curr_map);
423 ++kernel_range;
424 }
425
426 if (filter && filter(curr_map, pos)) {
427discard_symbol: rb_erase(&pos->rb_node, root);
428 symbol__delete(pos);
429 } else {
430 if (curr_map != map) {
431 rb_erase(&pos->rb_node, root);
432 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
433 }
434 count++;
435 }
436 }
437
438 return count;
439}
440
441
442static int dso__load_kallsyms(struct dso *self, struct map *map,
443 struct thread *thread, symbol_filter_t filter)
444{
445 if (dso__load_all_kallsyms(self, map) < 0)
446 return -1;
447
448 symbols__fixup_end(&self->symbols[map->type]);
449 self->origin = DSO__ORIG_KERNEL;
450
451 return dso__split_kallsyms(self, map, thread, filter);
452}
453
454size_t kernel_maps__fprintf(FILE *fp)
455{
456 size_t printed = fprintf(fp, "Kernel maps:\n");
457 printed += thread__fprintf_maps(kthread, fp);
458 return printed + fprintf(fp, "END kernel maps\n");
459}
460
461static int dso__load_perf_map(struct dso *self, struct map *map,
462 symbol_filter_t filter)
245{ 463{
246 char *line = NULL; 464 char *line = NULL;
247 size_t n; 465 size_t n;
248 FILE *file; 466 FILE *file;
249 int nr_syms = 0; 467 int nr_syms = 0;
250 468
251 file = fopen(self->name, "r"); 469 file = fopen(self->long_name, "r");
252 if (file == NULL) 470 if (file == NULL)
253 goto out_failure; 471 goto out_failure;
254 472
@@ -278,16 +496,15 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
278 if (len + 2 >= line_len) 496 if (len + 2 >= line_len)
279 continue; 497 continue;
280 498
281 sym = symbol__new(start, size, line + len, 499 sym = symbol__new(start, size, line + len);
282 self->sym_priv_size, start, v);
283 500
284 if (sym == NULL) 501 if (sym == NULL)
285 goto out_delete_line; 502 goto out_delete_line;
286 503
287 if (filter && filter(self, sym)) 504 if (filter && filter(map, sym))
288 symbol__delete(sym, self->sym_priv_size); 505 symbol__delete(sym);
289 else { 506 else {
290 dso__insert_symbol(self, sym); 507 symbols__insert(&self->symbols[map->type], sym);
291 nr_syms++; 508 nr_syms++;
292 } 509 }
293 } 510 }
@@ -393,7 +610,8 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
393 * And always look at the original dso, not at debuginfo packages, that 610 * And always look at the original dso, not at debuginfo packages, that
394 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 611 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
395 */ 612 */
396static int dso__synthesize_plt_symbols(struct dso *self, int v) 613static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
614 symbol_filter_t filter)
397{ 615{
398 uint32_t nr_rel_entries, idx; 616 uint32_t nr_rel_entries, idx;
399 GElf_Sym sym; 617 GElf_Sym sym;
@@ -409,7 +627,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
409 Elf *elf; 627 Elf *elf;
410 int nr = 0, symidx, fd, err = 0; 628 int nr = 0, symidx, fd, err = 0;
411 629
412 fd = open(self->name, O_RDONLY); 630 fd = open(self->long_name, O_RDONLY);
413 if (fd < 0) 631 if (fd < 0)
414 goto out; 632 goto out;
415 633
@@ -477,12 +695,16 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
477 "%s@plt", elf_sym__name(&sym, symstrs)); 695 "%s@plt", elf_sym__name(&sym, symstrs));
478 696
479 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 697 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
480 sympltname, self->sym_priv_size, 0, v); 698 sympltname);
481 if (!f) 699 if (!f)
482 goto out_elf_end; 700 goto out_elf_end;
483 701
484 dso__insert_symbol(self, f); 702 if (filter && filter(map, f))
485 ++nr; 703 symbol__delete(f);
704 else {
705 symbols__insert(&self->symbols[map->type], f);
706 ++nr;
707 }
486 } 708 }
487 } else if (shdr_rel_plt.sh_type == SHT_REL) { 709 } else if (shdr_rel_plt.sh_type == SHT_REL) {
488 GElf_Rel pos_mem, *pos; 710 GElf_Rel pos_mem, *pos;
@@ -495,12 +717,16 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
495 "%s@plt", elf_sym__name(&sym, symstrs)); 717 "%s@plt", elf_sym__name(&sym, symstrs));
496 718
497 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 719 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
498 sympltname, self->sym_priv_size, 0, v); 720 sympltname);
499 if (!f) 721 if (!f)
500 goto out_elf_end; 722 goto out_elf_end;
501 723
502 dso__insert_symbol(self, f); 724 if (filter && filter(map, f))
503 ++nr; 725 symbol__delete(f);
726 else {
727 symbols__insert(&self->symbols[map->type], f);
728 ++nr;
729 }
504 } 730 }
505 } 731 }
506 732
@@ -513,14 +739,18 @@ out_close:
513 if (err == 0) 739 if (err == 0)
514 return nr; 740 return nr;
515out: 741out:
516 fprintf(stderr, "%s: problems reading %s PLT info.\n", 742 pr_warning("%s: problems reading %s PLT info.\n",
517 __func__, self->name); 743 __func__, self->long_name);
518 return 0; 744 return 0;
519} 745}
520 746
521static int dso__load_sym(struct dso *self, int fd, const char *name, 747static int dso__load_sym(struct dso *self, struct map *map,
522 symbol_filter_t filter, int v, struct module *mod) 748 struct thread *thread, const char *name, int fd,
749 symbol_filter_t filter, int kernel, int kmodule)
523{ 750{
751 struct map *curr_map = map;
752 struct dso *curr_dso = self;
753 size_t dso_name_len = strlen(self->short_name);
524 Elf_Data *symstrs, *secstrs; 754 Elf_Data *symstrs, *secstrs;
525 uint32_t nr_syms; 755 uint32_t nr_syms;
526 int err = -1; 756 int err = -1;
@@ -531,19 +761,16 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
531 GElf_Sym sym; 761 GElf_Sym sym;
532 Elf_Scn *sec, *sec_strndx; 762 Elf_Scn *sec, *sec_strndx;
533 Elf *elf; 763 Elf *elf;
534 int nr = 0, kernel = !strcmp("[kernel]", self->name); 764 int nr = 0;
535 765
536 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 766 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
537 if (elf == NULL) { 767 if (elf == NULL) {
538 if (v) 768 pr_err("%s: cannot read %s ELF file.\n", __func__, name);
539 fprintf(stderr, "%s: cannot read %s ELF file.\n",
540 __func__, name);
541 goto out_close; 769 goto out_close;
542 } 770 }
543 771
544 if (gelf_getehdr(elf, &ehdr) == NULL) { 772 if (gelf_getehdr(elf, &ehdr) == NULL) {
545 if (v) 773 pr_err("%s: cannot get elf header.\n", __func__);
546 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
547 goto out_elf_end; 774 goto out_elf_end;
548 } 775 }
549 776
@@ -587,9 +814,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
587 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 814 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
588 struct symbol *f; 815 struct symbol *f;
589 const char *elf_name; 816 const char *elf_name;
590 char *demangled; 817 char *demangled = NULL;
591 u64 obj_start;
592 struct section *section = NULL;
593 int is_label = elf_sym__is_label(&sym); 818 int is_label = elf_sym__is_label(&sym);
594 const char *section_name; 819 const char *section_name;
595 820
@@ -605,52 +830,85 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
605 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 830 if (is_label && !elf_sec__is_text(&shdr, secstrs))
606 continue; 831 continue;
607 832
833 elf_name = elf_sym__name(&sym, symstrs);
608 section_name = elf_sec__name(&shdr, secstrs); 834 section_name = elf_sec__name(&shdr, secstrs);
609 obj_start = sym.st_value;
610 835
611 if (self->adjust_symbols) { 836 if (kernel || kmodule) {
612 if (v >= 2) 837 char dso_name[PATH_MAX];
613 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
614 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
615 838
616 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 839 if (strcmp(section_name,
617 } 840 curr_dso->short_name + dso_name_len) == 0)
841 goto new_symbol;
618 842
619 if (mod) { 843 if (strcmp(section_name, ".text") == 0) {
620 section = mod->sections->find_section(mod->sections, section_name); 844 curr_map = map;
621 if (section) 845 curr_dso = self;
622 sym.st_value += section->vma; 846 goto new_symbol;
623 else {
624 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
625 mod->name, section_name);
626 goto out_elf_end;
627 } 847 }
848
849 snprintf(dso_name, sizeof(dso_name),
850 "%s%s", self->short_name, section_name);
851
852 curr_map = thread__find_map_by_name(thread, dso_name);
853 if (curr_map == NULL) {
854 u64 start = sym.st_value;
855
856 if (kmodule)
857 start += map->start + shdr.sh_offset;
858
859 curr_dso = dso__new(dso_name);
860 if (curr_dso == NULL)
861 goto out_elf_end;
862 curr_map = map__new2(start, curr_dso,
863 MAP__FUNCTION);
864 if (curr_map == NULL) {
865 dso__delete(curr_dso);
866 goto out_elf_end;
867 }
868 curr_map->map_ip = identity__map_ip;
869 curr_map->unmap_ip = identity__map_ip;
870 curr_dso->origin = DSO__ORIG_KERNEL;
871 __thread__insert_map(kthread, curr_map);
872 dsos__add(&dsos__kernel, curr_dso);
873 } else
874 curr_dso = curr_map->dso;
875
876 goto new_symbol;
877 }
878
879 if (curr_dso->adjust_symbols) {
880 pr_debug2("adjusting symbol: st_value: %Lx sh_addr: "
881 "%Lx sh_offset: %Lx\n", (u64)sym.st_value,
882 (u64)shdr.sh_addr, (u64)shdr.sh_offset);
883 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
628 } 884 }
629 /* 885 /*
630 * We need to figure out if the object was created from C++ sources 886 * We need to figure out if the object was created from C++ sources
631 * DWARF DW_compile_unit has this, but we don't always have access 887 * DWARF DW_compile_unit has this, but we don't always have access
632 * to it... 888 * to it...
633 */ 889 */
634 elf_name = elf_sym__name(&sym, symstrs);
635 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); 890 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
636 if (demangled != NULL) 891 if (demangled != NULL)
637 elf_name = demangled; 892 elf_name = demangled;
638 893new_symbol:
639 f = symbol__new(sym.st_value, sym.st_size, elf_name, 894 f = symbol__new(sym.st_value, sym.st_size, elf_name);
640 self->sym_priv_size, obj_start, v);
641 free(demangled); 895 free(demangled);
642 if (!f) 896 if (!f)
643 goto out_elf_end; 897 goto out_elf_end;
644 898
645 if (filter && filter(self, f)) 899 if (filter && filter(curr_map, f))
646 symbol__delete(f, self->sym_priv_size); 900 symbol__delete(f);
647 else { 901 else {
648 f->module = mod; 902 symbols__insert(&curr_dso->symbols[curr_map->type], f);
649 dso__insert_symbol(self, f);
650 nr++; 903 nr++;
651 } 904 }
652 } 905 }
653 906
907 /*
908 * For misannotated, zeroed, ASM function sizes.
909 */
910 if (nr > 0)
911 symbols__fixup_end(&self->symbols[map->type]);
654 err = nr; 912 err = nr;
655out_elf_end: 913out_elf_end:
656 elf_end(elf); 914 elf_end(elf);
@@ -658,63 +916,153 @@ out_close:
658 return err; 916 return err;
659} 917}
660 918
661#define BUILD_ID_SIZE 128 919static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
920{
921 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
922}
662 923
663static char *dso__read_build_id(struct dso *self, int v) 924static bool __dsos__read_build_ids(struct list_head *head)
664{ 925{
665 int i; 926 bool have_build_id = false;
927 struct dso *pos;
928
929 list_for_each_entry(pos, head, node)
930 if (filename__read_build_id(pos->long_name, pos->build_id,
931 sizeof(pos->build_id)) > 0) {
932 have_build_id = true;
933 pos->has_build_id = true;
934 }
935
936 return have_build_id;
937}
938
939bool dsos__read_build_ids(void)
940{
941 return __dsos__read_build_ids(&dsos__kernel) ||
942 __dsos__read_build_ids(&dsos__user);
943}
944
945/*
946 * Align offset to 4 bytes as needed for note name and descriptor data.
947 */
948#define NOTE_ALIGN(n) (((n) + 3) & -4U)
949
950int filename__read_build_id(const char *filename, void *bf, size_t size)
951{
952 int fd, err = -1;
666 GElf_Ehdr ehdr; 953 GElf_Ehdr ehdr;
667 GElf_Shdr shdr; 954 GElf_Shdr shdr;
668 Elf_Data *build_id_data; 955 Elf_Data *data;
669 Elf_Scn *sec; 956 Elf_Scn *sec;
670 char *build_id = NULL, *bid; 957 Elf_Kind ek;
671 unsigned char *raw; 958 void *ptr;
672 Elf *elf; 959 Elf *elf;
673 int fd = open(self->name, O_RDONLY);
674 960
961 if (size < BUILD_ID_SIZE)
962 goto out;
963
964 fd = open(filename, O_RDONLY);
675 if (fd < 0) 965 if (fd < 0)
676 goto out; 966 goto out;
677 967
678 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 968 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
679 if (elf == NULL) { 969 if (elf == NULL) {
680 if (v) 970 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
681 fprintf(stderr, "%s: cannot read %s ELF file.\n",
682 __func__, self->name);
683 goto out_close; 971 goto out_close;
684 } 972 }
685 973
974 ek = elf_kind(elf);
975 if (ek != ELF_K_ELF)
976 goto out_elf_end;
977
686 if (gelf_getehdr(elf, &ehdr) == NULL) { 978 if (gelf_getehdr(elf, &ehdr) == NULL) {
687 if (v) 979 pr_err("%s: cannot get elf header.\n", __func__);
688 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
689 goto out_elf_end; 980 goto out_elf_end;
690 } 981 }
691 982
692 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL); 983 sec = elf_section_by_name(elf, &ehdr, &shdr,
693 if (sec == NULL) 984 ".note.gnu.build-id", NULL);
694 goto out_elf_end; 985 if (sec == NULL) {
986 sec = elf_section_by_name(elf, &ehdr, &shdr,
987 ".notes", NULL);
988 if (sec == NULL)
989 goto out_elf_end;
990 }
695 991
696 build_id_data = elf_getdata(sec, NULL); 992 data = elf_getdata(sec, NULL);
697 if (build_id_data == NULL) 993 if (data == NULL)
698 goto out_elf_end;
699 build_id = malloc(BUILD_ID_SIZE);
700 if (build_id == NULL)
701 goto out_elf_end; 994 goto out_elf_end;
702 raw = build_id_data->d_buf + 16;
703 bid = build_id;
704 995
705 for (i = 0; i < 20; ++i) { 996 ptr = data->d_buf;
706 sprintf(bid, "%02x", *raw); 997 while (ptr < (data->d_buf + data->d_size)) {
707 ++raw; 998 GElf_Nhdr *nhdr = ptr;
708 bid += 2; 999 int namesz = NOTE_ALIGN(nhdr->n_namesz),
1000 descsz = NOTE_ALIGN(nhdr->n_descsz);
1001 const char *name;
1002
1003 ptr += sizeof(*nhdr);
1004 name = ptr;
1005 ptr += namesz;
1006 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1007 nhdr->n_namesz == sizeof("GNU")) {
1008 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1009 memcpy(bf, ptr, BUILD_ID_SIZE);
1010 err = BUILD_ID_SIZE;
1011 break;
1012 }
1013 }
1014 ptr += descsz;
709 } 1015 }
710 if (v >= 2)
711 printf("%s(%s): %s\n", __func__, self->name, build_id);
712out_elf_end: 1016out_elf_end:
713 elf_end(elf); 1017 elf_end(elf);
714out_close: 1018out_close:
715 close(fd); 1019 close(fd);
716out: 1020out:
717 return build_id; 1021 return err;
1022}
1023
1024int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1025{
1026 int fd, err = -1;
1027
1028 if (size < BUILD_ID_SIZE)
1029 goto out;
1030
1031 fd = open(filename, O_RDONLY);
1032 if (fd < 0)
1033 goto out;
1034
1035 while (1) {
1036 char bf[BUFSIZ];
1037 GElf_Nhdr nhdr;
1038 int namesz, descsz;
1039
1040 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1041 break;
1042
1043 namesz = NOTE_ALIGN(nhdr.n_namesz);
1044 descsz = NOTE_ALIGN(nhdr.n_descsz);
1045 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1046 nhdr.n_namesz == sizeof("GNU")) {
1047 if (read(fd, bf, namesz) != namesz)
1048 break;
1049 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1050 if (read(fd, build_id,
1051 BUILD_ID_SIZE) == BUILD_ID_SIZE) {
1052 err = 0;
1053 break;
1054 }
1055 } else if (read(fd, bf, descsz) != descsz)
1056 break;
1057 } else {
1058 int n = namesz + descsz;
1059 if (read(fd, bf, n) != n)
1060 break;
1061 }
1062 }
1063 close(fd);
1064out:
1065 return err;
718} 1066}
719 1067
720char dso__symtab_origin(const struct dso *self) 1068char dso__symtab_origin(const struct dso *self)
@@ -726,6 +1074,7 @@ char dso__symtab_origin(const struct dso *self)
726 [DSO__ORIG_UBUNTU] = 'u', 1074 [DSO__ORIG_UBUNTU] = 'u',
727 [DSO__ORIG_BUILDID] = 'b', 1075 [DSO__ORIG_BUILDID] = 'b',
728 [DSO__ORIG_DSO] = 'd', 1076 [DSO__ORIG_DSO] = 'd',
1077 [DSO__ORIG_KMODULE] = 'K',
729 }; 1078 };
730 1079
731 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 1080 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -733,20 +1082,27 @@ char dso__symtab_origin(const struct dso *self)
733 return origin[self->origin]; 1082 return origin[self->origin];
734} 1083}
735 1084
736int dso__load(struct dso *self, symbol_filter_t filter, int v) 1085int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
737{ 1086{
738 int size = PATH_MAX; 1087 int size = PATH_MAX;
739 char *name = malloc(size), *build_id = NULL; 1088 char *name;
1089 u8 build_id[BUILD_ID_SIZE];
740 int ret = -1; 1090 int ret = -1;
741 int fd; 1091 int fd;
742 1092
1093 dso__set_loaded(self, map->type);
1094
1095 if (self->kernel)
1096 return dso__load_kernel_sym(self, map, kthread, filter);
1097
1098 name = malloc(size);
743 if (!name) 1099 if (!name)
744 return -1; 1100 return -1;
745 1101
746 self->adjust_symbols = 0; 1102 self->adjust_symbols = 0;
747 1103
748 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 1104 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
749 ret = dso__load_perf_map(self, filter, v); 1105 ret = dso__load_perf_map(self, map, filter);
750 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 1106 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
751 DSO__ORIG_NOT_FOUND; 1107 DSO__ORIG_NOT_FOUND;
752 return ret; 1108 return ret;
@@ -759,34 +1115,50 @@ more:
759 self->origin++; 1115 self->origin++;
760 switch (self->origin) { 1116 switch (self->origin) {
761 case DSO__ORIG_FEDORA: 1117 case DSO__ORIG_FEDORA:
762 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 1118 snprintf(name, size, "/usr/lib/debug%s.debug",
1119 self->long_name);
763 break; 1120 break;
764 case DSO__ORIG_UBUNTU: 1121 case DSO__ORIG_UBUNTU:
765 snprintf(name, size, "/usr/lib/debug%s", self->name); 1122 snprintf(name, size, "/usr/lib/debug%s",
1123 self->long_name);
766 break; 1124 break;
767 case DSO__ORIG_BUILDID: 1125 case DSO__ORIG_BUILDID:
768 build_id = dso__read_build_id(self, v); 1126 if (filename__read_build_id(self->long_name, build_id,
769 if (build_id != NULL) { 1127 sizeof(build_id))) {
1128 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1129
1130 build_id__sprintf(build_id, sizeof(build_id),
1131 build_id_hex);
770 snprintf(name, size, 1132 snprintf(name, size,
771 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1133 "/usr/lib/debug/.build-id/%.2s/%s.debug",
772 build_id, build_id + 2); 1134 build_id_hex, build_id_hex + 2);
773 free(build_id); 1135 if (self->has_build_id)
1136 goto compare_build_id;
774 break; 1137 break;
775 } 1138 }
776 self->origin++; 1139 self->origin++;
777 /* Fall thru */ 1140 /* Fall thru */
778 case DSO__ORIG_DSO: 1141 case DSO__ORIG_DSO:
779 snprintf(name, size, "%s", self->name); 1142 snprintf(name, size, "%s", self->long_name);
780 break; 1143 break;
781 1144
782 default: 1145 default:
783 goto out; 1146 goto out;
784 } 1147 }
785 1148
1149 if (self->has_build_id) {
1150 if (filename__read_build_id(name, build_id,
1151 sizeof(build_id)) < 0)
1152 goto more;
1153compare_build_id:
1154 if (!dso__build_id_equal(self, build_id))
1155 goto more;
1156 }
1157
786 fd = open(name, O_RDONLY); 1158 fd = open(name, O_RDONLY);
787 } while (fd < 0); 1159 } while (fd < 0);
788 1160
789 ret = dso__load_sym(self, fd, name, filter, v, NULL); 1161 ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0);
790 close(fd); 1162 close(fd);
791 1163
792 /* 1164 /*
@@ -796,7 +1168,7 @@ more:
796 goto more; 1168 goto more;
797 1169
798 if (ret > 0) { 1170 if (ret > 0) {
799 int nr_plt = dso__synthesize_plt_symbols(self, v); 1171 int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
800 if (nr_plt > 0) 1172 if (nr_plt > 0)
801 ret += nr_plt; 1173 ret += nr_plt;
802 } 1174 }
@@ -807,151 +1179,279 @@ out:
807 return ret; 1179 return ret;
808} 1180}
809 1181
810static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 1182static struct map *thread__find_map_by_name(struct thread *self, char *name)
811 symbol_filter_t filter, int v)
812{ 1183{
813 struct module *mod = mod_dso__find_module(mods, name); 1184 struct rb_node *nd;
814 int err = 0, fd;
815 1185
816 if (mod == NULL || !mod->active) 1186 for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
817 return err; 1187 struct map *map = rb_entry(nd, struct map, rb_node);
818 1188
819 fd = open(mod->path, O_RDONLY); 1189 if (map->dso && strcmp(map->dso->name, name) == 0)
1190 return map;
1191 }
820 1192
821 if (fd < 0) 1193 return NULL;
822 return err; 1194}
823 1195
824 err = dso__load_sym(self, fd, name, filter, v, mod); 1196static int dsos__set_modules_path_dir(char *dirname)
825 close(fd); 1197{
1198 struct dirent *dent;
1199 DIR *dir = opendir(dirname);
826 1200
827 return err; 1201 if (!dir) {
1202 pr_debug("%s: cannot open %s dir\n", __func__, dirname);
1203 return -1;
1204 }
1205
1206 while ((dent = readdir(dir)) != NULL) {
1207 char path[PATH_MAX];
1208
1209 if (dent->d_type == DT_DIR) {
1210 if (!strcmp(dent->d_name, ".") ||
1211 !strcmp(dent->d_name, ".."))
1212 continue;
1213
1214 snprintf(path, sizeof(path), "%s/%s",
1215 dirname, dent->d_name);
1216 if (dsos__set_modules_path_dir(path) < 0)
1217 goto failure;
1218 } else {
1219 char *dot = strrchr(dent->d_name, '.'),
1220 dso_name[PATH_MAX];
1221 struct map *map;
1222 char *long_name;
1223
1224 if (dot == NULL || strcmp(dot, ".ko"))
1225 continue;
1226 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1227 (int)(dot - dent->d_name), dent->d_name);
1228
1229 strxfrchar(dso_name, '-', '_');
1230 map = thread__find_map_by_name(kthread, dso_name);
1231 if (map == NULL)
1232 continue;
1233
1234 snprintf(path, sizeof(path), "%s/%s",
1235 dirname, dent->d_name);
1236
1237 long_name = strdup(path);
1238 if (long_name == NULL)
1239 goto failure;
1240 dso__set_long_name(map->dso, long_name);
1241 }
1242 }
1243
1244 return 0;
1245failure:
1246 closedir(dir);
1247 return -1;
828} 1248}
829 1249
830int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) 1250static int dsos__set_modules_path(void)
831{ 1251{
832 struct mod_dso *mods = mod_dso__new_dso("modules"); 1252 struct utsname uts;
833 struct module *pos; 1253 char modules_path[PATH_MAX];
834 struct rb_node *next;
835 int err, count = 0;
836 1254
837 err = mod_dso__load_modules(mods); 1255 if (uname(&uts) < 0)
838 1256 return -1;
839 if (err <= 0)
840 return err;
841 1257
842 /* 1258 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
843 * Iterate over modules, and load active symbols. 1259 uts.release);
844 */
845 next = rb_first(&mods->mods);
846 while (next) {
847 pos = rb_entry(next, struct module, rb_node);
848 err = dso__load_module(self, mods, pos->name, filter, v);
849 1260
850 if (err < 0) 1261 return dsos__set_modules_path_dir(modules_path);
851 break; 1262}
852 1263
853 next = rb_next(&pos->rb_node); 1264/*
854 count += err; 1265 * Constructor variant for modules (where we know from /proc/modules where
855 } 1266 * they are loaded) and for vmlinux, where only after we load all the
1267 * symbols we'll know where it starts and ends.
1268 */
1269static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1270{
1271 struct map *self = malloc(sizeof(*self));
856 1272
857 if (err < 0) { 1273 if (self != NULL) {
858 mod_dso__delete_modules(mods); 1274 /*
859 mod_dso__delete_self(mods); 1275 * ->end will be filled after we load all the symbols
860 return err; 1276 */
1277 map__init(self, type, start, 0, 0, dso);
861 } 1278 }
862 1279
863 return count; 1280 return self;
864} 1281}
865 1282
866static inline void dso__fill_symbol_holes(struct dso *self) 1283static int thread__create_module_maps(struct thread *self)
867{ 1284{
868 struct symbol *prev = NULL; 1285 char *line = NULL;
869 struct rb_node *nd; 1286 size_t n;
1287 FILE *file = fopen("/proc/modules", "r");
1288 struct map *map;
870 1289
871 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 1290 if (file == NULL)
872 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 1291 return -1;
873 1292
874 if (prev) { 1293 while (!feof(file)) {
875 u64 hole = 0; 1294 char name[PATH_MAX];
876 int alias = pos->start == prev->start; 1295 u64 start;
1296 struct dso *dso;
1297 char *sep;
1298 int line_len;
877 1299
878 if (!alias) 1300 line_len = getline(&line, &n, file);
879 hole = prev->start - pos->end - 1; 1301 if (line_len < 0)
1302 break;
880 1303
881 if (hole || alias) { 1304 if (!line)
882 if (alias) 1305 goto out_failure;
883 pos->end = prev->end; 1306
884 else if (hole) 1307 line[--line_len] = '\0'; /* \n */
885 pos->end = prev->start - 1; 1308
886 } 1309 sep = strrchr(line, 'x');
1310 if (sep == NULL)
1311 continue;
1312
1313 hex2u64(sep + 1, &start);
1314
1315 sep = strchr(line, ' ');
1316 if (sep == NULL)
1317 continue;
1318
1319 *sep = '\0';
1320
1321 snprintf(name, sizeof(name), "[%s]", line);
1322 dso = dso__new(name);
1323
1324 if (dso == NULL)
1325 goto out_delete_line;
1326
1327 map = map__new2(start, dso, MAP__FUNCTION);
1328 if (map == NULL) {
1329 dso__delete(dso);
1330 goto out_delete_line;
887 } 1331 }
888 prev = pos; 1332
1333 snprintf(name, sizeof(name),
1334 "/sys/module/%s/notes/.note.gnu.build-id", line);
1335 if (sysfs__read_build_id(name, dso->build_id,
1336 sizeof(dso->build_id)) == 0)
1337 dso->has_build_id = true;
1338
1339 dso->origin = DSO__ORIG_KMODULE;
1340 __thread__insert_map(self, map);
1341 dsos__add(&dsos__kernel, dso);
889 } 1342 }
1343
1344 free(line);
1345 fclose(file);
1346
1347 return dsos__set_modules_path();
1348
1349out_delete_line:
1350 free(line);
1351out_failure:
1352 return -1;
890} 1353}
891 1354
892static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 1355static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread,
893 symbol_filter_t filter, int v) 1356 const char *vmlinux, symbol_filter_t filter)
894{ 1357{
895 int err, fd = open(vmlinux, O_RDONLY); 1358 int err = -1, fd;
896 1359
897 if (fd < 0) 1360 if (self->has_build_id) {
898 return -1; 1361 u8 build_id[BUILD_ID_SIZE];
899 1362
900 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); 1363 if (filename__read_build_id(vmlinux, build_id,
1364 sizeof(build_id)) < 0) {
1365 pr_debug("No build_id in %s, ignoring it\n", vmlinux);
1366 return -1;
1367 }
1368 if (!dso__build_id_equal(self, build_id)) {
1369 char expected_build_id[BUILD_ID_SIZE * 2 + 1],
1370 vmlinux_build_id[BUILD_ID_SIZE * 2 + 1];
1371
1372 build_id__sprintf(self->build_id,
1373 sizeof(self->build_id),
1374 expected_build_id);
1375 build_id__sprintf(build_id, sizeof(build_id),
1376 vmlinux_build_id);
1377 pr_debug("build_id in %s is %s while expected is %s, "
1378 "ignoring it\n", vmlinux, vmlinux_build_id,
1379 expected_build_id);
1380 return -1;
1381 }
1382 }
901 1383
902 if (err > 0) 1384 fd = open(vmlinux, O_RDONLY);
903 dso__fill_symbol_holes(self); 1385 if (fd < 0)
1386 return -1;
904 1387
1388 dso__set_loaded(self, map->type);
1389 err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0);
905 close(fd); 1390 close(fd);
906 1391
907 return err; 1392 return err;
908} 1393}
909 1394
910int dso__load_kernel(struct dso *self, const char *vmlinux, 1395static int dso__load_kernel_sym(struct dso *self, struct map *map,
911 symbol_filter_t filter, int v, int use_modules) 1396 struct thread *thread, symbol_filter_t filter)
912{ 1397{
913 int err = -1; 1398 int err;
914 1399 bool is_kallsyms;
915 if (vmlinux) { 1400
916 err = dso__load_vmlinux(self, vmlinux, filter, v); 1401 if (vmlinux_path != NULL) {
917 if (err > 0 && use_modules) { 1402 int i;
918 int syms = dso__load_modules(self, filter, v); 1403 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
919 1404 vmlinux_path__nr_entries);
920 if (syms < 0) { 1405 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
921 fprintf(stderr, "dso__load_modules failed!\n"); 1406 err = dso__load_vmlinux(self, map, thread,
922 return syms; 1407 vmlinux_path[i], filter);
1408 if (err > 0) {
1409 pr_debug("Using %s for symbols\n",
1410 vmlinux_path[i]);
1411 dso__set_long_name(self,
1412 strdup(vmlinux_path[i]));
1413 goto out_fixup;
923 } 1414 }
924 err += syms;
925 } 1415 }
926 } 1416 }
927 1417
928 if (err <= 0) 1418 is_kallsyms = self->long_name[0] == '[';
929 err = dso__load_kallsyms(self, filter, v); 1419 if (is_kallsyms)
1420 goto do_kallsyms;
930 1421
931 if (err > 0) 1422 err = dso__load_vmlinux(self, map, thread, self->long_name, filter);
932 self->origin = DSO__ORIG_KERNEL; 1423 if (err <= 0) {
1424 pr_info("The file %s cannot be used, "
1425 "trying to use /proc/kallsyms...", self->long_name);
1426do_kallsyms:
1427 err = dso__load_kallsyms(self, map, thread, filter);
1428 if (err > 0 && !is_kallsyms)
1429 dso__set_long_name(self, strdup("[kernel.kallsyms]"));
1430 }
1431
1432 if (err > 0) {
1433out_fixup:
1434 map__fixup_start(map);
1435 map__fixup_end(map);
1436 }
933 1437
934 return err; 1438 return err;
935} 1439}
936 1440
937LIST_HEAD(dsos); 1441LIST_HEAD(dsos__user);
938struct dso *kernel_dso; 1442LIST_HEAD(dsos__kernel);
939struct dso *vdso; 1443struct dso *vdso;
940struct dso *hypervisor_dso;
941
942const char *vmlinux_name = "vmlinux";
943int modules;
944 1444
945static void dsos__add(struct dso *dso) 1445static void dsos__add(struct list_head *head, struct dso *dso)
946{ 1446{
947 list_add_tail(&dso->node, &dsos); 1447 list_add_tail(&dso->node, head);
948} 1448}
949 1449
950static struct dso *dsos__find(const char *name) 1450static struct dso *dsos__find(struct list_head *head, const char *name)
951{ 1451{
952 struct dso *pos; 1452 struct dso *pos;
953 1453
954 list_for_each_entry(pos, &dsos, node) 1454 list_for_each_entry(pos, head, node)
955 if (strcmp(pos->name, name) == 0) 1455 if (strcmp(pos->name, name) == 0)
956 return pos; 1456 return pos;
957 return NULL; 1457 return NULL;
@@ -959,79 +1459,170 @@ static struct dso *dsos__find(const char *name)
959 1459
960struct dso *dsos__findnew(const char *name) 1460struct dso *dsos__findnew(const char *name)
961{ 1461{
962 struct dso *dso = dsos__find(name); 1462 struct dso *dso = dsos__find(&dsos__user, name);
963 int nr;
964
965 if (dso)
966 return dso;
967
968 dso = dso__new(name, 0);
969 if (!dso)
970 goto out_delete_dso;
971 1463
972 nr = dso__load(dso, NULL, verbose); 1464 if (!dso) {
973 if (nr < 0) { 1465 dso = dso__new(name);
974 eprintf("Failed to open: %s\n", name); 1466 if (dso != NULL) {
975 goto out_delete_dso; 1467 dsos__add(&dsos__user, dso);
1468 dso__set_basename(dso);
1469 }
976 } 1470 }
977 if (!nr)
978 eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
979
980 dsos__add(dso);
981 1471
982 return dso; 1472 return dso;
1473}
983 1474
984out_delete_dso: 1475static void __dsos__fprintf(struct list_head *head, FILE *fp)
985 dso__delete(dso); 1476{
986 return NULL; 1477 struct dso *pos;
1478
1479 list_for_each_entry(pos, head, node) {
1480 int i;
1481 for (i = 0; i < MAP__NR_TYPES; ++i)
1482 dso__fprintf(pos, i, fp);
1483 }
987} 1484}
988 1485
989void dsos__fprintf(FILE *fp) 1486void dsos__fprintf(FILE *fp)
990{ 1487{
1488 __dsos__fprintf(&dsos__kernel, fp);
1489 __dsos__fprintf(&dsos__user, fp);
1490}
1491
1492static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp)
1493{
991 struct dso *pos; 1494 struct dso *pos;
1495 size_t ret = 0;
992 1496
993 list_for_each_entry(pos, &dsos, node) 1497 list_for_each_entry(pos, head, node) {
994 dso__fprintf(pos, fp); 1498 ret += dso__fprintf_buildid(pos, fp);
1499 ret += fprintf(fp, " %s\n", pos->long_name);
1500 }
1501 return ret;
995} 1502}
996 1503
997static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 1504size_t dsos__fprintf_buildid(FILE *fp)
998{ 1505{
999 return dso__find_symbol(dso, ip); 1506 return (__dsos__fprintf_buildid(&dsos__kernel, fp) +
1507 __dsos__fprintf_buildid(&dsos__user, fp));
1000} 1508}
1001 1509
1002int load_kernel(void) 1510static int thread__create_kernel_map(struct thread *self, const char *vmlinux)
1003{ 1511{
1004 int err; 1512 struct map *kmap;
1513 struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]");
1005 1514
1006 kernel_dso = dso__new("[kernel]", 0); 1515 if (kernel == NULL)
1007 if (!kernel_dso)
1008 return -1; 1516 return -1;
1009 1517
1010 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules); 1518 kmap = map__new2(0, kernel, MAP__FUNCTION);
1011 if (err <= 0) { 1519 if (kmap == NULL)
1012 dso__delete(kernel_dso); 1520 goto out_delete_kernel_dso;
1013 kernel_dso = NULL;
1014 } else
1015 dsos__add(kernel_dso);
1016 1521
1017 vdso = dso__new("[vdso]", 0); 1522 kmap->map_ip = kmap->unmap_ip = identity__map_ip;
1018 if (!vdso) 1523 kernel->short_name = "[kernel]";
1019 return -1; 1524 kernel->kernel = 1;
1020 1525
1021 vdso->find_symbol = vdso__find_symbol; 1526 vdso = dso__new("[vdso]");
1527 if (vdso == NULL)
1528 goto out_delete_kernel_map;
1529 dso__set_loaded(vdso, MAP__FUNCTION);
1022 1530
1023 dsos__add(vdso); 1531 if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id,
1532 sizeof(kernel->build_id)) == 0)
1533 kernel->has_build_id = true;
1024 1534
1025 hypervisor_dso = dso__new("[hypervisor]", 0); 1535 __thread__insert_map(self, kmap);
1026 if (!hypervisor_dso) 1536 dsos__add(&dsos__kernel, kernel);
1027 return -1; 1537 dsos__add(&dsos__user, vdso);
1028 dsos__add(hypervisor_dso);
1029 1538
1030 return err; 1539 return 0;
1540
1541out_delete_kernel_map:
1542 map__delete(kmap);
1543out_delete_kernel_dso:
1544 dso__delete(kernel);
1545 return -1;
1546}
1547
1548static void vmlinux_path__exit(void)
1549{
1550 while (--vmlinux_path__nr_entries >= 0) {
1551 free(vmlinux_path[vmlinux_path__nr_entries]);
1552 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1553 }
1554
1555 free(vmlinux_path);
1556 vmlinux_path = NULL;
1031} 1557}
1032 1558
1559static int vmlinux_path__init(void)
1560{
1561 struct utsname uts;
1562 char bf[PATH_MAX];
1563
1564 if (uname(&uts) < 0)
1565 return -1;
1566
1567 vmlinux_path = malloc(sizeof(char *) * 5);
1568 if (vmlinux_path == NULL)
1569 return -1;
1570
1571 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
1572 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1573 goto out_fail;
1574 ++vmlinux_path__nr_entries;
1575 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
1576 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1577 goto out_fail;
1578 ++vmlinux_path__nr_entries;
1579 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
1580 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1581 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1582 goto out_fail;
1583 ++vmlinux_path__nr_entries;
1584 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
1585 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1586 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1587 goto out_fail;
1588 ++vmlinux_path__nr_entries;
1589 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1590 uts.release);
1591 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1592 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1593 goto out_fail;
1594 ++vmlinux_path__nr_entries;
1595
1596 return 0;
1597
1598out_fail:
1599 vmlinux_path__exit();
1600 return -1;
1601}
1033 1602
1034void symbol__init(void) 1603int symbol__init(struct symbol_conf *conf)
1035{ 1604{
1605 const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults;
1606
1036 elf_version(EV_CURRENT); 1607 elf_version(EV_CURRENT);
1608 symbol__priv_size = pconf->priv_size;
1609 thread__init(kthread, 0);
1610
1611 if (pconf->try_vmlinux_path && vmlinux_path__init() < 0)
1612 return -1;
1613
1614 if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) {
1615 vmlinux_path__exit();
1616 return -1;
1617 }
1618
1619 kthread->use_modules = pconf->use_modules;
1620 if (pconf->use_modules && thread__create_module_maps(kthread) < 0)
1621 pr_debug("Failed to load list of modules in use, "
1622 "continuing...\n");
1623 /*
1624 * Now that we have all the maps created, just set the ->end of them:
1625 */
1626 thread__fixup_maps_end(kthread);
1627 return 0;
1037} 1628}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 829da9edba64..17003efa0b39 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -1,11 +1,11 @@
1#ifndef _PERF_SYMBOL_ 1#ifndef __PERF_SYMBOL
2#define _PERF_SYMBOL_ 1 2#define __PERF_SYMBOL 1
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <stdbool.h>
5#include "types.h" 6#include "types.h"
6#include <linux/list.h> 7#include <linux/list.h>
7#include <linux/rbtree.h> 8#include <linux/rbtree.h>
8#include "module.h"
9#include "event.h" 9#include "event.h"
10 10
11#ifdef HAVE_CPLUS_DEMANGLE 11#ifdef HAVE_CPLUS_DEMANGLE
@@ -46,57 +46,75 @@ struct symbol {
46 struct rb_node rb_node; 46 struct rb_node rb_node;
47 u64 start; 47 u64 start;
48 u64 end; 48 u64 end;
49 u64 obj_start;
50 u64 hist_sum;
51 u64 *hist;
52 struct module *module;
53 void *priv;
54 char name[0]; 49 char name[0];
55}; 50};
56 51
52struct symbol_conf {
53 unsigned short priv_size;
54 bool try_vmlinux_path,
55 use_modules;
56 const char *vmlinux_name;
57};
58
59extern unsigned int symbol__priv_size;
60
61static inline void *symbol__priv(struct symbol *self)
62{
63 return ((void *)self) - symbol__priv_size;
64}
65
66struct addr_location {
67 struct thread *thread;
68 struct map *map;
69 struct symbol *sym;
70 u64 addr;
71 char level;
72};
73
57struct dso { 74struct dso {
58 struct list_head node; 75 struct list_head node;
59 struct rb_root syms; 76 struct rb_root symbols[MAP__NR_TYPES];
60 struct symbol *(*find_symbol)(struct dso *, u64 ip); 77 struct symbol *(*find_symbol)(struct dso *self,
61 unsigned int sym_priv_size; 78 enum map_type type, u64 addr);
62 unsigned char adjust_symbols; 79 u8 adjust_symbols:1;
63 unsigned char slen_calculated; 80 u8 slen_calculated:1;
81 u8 has_build_id:1;
82 u8 kernel:1;
64 unsigned char origin; 83 unsigned char origin;
84 u8 loaded;
85 u8 build_id[BUILD_ID_SIZE];
86 u16 long_name_len;
87 const char *short_name;
88 char *long_name;
65 char name[0]; 89 char name[0];
66}; 90};
67 91
68extern const char *sym_hist_filter; 92struct dso *dso__new(const char *name);
69
70typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym);
71
72struct dso *dso__new(const char *name, unsigned int sym_priv_size);
73void dso__delete(struct dso *self); 93void dso__delete(struct dso *self);
74 94
75static inline void *dso__sym_priv(struct dso *self, struct symbol *sym) 95bool dso__loaded(const struct dso *self, enum map_type type);
76{
77 return ((void *)sym) - self->sym_priv_size;
78}
79
80struct symbol *dso__find_symbol(struct dso *self, u64 ip);
81 96
82int dso__load_kernel(struct dso *self, const char *vmlinux,
83 symbol_filter_t filter, int verbose, int modules);
84int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
85int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
86struct dso *dsos__findnew(const char *name); 97struct dso *dsos__findnew(const char *name);
98int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
87void dsos__fprintf(FILE *fp); 99void dsos__fprintf(FILE *fp);
100size_t dsos__fprintf_buildid(FILE *fp);
88 101
89size_t dso__fprintf(struct dso *self, FILE *fp); 102size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
103size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
90char dso__symtab_origin(const struct dso *self); 104char dso__symtab_origin(const struct dso *self);
105void dso__set_build_id(struct dso *self, void *build_id);
106
107int filename__read_build_id(const char *filename, void *bf, size_t size);
108int sysfs__read_build_id(const char *filename, void *bf, size_t size);
109bool dsos__read_build_ids(void);
110int build_id__sprintf(u8 *self, int len, char *bf);
91 111
92int load_kernel(void); 112size_t kernel_maps__fprintf(FILE *fp);
93 113
94void symbol__init(void); 114int symbol__init(struct symbol_conf *conf);
95 115
96extern struct list_head dsos; 116struct thread;
97extern struct dso *kernel_dso; 117struct thread *kthread;
118extern struct list_head dsos__user, dsos__kernel;
98extern struct dso *vdso; 119extern struct dso *vdso;
99extern struct dso *hypervisor_dso; 120#endif /* __PERF_SYMBOL */
100extern const char *vmlinux_name;
101extern int modules;
102#endif /* _PERF_SYMBOL_ */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 45efb5db0d19..603f5610861b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,16 +6,29 @@
6#include "util.h" 6#include "util.h"
7#include "debug.h" 7#include "debug.h"
8 8
9static struct rb_root threads;
10static struct thread *last_match;
11
12void thread__init(struct thread *self, pid_t pid)
13{
14 int i;
15 self->pid = pid;
16 self->comm = NULL;
17 for (i = 0; i < MAP__NR_TYPES; ++i) {
18 self->maps[i] = RB_ROOT;
19 INIT_LIST_HEAD(&self->removed_maps[i]);
20 }
21}
22
9static struct thread *thread__new(pid_t pid) 23static struct thread *thread__new(pid_t pid)
10{ 24{
11 struct thread *self = calloc(1, sizeof(*self)); 25 struct thread *self = zalloc(sizeof(*self));
12 26
13 if (self != NULL) { 27 if (self != NULL) {
14 self->pid = pid; 28 thread__init(self, pid);
15 self->comm = malloc(32); 29 self->comm = malloc(32);
16 if (self->comm) 30 if (self->comm)
17 snprintf(self->comm, 32, ":%d", self->pid); 31 snprintf(self->comm, 32, ":%d", self->pid);
18 INIT_LIST_HEAD(&self->maps);
19 } 32 }
20 33
21 return self; 34 return self;
@@ -29,21 +42,84 @@ int thread__set_comm(struct thread *self, const char *comm)
29 return self->comm ? 0 : -ENOMEM; 42 return self->comm ? 0 : -ENOMEM;
30} 43}
31 44
32static size_t thread__fprintf(struct thread *self, FILE *fp) 45int thread__comm_len(struct thread *self)
46{
47 if (!self->comm_len) {
48 if (!self->comm)
49 return 0;
50 self->comm_len = strlen(self->comm);
51 }
52
53 return self->comm_len;
54}
55
56static const char *map_type__name[MAP__NR_TYPES] = {
57 [MAP__FUNCTION] = "Functions",
58};
59
60static size_t __thread__fprintf_maps(struct thread *self,
61 enum map_type type, FILE *fp)
62{
63 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
64 struct rb_node *nd;
65
66 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
67 struct map *pos = rb_entry(nd, struct map, rb_node);
68 printed += fprintf(fp, "Map:");
69 printed += map__fprintf(pos, fp);
70 if (verbose > 1) {
71 printed += dso__fprintf(pos->dso, type, fp);
72 printed += fprintf(fp, "--\n");
73 }
74 }
75
76 return printed;
77}
78
79size_t thread__fprintf_maps(struct thread *self, FILE *fp)
80{
81 size_t printed = 0, i;
82 for (i = 0; i < MAP__NR_TYPES; ++i)
83 printed += __thread__fprintf_maps(self, i, fp);
84 return printed;
85}
86
87static size_t __thread__fprintf_removed_maps(struct thread *self,
88 enum map_type type, FILE *fp)
33{ 89{
34 struct map *pos; 90 struct map *pos;
35 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 91 size_t printed = 0;
92
93 list_for_each_entry(pos, &self->removed_maps[type], node) {
94 printed += fprintf(fp, "Map:");
95 printed += map__fprintf(pos, fp);
96 if (verbose > 1) {
97 printed += dso__fprintf(pos->dso, type, fp);
98 printed += fprintf(fp, "--\n");
99 }
100 }
101 return printed;
102}
36 103
37 list_for_each_entry(pos, &self->maps, node) 104static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp)
38 ret += map__fprintf(pos, fp); 105{
106 size_t printed = 0, i;
107 for (i = 0; i < MAP__NR_TYPES; ++i)
108 printed += __thread__fprintf_removed_maps(self, i, fp);
109 return printed;
110}
39 111
40 return ret; 112static size_t thread__fprintf(struct thread *self, FILE *fp)
113{
114 size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
115 printed += thread__fprintf_removed_maps(self, fp);
116 printed += fprintf(fp, "Removed maps:\n");
117 return printed + thread__fprintf_removed_maps(self, fp);
41} 118}
42 119
43struct thread * 120struct thread *threads__findnew(pid_t pid)
44threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
45{ 121{
46 struct rb_node **p = &threads->rb_node; 122 struct rb_node **p = &threads.rb_node;
47 struct rb_node *parent = NULL; 123 struct rb_node *parent = NULL;
48 struct thread *th; 124 struct thread *th;
49 125
@@ -52,15 +128,15 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
52 * so most of the time we dont have to look up 128 * so most of the time we dont have to look up
53 * the full rbtree: 129 * the full rbtree:
54 */ 130 */
55 if (*last_match && (*last_match)->pid == pid) 131 if (last_match && last_match->pid == pid)
56 return *last_match; 132 return last_match;
57 133
58 while (*p != NULL) { 134 while (*p != NULL) {
59 parent = *p; 135 parent = *p;
60 th = rb_entry(parent, struct thread, rb_node); 136 th = rb_entry(parent, struct thread, rb_node);
61 137
62 if (th->pid == pid) { 138 if (th->pid == pid) {
63 *last_match = th; 139 last_match = th;
64 return th; 140 return th;
65 } 141 }
66 142
@@ -73,17 +149,16 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
73 th = thread__new(pid); 149 th = thread__new(pid);
74 if (th != NULL) { 150 if (th != NULL) {
75 rb_link_node(&th->rb_node, parent, p); 151 rb_link_node(&th->rb_node, parent, p);
76 rb_insert_color(&th->rb_node, threads); 152 rb_insert_color(&th->rb_node, &threads);
77 *last_match = th; 153 last_match = th;
78 } 154 }
79 155
80 return th; 156 return th;
81} 157}
82 158
83struct thread * 159struct thread *register_idle_thread(void)
84register_idle_thread(struct rb_root *threads, struct thread **last_match)
85{ 160{
86 struct thread *thread = threads__findnew(0, threads, last_match); 161 struct thread *thread = threads__findnew(0);
87 162
88 if (!thread || thread__set_comm(thread, "swapper")) { 163 if (!thread || thread__set_comm(thread, "swapper")) {
89 fprintf(stderr, "problem inserting idle task.\n"); 164 fprintf(stderr, "problem inserting idle task.\n");
@@ -93,79 +168,116 @@ register_idle_thread(struct rb_root *threads, struct thread **last_match)
93 return thread; 168 return thread;
94} 169}
95 170
96void thread__insert_map(struct thread *self, struct map *map) 171static void thread__remove_overlappings(struct thread *self, struct map *map)
97{ 172{
98 struct map *pos, *tmp; 173 struct rb_root *root = &self->maps[map->type];
174 struct rb_node *next = rb_first(root);
99 175
100 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 176 while (next) {
101 if (map__overlap(pos, map)) { 177 struct map *pos = rb_entry(next, struct map, rb_node);
102 if (verbose >= 2) { 178 next = rb_next(&pos->rb_node);
103 printf("overlapping maps:\n");
104 map__fprintf(map, stdout);
105 map__fprintf(pos, stdout);
106 }
107 179
108 if (map->start <= pos->start && map->end > pos->start) 180 if (!map__overlap(pos, map))
109 pos->start = map->end; 181 continue;
110 182
111 if (map->end >= pos->end && map->start < pos->end) 183 if (verbose >= 2) {
112 pos->end = map->start; 184 fputs("overlapping maps:\n", stderr);
185 map__fprintf(map, stderr);
186 map__fprintf(pos, stderr);
187 }
113 188
114 if (verbose >= 2) { 189 rb_erase(&pos->rb_node, root);
115 printf("after collision:\n"); 190 /*
116 map__fprintf(pos, stdout); 191 * We may have references to this map, for instance in some
117 } 192 * hist_entry instances, so just move them to a separate
193 * list.
194 */
195 list_add_tail(&pos->node, &self->removed_maps[map->type]);
196 }
197}
118 198
119 if (pos->start >= pos->end) { 199void maps__insert(struct rb_root *maps, struct map *map)
120 list_del_init(&pos->node); 200{
121 free(pos); 201 struct rb_node **p = &maps->rb_node;
122 } 202 struct rb_node *parent = NULL;
123 } 203 const u64 ip = map->start;
204 struct map *m;
205
206 while (*p != NULL) {
207 parent = *p;
208 m = rb_entry(parent, struct map, rb_node);
209 if (ip < m->start)
210 p = &(*p)->rb_left;
211 else
212 p = &(*p)->rb_right;
124 } 213 }
125 214
126 list_add_tail(&map->node, &self->maps); 215 rb_link_node(&map->rb_node, parent, p);
216 rb_insert_color(&map->rb_node, maps);
127} 217}
128 218
129int thread__fork(struct thread *self, struct thread *parent) 219struct map *maps__find(struct rb_root *maps, u64 ip)
130{ 220{
131 struct map *map; 221 struct rb_node **p = &maps->rb_node;
222 struct rb_node *parent = NULL;
223 struct map *m;
132 224
133 if (self->comm) 225 while (*p != NULL) {
134 free(self->comm); 226 parent = *p;
135 self->comm = strdup(parent->comm); 227 m = rb_entry(parent, struct map, rb_node);
136 if (!self->comm) 228 if (ip < m->start)
137 return -ENOMEM; 229 p = &(*p)->rb_left;
230 else if (ip > m->end)
231 p = &(*p)->rb_right;
232 else
233 return m;
234 }
235
236 return NULL;
237}
238
239void thread__insert_map(struct thread *self, struct map *map)
240{
241 thread__remove_overlappings(self, map);
242 maps__insert(&self->maps[map->type], map);
243}
138 244
139 list_for_each_entry(map, &parent->maps, node) { 245static int thread__clone_maps(struct thread *self, struct thread *parent,
246 enum map_type type)
247{
248 struct rb_node *nd;
249 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
250 struct map *map = rb_entry(nd, struct map, rb_node);
140 struct map *new = map__clone(map); 251 struct map *new = map__clone(map);
141 if (!new) 252 if (new == NULL)
142 return -ENOMEM; 253 return -ENOMEM;
143 thread__insert_map(self, new); 254 thread__insert_map(self, new);
144 } 255 }
145
146 return 0; 256 return 0;
147} 257}
148 258
149struct map *thread__find_map(struct thread *self, u64 ip) 259int thread__fork(struct thread *self, struct thread *parent)
150{ 260{
151 struct map *pos; 261 int i;
152 262
153 if (self == NULL) 263 if (self->comm)
154 return NULL; 264 free(self->comm);
155 265 self->comm = strdup(parent->comm);
156 list_for_each_entry(pos, &self->maps, node) 266 if (!self->comm)
157 if (ip >= pos->start && ip <= pos->end) 267 return -ENOMEM;
158 return pos;
159 268
160 return NULL; 269 for (i = 0; i < MAP__NR_TYPES; ++i)
270 if (thread__clone_maps(self, parent, i) < 0)
271 return -ENOMEM;
272 return 0;
161} 273}
162 274
163size_t threads__fprintf(FILE *fp, struct rb_root *threads) 275size_t threads__fprintf(FILE *fp)
164{ 276{
165 size_t ret = 0; 277 size_t ret = 0;
166 struct rb_node *nd; 278 struct rb_node *nd;
167 279
168 for (nd = rb_first(threads); nd; nd = rb_next(nd)) { 280 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
169 struct thread *pos = rb_entry(nd, struct thread, rb_node); 281 struct thread *pos = rb_entry(nd, struct thread, rb_node);
170 282
171 ret += thread__fprintf(pos, fp); 283 ret += thread__fprintf(pos, fp);
@@ -173,3 +285,15 @@ size_t threads__fprintf(FILE *fp, struct rb_root *threads)
173 285
174 return ret; 286 return ret;
175} 287}
288
289struct symbol *thread__find_symbol(struct thread *self,
290 enum map_type type, u64 addr,
291 symbol_filter_t filter)
292{
293 struct map *map = thread__find_map(self, type, addr);
294
295 if (map != NULL)
296 return map__find_symbol(map, map->map_ip(map, addr), filter);
297
298 return NULL;
299}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 32aea3c1c2ad..686d6e914d9e 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,22 +1,56 @@
1#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H
3
1#include <linux/rbtree.h> 4#include <linux/rbtree.h>
2#include <linux/list.h>
3#include <unistd.h> 5#include <unistd.h>
4#include "symbol.h" 6#include "symbol.h"
5 7
6struct thread { 8struct thread {
7 struct rb_node rb_node; 9 struct rb_node rb_node;
8 struct list_head maps; 10 struct rb_root maps[MAP__NR_TYPES];
11 struct list_head removed_maps[MAP__NR_TYPES];
9 pid_t pid; 12 pid_t pid;
13 bool use_modules;
10 char shortname[3]; 14 char shortname[3];
11 char *comm; 15 char *comm;
16 int comm_len;
12}; 17};
13 18
19void thread__init(struct thread *self, pid_t pid);
14int thread__set_comm(struct thread *self, const char *comm); 20int thread__set_comm(struct thread *self, const char *comm);
15struct thread * 21int thread__comm_len(struct thread *self);
16threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match); 22struct thread *threads__findnew(pid_t pid);
17struct thread * 23struct thread *register_idle_thread(void);
18register_idle_thread(struct rb_root *threads, struct thread **last_match);
19void thread__insert_map(struct thread *self, struct map *map); 24void thread__insert_map(struct thread *self, struct map *map);
20int thread__fork(struct thread *self, struct thread *parent); 25int thread__fork(struct thread *self, struct thread *parent);
21struct map *thread__find_map(struct thread *self, u64 ip); 26size_t thread__fprintf_maps(struct thread *self, FILE *fp);
22size_t threads__fprintf(FILE *fp, struct rb_root *threads); 27size_t threads__fprintf(FILE *fp);
28
29void maps__insert(struct rb_root *maps, struct map *map);
30struct map *maps__find(struct rb_root *maps, u64 addr);
31
32static inline struct map *thread__find_map(struct thread *self,
33 enum map_type type, u64 addr)
34{
35 return self ? maps__find(&self->maps[type], addr) : NULL;
36}
37
38static inline void __thread__insert_map(struct thread *self, struct map *map)
39{
40 maps__insert(&self->maps[map->type], map);
41}
42
43void thread__find_addr_location(struct thread *self, u8 cpumode,
44 enum map_type type, u64 addr,
45 struct addr_location *al,
46 symbol_filter_t filter);
47struct symbol *thread__find_symbol(struct thread *self,
48 enum map_type type, u64 addr,
49 symbol_filter_t filter);
50
51static inline struct symbol *
52thread__find_function(struct thread *self, u64 addr, symbol_filter_t filter)
53{
54 return thread__find_symbol(self, MAP__FUNCTION, addr, filter);
55}
56#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index af4b0573b37f..cace35595530 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -33,11 +33,11 @@
33#include <ctype.h> 33#include <ctype.h>
34#include <errno.h> 34#include <errno.h>
35#include <stdbool.h> 35#include <stdbool.h>
36#include <linux/kernel.h>
36 37
37#include "../perf.h" 38#include "../perf.h"
38#include "trace-event.h" 39#include "trace-event.h"
39 40
40
41#define VERSION "0.5" 41#define VERSION "0.5"
42 42
43#define _STR(x) #x 43#define _STR(x) #x
@@ -483,27 +483,33 @@ static struct tracepoint_path *
483get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) 483get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
484{ 484{
485 struct tracepoint_path path, *ppath = &path; 485 struct tracepoint_path path, *ppath = &path;
486 int i; 486 int i, nr_tracepoints = 0;
487 487
488 for (i = 0; i < nb_events; i++) { 488 for (i = 0; i < nb_events; i++) {
489 if (pattrs[i].type != PERF_TYPE_TRACEPOINT) 489 if (pattrs[i].type != PERF_TYPE_TRACEPOINT)
490 continue; 490 continue;
491 ++nr_tracepoints;
491 ppath->next = tracepoint_id_to_path(pattrs[i].config); 492 ppath->next = tracepoint_id_to_path(pattrs[i].config);
492 if (!ppath->next) 493 if (!ppath->next)
493 die("%s\n", "No memory to alloc tracepoints list"); 494 die("%s\n", "No memory to alloc tracepoints list");
494 ppath = ppath->next; 495 ppath = ppath->next;
495 } 496 }
496 497
497 return path.next; 498 return nr_tracepoints > 0 ? path.next : NULL;
498} 499}
499void read_tracing_data(struct perf_event_attr *pattrs, int nb_events) 500
501int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
500{ 502{
501 char buf[BUFSIZ]; 503 char buf[BUFSIZ];
502 struct tracepoint_path *tps; 504 struct tracepoint_path *tps = get_tracepoints_path(pattrs, nb_events);
505
506 /*
507 * What? No tracepoints? No sense writing anything here, bail out.
508 */
509 if (tps == NULL)
510 return -1;
503 511
504 output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644); 512 output_fd = fd;
505 if (output_fd < 0)
506 die("creating file '%s'", output_file);
507 513
508 buf[0] = 23; 514 buf[0] = 23;
509 buf[1] = 8; 515 buf[1] = 8;
@@ -530,11 +536,11 @@ void read_tracing_data(struct perf_event_attr *pattrs, int nb_events)
530 page_size = getpagesize(); 536 page_size = getpagesize();
531 write_or_die(&page_size, 4); 537 write_or_die(&page_size, 4);
532 538
533 tps = get_tracepoints_path(pattrs, nb_events);
534
535 read_header_files(); 539 read_header_files();
536 read_ftrace_files(tps); 540 read_ftrace_files(tps);
537 read_event_files(tps); 541 read_event_files(tps);
538 read_proc_kallsyms(); 542 read_proc_kallsyms();
539 read_ftrace_printk(); 543 read_ftrace_printk();
544
545 return 0;
540} 546}
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 55c9659a56e2..0302405aa2ca 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -40,12 +40,19 @@ int header_page_size_size;
40int header_page_data_offset; 40int header_page_data_offset;
41int header_page_data_size; 41int header_page_data_size;
42 42
43int latency_format;
44
43static char *input_buf; 45static char *input_buf;
44static unsigned long long input_buf_ptr; 46static unsigned long long input_buf_ptr;
45static unsigned long long input_buf_siz; 47static unsigned long long input_buf_siz;
46 48
47static int cpus; 49static int cpus;
48static int long_size; 50static int long_size;
51static int is_flag_field;
52static int is_symbolic_field;
53
54static struct format_field *
55find_any_field(struct event *event, const char *name);
49 56
50static void init_input_buf(char *buf, unsigned long long size) 57static void init_input_buf(char *buf, unsigned long long size)
51{ 58{
@@ -284,18 +291,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
284 char *line; 291 char *line;
285 char *next = NULL; 292 char *next = NULL;
286 char *addr_str; 293 char *addr_str;
287 int ret;
288 int i; 294 int i;
289 295
290 line = strtok_r(file, "\n", &next); 296 line = strtok_r(file, "\n", &next);
291 while (line) { 297 while (line) {
298 addr_str = strsep(&line, ":");
299 if (!line) {
300 warning("error parsing print strings");
301 break;
302 }
292 item = malloc_or_die(sizeof(*item)); 303 item = malloc_or_die(sizeof(*item));
293 ret = sscanf(line, "%as : %as",
294 (float *)(void *)&addr_str, /* workaround gcc warning */
295 (float *)(void *)&item->printk);
296 item->addr = strtoull(addr_str, NULL, 16); 304 item->addr = strtoull(addr_str, NULL, 16);
297 free(addr_str); 305 /* fmt still has a space, skip it */
298 306 item->printk = strdup(line+1);
299 item->next = list; 307 item->next = list;
300 list = item; 308 list = item;
301 line = strtok_r(NULL, "\n", &next); 309 line = strtok_r(NULL, "\n", &next);
@@ -522,7 +530,10 @@ static enum event_type __read_token(char **tok)
522 last_ch = ch; 530 last_ch = ch;
523 ch = __read_char(); 531 ch = __read_char();
524 buf[i++] = ch; 532 buf[i++] = ch;
525 } while (ch != quote_ch && last_ch != '\\'); 533 /* the '\' '\' will cancel itself */
534 if (ch == '\\' && last_ch == '\\')
535 last_ch = 0;
536 } while (ch != quote_ch || last_ch == '\\');
526 /* remove the last quote */ 537 /* remove the last quote */
527 i--; 538 i--;
528 goto out; 539 goto out;
@@ -610,7 +621,7 @@ static enum event_type read_token_item(char **tok)
610static int test_type(enum event_type type, enum event_type expect) 621static int test_type(enum event_type type, enum event_type expect)
611{ 622{
612 if (type != expect) { 623 if (type != expect) {
613 die("Error: expected type %d but read %d", 624 warning("Error: expected type %d but read %d",
614 expect, type); 625 expect, type);
615 return -1; 626 return -1;
616 } 627 }
@@ -621,13 +632,13 @@ static int test_type_token(enum event_type type, char *token,
621 enum event_type expect, const char *expect_tok) 632 enum event_type expect, const char *expect_tok)
622{ 633{
623 if (type != expect) { 634 if (type != expect) {
624 die("Error: expected type %d but read %d", 635 warning("Error: expected type %d but read %d",
625 expect, type); 636 expect, type);
626 return -1; 637 return -1;
627 } 638 }
628 639
629 if (strcmp(token, expect_tok) != 0) { 640 if (strcmp(token, expect_tok) != 0) {
630 die("Error: expected '%s' but read '%s'", 641 warning("Error: expected '%s' but read '%s'",
631 expect_tok, token); 642 expect_tok, token);
632 return -1; 643 return -1;
633 } 644 }
@@ -665,7 +676,7 @@ static int __read_expected(enum event_type expect, const char *str, int newline_
665 676
666 free_token(token); 677 free_token(token);
667 678
668 return 0; 679 return ret;
669} 680}
670 681
671static int read_expected(enum event_type expect, const char *str) 682static int read_expected(enum event_type expect, const char *str)
@@ -682,10 +693,10 @@ static char *event_read_name(void)
682{ 693{
683 char *token; 694 char *token;
684 695
685 if (read_expected(EVENT_ITEM, (char *)"name") < 0) 696 if (read_expected(EVENT_ITEM, "name") < 0)
686 return NULL; 697 return NULL;
687 698
688 if (read_expected(EVENT_OP, (char *)":") < 0) 699 if (read_expected(EVENT_OP, ":") < 0)
689 return NULL; 700 return NULL;
690 701
691 if (read_expect_type(EVENT_ITEM, &token) < 0) 702 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -703,10 +714,10 @@ static int event_read_id(void)
703 char *token; 714 char *token;
704 int id; 715 int id;
705 716
706 if (read_expected_item(EVENT_ITEM, (char *)"ID") < 0) 717 if (read_expected_item(EVENT_ITEM, "ID") < 0)
707 return -1; 718 return -1;
708 719
709 if (read_expected(EVENT_OP, (char *)":") < 0) 720 if (read_expected(EVENT_OP, ":") < 0)
710 return -1; 721 return -1;
711 722
712 if (read_expect_type(EVENT_ITEM, &token) < 0) 723 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -721,6 +732,24 @@ static int event_read_id(void)
721 return -1; 732 return -1;
722} 733}
723 734
735static int field_is_string(struct format_field *field)
736{
737 if ((field->flags & FIELD_IS_ARRAY) &&
738 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
739 !strstr(field->type, "s8")))
740 return 1;
741
742 return 0;
743}
744
745static int field_is_dynamic(struct format_field *field)
746{
747 if (!strcmp(field->type, "__data_loc"))
748 return 1;
749
750 return 0;
751}
752
724static int event_read_fields(struct event *event, struct format_field **fields) 753static int event_read_fields(struct event *event, struct format_field **fields)
725{ 754{
726 struct format_field *field = NULL; 755 struct format_field *field = NULL;
@@ -738,7 +767,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
738 767
739 count++; 768 count++;
740 769
741 if (test_type_token(type, token, EVENT_ITEM, (char *)"field")) 770 if (test_type_token(type, token, EVENT_ITEM, "field"))
742 goto fail; 771 goto fail;
743 free_token(token); 772 free_token(token);
744 773
@@ -753,7 +782,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
753 type = read_token(&token); 782 type = read_token(&token);
754 } 783 }
755 784
756 if (test_type_token(type, token, EVENT_OP, (char *)":") < 0) 785 if (test_type_token(type, token, EVENT_OP, ":") < 0)
757 return -1; 786 return -1;
758 787
759 if (read_expect_type(EVENT_ITEM, &token) < 0) 788 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -865,14 +894,20 @@ static int event_read_fields(struct event *event, struct format_field **fields)
865 free(brackets); 894 free(brackets);
866 } 895 }
867 896
868 if (test_type_token(type, token, EVENT_OP, (char *)";")) 897 if (field_is_string(field)) {
898 field->flags |= FIELD_IS_STRING;
899 if (field_is_dynamic(field))
900 field->flags |= FIELD_IS_DYNAMIC;
901 }
902
903 if (test_type_token(type, token, EVENT_OP, ";"))
869 goto fail; 904 goto fail;
870 free_token(token); 905 free_token(token);
871 906
872 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 907 if (read_expected(EVENT_ITEM, "offset") < 0)
873 goto fail_expect; 908 goto fail_expect;
874 909
875 if (read_expected(EVENT_OP, (char *)":") < 0) 910 if (read_expected(EVENT_OP, ":") < 0)
876 goto fail_expect; 911 goto fail_expect;
877 912
878 if (read_expect_type(EVENT_ITEM, &token)) 913 if (read_expect_type(EVENT_ITEM, &token))
@@ -880,13 +915,13 @@ static int event_read_fields(struct event *event, struct format_field **fields)
880 field->offset = strtoul(token, NULL, 0); 915 field->offset = strtoul(token, NULL, 0);
881 free_token(token); 916 free_token(token);
882 917
883 if (read_expected(EVENT_OP, (char *)";") < 0) 918 if (read_expected(EVENT_OP, ";") < 0)
884 goto fail_expect; 919 goto fail_expect;
885 920
886 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 921 if (read_expected(EVENT_ITEM, "size") < 0)
887 goto fail_expect; 922 goto fail_expect;
888 923
889 if (read_expected(EVENT_OP, (char *)":") < 0) 924 if (read_expected(EVENT_OP, ":") < 0)
890 goto fail_expect; 925 goto fail_expect;
891 926
892 if (read_expect_type(EVENT_ITEM, &token)) 927 if (read_expect_type(EVENT_ITEM, &token))
@@ -894,11 +929,34 @@ static int event_read_fields(struct event *event, struct format_field **fields)
894 field->size = strtoul(token, NULL, 0); 929 field->size = strtoul(token, NULL, 0);
895 free_token(token); 930 free_token(token);
896 931
897 if (read_expected(EVENT_OP, (char *)";") < 0) 932 if (read_expected(EVENT_OP, ";") < 0)
898 goto fail_expect; 933 goto fail_expect;
899 934
900 if (read_expect_type(EVENT_NEWLINE, &token) < 0) 935 type = read_token(&token);
901 goto fail; 936 if (type != EVENT_NEWLINE) {
937 /* newer versions of the kernel have a "signed" type */
938 if (test_type_token(type, token, EVENT_ITEM, "signed"))
939 goto fail;
940
941 free_token(token);
942
943 if (read_expected(EVENT_OP, ":") < 0)
944 goto fail_expect;
945
946 if (read_expect_type(EVENT_ITEM, &token))
947 goto fail;
948
949 if (strtoul(token, NULL, 0))
950 field->flags |= FIELD_IS_SIGNED;
951
952 free_token(token);
953 if (read_expected(EVENT_OP, ";") < 0)
954 goto fail_expect;
955
956 if (read_expect_type(EVENT_NEWLINE, &token))
957 goto fail;
958 }
959
902 free_token(token); 960 free_token(token);
903 961
904 *fields = field; 962 *fields = field;
@@ -921,10 +979,10 @@ static int event_read_format(struct event *event)
921 char *token; 979 char *token;
922 int ret; 980 int ret;
923 981
924 if (read_expected_item(EVENT_ITEM, (char *)"format") < 0) 982 if (read_expected_item(EVENT_ITEM, "format") < 0)
925 return -1; 983 return -1;
926 984
927 if (read_expected(EVENT_OP, (char *)":") < 0) 985 if (read_expected(EVENT_OP, ":") < 0)
928 return -1; 986 return -1;
929 987
930 if (read_expect_type(EVENT_NEWLINE, &token)) 988 if (read_expect_type(EVENT_NEWLINE, &token))
@@ -984,7 +1042,7 @@ process_cond(struct event *event, struct print_arg *top, char **tok)
984 1042
985 *tok = NULL; 1043 *tok = NULL;
986 type = process_arg(event, left, &token); 1044 type = process_arg(event, left, &token);
987 if (test_type_token(type, token, EVENT_OP, (char *)":")) 1045 if (test_type_token(type, token, EVENT_OP, ":"))
988 goto out_free; 1046 goto out_free;
989 1047
990 arg->op.op = token; 1048 arg->op.op = token;
@@ -1004,6 +1062,35 @@ out_free:
1004 return EVENT_ERROR; 1062 return EVENT_ERROR;
1005} 1063}
1006 1064
1065static enum event_type
1066process_array(struct event *event, struct print_arg *top, char **tok)
1067{
1068 struct print_arg *arg;
1069 enum event_type type;
1070 char *token = NULL;
1071
1072 arg = malloc_or_die(sizeof(*arg));
1073 memset(arg, 0, sizeof(*arg));
1074
1075 *tok = NULL;
1076 type = process_arg(event, arg, &token);
1077 if (test_type_token(type, token, EVENT_OP, "]"))
1078 goto out_free;
1079
1080 top->op.right = arg;
1081
1082 free_token(token);
1083 type = read_token_item(&token);
1084 *tok = token;
1085
1086 return type;
1087
1088out_free:
1089 free_token(*tok);
1090 free_arg(arg);
1091 return EVENT_ERROR;
1092}
1093
1007static int get_op_prio(char *op) 1094static int get_op_prio(char *op)
1008{ 1095{
1009 if (!op[1]) { 1096 if (!op[1]) {
@@ -1128,6 +1215,8 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1128 strcmp(token, "*") == 0 || 1215 strcmp(token, "*") == 0 ||
1129 strcmp(token, "^") == 0 || 1216 strcmp(token, "^") == 0 ||
1130 strcmp(token, "/") == 0 || 1217 strcmp(token, "/") == 0 ||
1218 strcmp(token, "<") == 0 ||
1219 strcmp(token, ">") == 0 ||
1131 strcmp(token, "==") == 0 || 1220 strcmp(token, "==") == 0 ||
1132 strcmp(token, "!=") == 0) { 1221 strcmp(token, "!=") == 0) {
1133 1222
@@ -1144,17 +1233,46 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1144 1233
1145 right = malloc_or_die(sizeof(*right)); 1234 right = malloc_or_die(sizeof(*right));
1146 1235
1147 type = process_arg(event, right, tok); 1236 type = read_token_item(&token);
1237 *tok = token;
1238
1239 /* could just be a type pointer */
1240 if ((strcmp(arg->op.op, "*") == 0) &&
1241 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1242 if (left->type != PRINT_ATOM)
1243 die("bad pointer type");
1244 left->atom.atom = realloc(left->atom.atom,
1245 sizeof(left->atom.atom) + 3);
1246 strcat(left->atom.atom, " *");
1247 *arg = *left;
1248 free(arg);
1249
1250 return type;
1251 }
1252
1253 type = process_arg_token(event, right, tok, type);
1148 1254
1149 arg->op.right = right; 1255 arg->op.right = right;
1150 1256
1257 } else if (strcmp(token, "[") == 0) {
1258
1259 left = malloc_or_die(sizeof(*left));
1260 *left = *arg;
1261
1262 arg->type = PRINT_OP;
1263 arg->op.op = token;
1264 arg->op.left = left;
1265
1266 arg->op.prio = 0;
1267 type = process_array(event, arg, tok);
1268
1151 } else { 1269 } else {
1152 die("unknown op '%s'", token); 1270 warning("unknown op '%s'", token);
1271 event->flags |= EVENT_FL_FAILED;
1153 /* the arg is now the left side */ 1272 /* the arg is now the left side */
1154 return EVENT_NONE; 1273 return EVENT_NONE;
1155 } 1274 }
1156 1275
1157
1158 if (type == EVENT_OP) { 1276 if (type == EVENT_OP) {
1159 int prio; 1277 int prio;
1160 1278
@@ -1178,7 +1296,7 @@ process_entry(struct event *event __unused, struct print_arg *arg,
1178 char *field; 1296 char *field;
1179 char *token; 1297 char *token;
1180 1298
1181 if (read_expected(EVENT_OP, (char *)"->") < 0) 1299 if (read_expected(EVENT_OP, "->") < 0)
1182 return EVENT_ERROR; 1300 return EVENT_ERROR;
1183 1301
1184 if (read_expect_type(EVENT_ITEM, &token) < 0) 1302 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1188,6 +1306,16 @@ process_entry(struct event *event __unused, struct print_arg *arg,
1188 arg->type = PRINT_FIELD; 1306 arg->type = PRINT_FIELD;
1189 arg->field.name = field; 1307 arg->field.name = field;
1190 1308
1309 if (is_flag_field) {
1310 arg->field.field = find_any_field(event, arg->field.name);
1311 arg->field.field->flags |= FIELD_IS_FLAG;
1312 is_flag_field = 0;
1313 } else if (is_symbolic_field) {
1314 arg->field.field = find_any_field(event, arg->field.name);
1315 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1316 is_symbolic_field = 0;
1317 }
1318
1191 type = read_token(&token); 1319 type = read_token(&token);
1192 *tok = token; 1320 *tok = token;
1193 1321
@@ -1338,14 +1466,14 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1338 do { 1466 do {
1339 free_token(token); 1467 free_token(token);
1340 type = read_token_item(&token); 1468 type = read_token_item(&token);
1341 if (test_type_token(type, token, EVENT_OP, (char *)"{")) 1469 if (test_type_token(type, token, EVENT_OP, "{"))
1342 break; 1470 break;
1343 1471
1344 arg = malloc_or_die(sizeof(*arg)); 1472 arg = malloc_or_die(sizeof(*arg));
1345 1473
1346 free_token(token); 1474 free_token(token);
1347 type = process_arg(event, arg, &token); 1475 type = process_arg(event, arg, &token);
1348 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1476 if (test_type_token(type, token, EVENT_DELIM, ","))
1349 goto out_free; 1477 goto out_free;
1350 1478
1351 field = malloc_or_die(sizeof(*field)); 1479 field = malloc_or_die(sizeof(*field));
@@ -1356,7 +1484,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1356 1484
1357 free_token(token); 1485 free_token(token);
1358 type = process_arg(event, arg, &token); 1486 type = process_arg(event, arg, &token);
1359 if (test_type_token(type, token, EVENT_OP, (char *)"}")) 1487 if (test_type_token(type, token, EVENT_OP, "}"))
1360 goto out_free; 1488 goto out_free;
1361 1489
1362 value = arg_eval(arg); 1490 value = arg_eval(arg);
@@ -1391,13 +1519,13 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1391 memset(arg, 0, sizeof(*arg)); 1519 memset(arg, 0, sizeof(*arg));
1392 arg->type = PRINT_FLAGS; 1520 arg->type = PRINT_FLAGS;
1393 1521
1394 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1522 if (read_expected_item(EVENT_DELIM, "(") < 0)
1395 return EVENT_ERROR; 1523 return EVENT_ERROR;
1396 1524
1397 field = malloc_or_die(sizeof(*field)); 1525 field = malloc_or_die(sizeof(*field));
1398 1526
1399 type = process_arg(event, field, &token); 1527 type = process_arg(event, field, &token);
1400 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1528 if (test_type_token(type, token, EVENT_DELIM, ","))
1401 goto out_free; 1529 goto out_free;
1402 1530
1403 arg->flags.field = field; 1531 arg->flags.field = field;
@@ -1408,11 +1536,11 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1408 type = read_token_item(&token); 1536 type = read_token_item(&token);
1409 } 1537 }
1410 1538
1411 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1539 if (test_type_token(type, token, EVENT_DELIM, ","))
1412 goto out_free; 1540 goto out_free;
1413 1541
1414 type = process_fields(event, &arg->flags.flags, &token); 1542 type = process_fields(event, &arg->flags.flags, &token);
1415 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1543 if (test_type_token(type, token, EVENT_DELIM, ")"))
1416 goto out_free; 1544 goto out_free;
1417 1545
1418 free_token(token); 1546 free_token(token);
@@ -1434,19 +1562,19 @@ process_symbols(struct event *event, struct print_arg *arg, char **tok)
1434 memset(arg, 0, sizeof(*arg)); 1562 memset(arg, 0, sizeof(*arg));
1435 arg->type = PRINT_SYMBOL; 1563 arg->type = PRINT_SYMBOL;
1436 1564
1437 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1565 if (read_expected_item(EVENT_DELIM, "(") < 0)
1438 return EVENT_ERROR; 1566 return EVENT_ERROR;
1439 1567
1440 field = malloc_or_die(sizeof(*field)); 1568 field = malloc_or_die(sizeof(*field));
1441 1569
1442 type = process_arg(event, field, &token); 1570 type = process_arg(event, field, &token);
1443 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1571 if (test_type_token(type, token, EVENT_DELIM, ","))
1444 goto out_free; 1572 goto out_free;
1445 1573
1446 arg->symbol.field = field; 1574 arg->symbol.field = field;
1447 1575
1448 type = process_fields(event, &arg->symbol.symbols, &token); 1576 type = process_fields(event, &arg->symbol.symbols, &token);
1449 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1577 if (test_type_token(type, token, EVENT_DELIM, ")"))
1450 goto out_free; 1578 goto out_free;
1451 1579
1452 free_token(token); 1580 free_token(token);
@@ -1463,7 +1591,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1463{ 1591{
1464 struct print_arg *item_arg; 1592 struct print_arg *item_arg;
1465 enum event_type type; 1593 enum event_type type;
1466 int ptr_cast = 0;
1467 char *token; 1594 char *token;
1468 1595
1469 type = process_arg(event, arg, &token); 1596 type = process_arg(event, arg, &token);
@@ -1471,28 +1598,13 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1471 if (type == EVENT_ERROR) 1598 if (type == EVENT_ERROR)
1472 return EVENT_ERROR; 1599 return EVENT_ERROR;
1473 1600
1474 if (type == EVENT_OP) { 1601 if (type == EVENT_OP)
1475 /* handle the ptr casts */ 1602 type = process_op(event, arg, &token);
1476 if (!strcmp(token, "*")) {
1477 /*
1478 * FIXME: should we zapp whitespaces before ')' ?
1479 * (may require a peek_token_item())
1480 */
1481 if (__peek_char() == ')') {
1482 ptr_cast = 1;
1483 free_token(token);
1484 type = read_token_item(&token);
1485 }
1486 }
1487 if (!ptr_cast) {
1488 type = process_op(event, arg, &token);
1489 1603
1490 if (type == EVENT_ERROR) 1604 if (type == EVENT_ERROR)
1491 return EVENT_ERROR; 1605 return EVENT_ERROR;
1492 }
1493 }
1494 1606
1495 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) { 1607 if (test_type_token(type, token, EVENT_DELIM, ")")) {
1496 free_token(token); 1608 free_token(token);
1497 return EVENT_ERROR; 1609 return EVENT_ERROR;
1498 } 1610 }
@@ -1516,13 +1628,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1516 item_arg = malloc_or_die(sizeof(*item_arg)); 1628 item_arg = malloc_or_die(sizeof(*item_arg));
1517 1629
1518 arg->type = PRINT_TYPE; 1630 arg->type = PRINT_TYPE;
1519 if (ptr_cast) {
1520 char *old = arg->atom.atom;
1521
1522 arg->atom.atom = malloc_or_die(strlen(old + 3));
1523 sprintf(arg->atom.atom, "%s *", old);
1524 free(old);
1525 }
1526 arg->typecast.type = arg->atom.atom; 1631 arg->typecast.type = arg->atom.atom;
1527 arg->typecast.item = item_arg; 1632 arg->typecast.item = item_arg;
1528 type = process_arg_token(event, item_arg, &token, type); 1633 type = process_arg_token(event, item_arg, &token, type);
@@ -1540,7 +1645,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1540 enum event_type type; 1645 enum event_type type;
1541 char *token; 1646 char *token;
1542 1647
1543 if (read_expected(EVENT_DELIM, (char *)"(") < 0) 1648 if (read_expected(EVENT_DELIM, "(") < 0)
1544 return EVENT_ERROR; 1649 return EVENT_ERROR;
1545 1650
1546 if (read_expect_type(EVENT_ITEM, &token) < 0) 1651 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1550,7 +1655,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1550 arg->string.string = token; 1655 arg->string.string = token;
1551 arg->string.offset = -1; 1656 arg->string.offset = -1;
1552 1657
1553 if (read_expected(EVENT_DELIM, (char *)")") < 0) 1658 if (read_expected(EVENT_DELIM, ")") < 0)
1554 return EVENT_ERROR; 1659 return EVENT_ERROR;
1555 1660
1556 type = read_token(&token); 1661 type = read_token(&token);
@@ -1578,9 +1683,11 @@ process_arg_token(struct event *event, struct print_arg *arg,
1578 type = process_entry(event, arg, &token); 1683 type = process_entry(event, arg, &token);
1579 } else if (strcmp(token, "__print_flags") == 0) { 1684 } else if (strcmp(token, "__print_flags") == 0) {
1580 free_token(token); 1685 free_token(token);
1686 is_flag_field = 1;
1581 type = process_flags(event, arg, &token); 1687 type = process_flags(event, arg, &token);
1582 } else if (strcmp(token, "__print_symbolic") == 0) { 1688 } else if (strcmp(token, "__print_symbolic") == 0) {
1583 free_token(token); 1689 free_token(token);
1690 is_symbolic_field = 1;
1584 type = process_symbols(event, arg, &token); 1691 type = process_symbols(event, arg, &token);
1585 } else if (strcmp(token, "__get_str") == 0) { 1692 } else if (strcmp(token, "__get_str") == 0) {
1586 free_token(token); 1693 free_token(token);
@@ -1637,12 +1744,18 @@ process_arg_token(struct event *event, struct print_arg *arg,
1637 1744
1638static int event_read_print_args(struct event *event, struct print_arg **list) 1745static int event_read_print_args(struct event *event, struct print_arg **list)
1639{ 1746{
1640 enum event_type type; 1747 enum event_type type = EVENT_ERROR;
1641 struct print_arg *arg; 1748 struct print_arg *arg;
1642 char *token; 1749 char *token;
1643 int args = 0; 1750 int args = 0;
1644 1751
1645 do { 1752 do {
1753 if (type == EVENT_NEWLINE) {
1754 free_token(token);
1755 type = read_token_item(&token);
1756 continue;
1757 }
1758
1646 arg = malloc_or_die(sizeof(*arg)); 1759 arg = malloc_or_die(sizeof(*arg));
1647 memset(arg, 0, sizeof(*arg)); 1760 memset(arg, 0, sizeof(*arg));
1648 1761
@@ -1683,18 +1796,19 @@ static int event_read_print(struct event *event)
1683 char *token; 1796 char *token;
1684 int ret; 1797 int ret;
1685 1798
1686 if (read_expected_item(EVENT_ITEM, (char *)"print") < 0) 1799 if (read_expected_item(EVENT_ITEM, "print") < 0)
1687 return -1; 1800 return -1;
1688 1801
1689 if (read_expected(EVENT_ITEM, (char *)"fmt") < 0) 1802 if (read_expected(EVENT_ITEM, "fmt") < 0)
1690 return -1; 1803 return -1;
1691 1804
1692 if (read_expected(EVENT_OP, (char *)":") < 0) 1805 if (read_expected(EVENT_OP, ":") < 0)
1693 return -1; 1806 return -1;
1694 1807
1695 if (read_expect_type(EVENT_DQUOTE, &token) < 0) 1808 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1696 goto fail; 1809 goto fail;
1697 1810
1811 concat:
1698 event->print_fmt.format = token; 1812 event->print_fmt.format = token;
1699 event->print_fmt.args = NULL; 1813 event->print_fmt.args = NULL;
1700 1814
@@ -1704,7 +1818,22 @@ static int event_read_print(struct event *event)
1704 if (type == EVENT_NONE) 1818 if (type == EVENT_NONE)
1705 return 0; 1819 return 0;
1706 1820
1707 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1821 /* Handle concatination of print lines */
1822 if (type == EVENT_DQUOTE) {
1823 char *cat;
1824
1825 cat = malloc_or_die(strlen(event->print_fmt.format) +
1826 strlen(token) + 1);
1827 strcpy(cat, event->print_fmt.format);
1828 strcat(cat, token);
1829 free_token(token);
1830 free_token(event->print_fmt.format);
1831 event->print_fmt.format = NULL;
1832 token = cat;
1833 goto concat;
1834 }
1835
1836 if (test_type_token(type, token, EVENT_DELIM, ","))
1708 goto fail; 1837 goto fail;
1709 1838
1710 free_token(token); 1839 free_token(token);
@@ -1713,7 +1842,7 @@ static int event_read_print(struct event *event)
1713 if (ret < 0) 1842 if (ret < 0)
1714 return -1; 1843 return -1;
1715 1844
1716 return 0; 1845 return ret;
1717 1846
1718 fail: 1847 fail:
1719 free_token(token); 1848 free_token(token);
@@ -1759,7 +1888,7 @@ find_any_field(struct event *event, const char *name)
1759 return find_field(event, name); 1888 return find_field(event, name);
1760} 1889}
1761 1890
1762static unsigned long long read_size(void *ptr, int size) 1891unsigned long long read_size(void *ptr, int size)
1763{ 1892{
1764 switch (size) { 1893 switch (size) {
1765 case 1: 1894 case 1:
@@ -1822,37 +1951,67 @@ static int get_common_info(const char *type, int *offset, int *size)
1822 return 0; 1951 return 0;
1823} 1952}
1824 1953
1825int trace_parse_common_type(void *data) 1954static int __parse_common(void *data, int *size, int *offset,
1955 const char *name)
1826{ 1956{
1827 static int type_offset;
1828 static int type_size;
1829 int ret; 1957 int ret;
1830 1958
1831 if (!type_size) { 1959 if (!*size) {
1832 ret = get_common_info("common_type", 1960 ret = get_common_info(name, offset, size);
1833 &type_offset,
1834 &type_size);
1835 if (ret < 0) 1961 if (ret < 0)
1836 return ret; 1962 return ret;
1837 } 1963 }
1838 return read_size(data + type_offset, type_size); 1964 return read_size(data + *offset, *size);
1965}
1966
1967int trace_parse_common_type(void *data)
1968{
1969 static int type_offset;
1970 static int type_size;
1971
1972 return __parse_common(data, &type_size, &type_offset,
1973 "common_type");
1839} 1974}
1840 1975
1841static int parse_common_pid(void *data) 1976int trace_parse_common_pid(void *data)
1842{ 1977{
1843 static int pid_offset; 1978 static int pid_offset;
1844 static int pid_size; 1979 static int pid_size;
1980
1981 return __parse_common(data, &pid_size, &pid_offset,
1982 "common_pid");
1983}
1984
1985int parse_common_pc(void *data)
1986{
1987 static int pc_offset;
1988 static int pc_size;
1989
1990 return __parse_common(data, &pc_size, &pc_offset,
1991 "common_preempt_count");
1992}
1993
1994int parse_common_flags(void *data)
1995{
1996 static int flags_offset;
1997 static int flags_size;
1998
1999 return __parse_common(data, &flags_size, &flags_offset,
2000 "common_flags");
2001}
2002
2003int parse_common_lock_depth(void *data)
2004{
2005 static int ld_offset;
2006 static int ld_size;
1845 int ret; 2007 int ret;
1846 2008
1847 if (!pid_size) { 2009 ret = __parse_common(data, &ld_size, &ld_offset,
1848 ret = get_common_info("common_pid", 2010 "common_lock_depth");
1849 &pid_offset, 2011 if (ret < 0)
1850 &pid_size); 2012 return -1;
1851 if (ret < 0)
1852 return ret;
1853 }
1854 2013
1855 return read_size(data + pid_offset, pid_size); 2014 return ret;
1856} 2015}
1857 2016
1858struct event *trace_find_event(int id) 2017struct event *trace_find_event(int id)
@@ -1866,11 +2025,20 @@ struct event *trace_find_event(int id)
1866 return event; 2025 return event;
1867} 2026}
1868 2027
2028struct event *trace_find_next_event(struct event *event)
2029{
2030 if (!event)
2031 return event_list;
2032
2033 return event->next;
2034}
2035
1869static unsigned long long eval_num_arg(void *data, int size, 2036static unsigned long long eval_num_arg(void *data, int size,
1870 struct event *event, struct print_arg *arg) 2037 struct event *event, struct print_arg *arg)
1871{ 2038{
1872 unsigned long long val = 0; 2039 unsigned long long val = 0;
1873 unsigned long long left, right; 2040 unsigned long long left, right;
2041 struct print_arg *larg;
1874 2042
1875 switch (arg->type) { 2043 switch (arg->type) {
1876 case PRINT_NULL: 2044 case PRINT_NULL:
@@ -1897,6 +2065,26 @@ static unsigned long long eval_num_arg(void *data, int size,
1897 return 0; 2065 return 0;
1898 break; 2066 break;
1899 case PRINT_OP: 2067 case PRINT_OP:
2068 if (strcmp(arg->op.op, "[") == 0) {
2069 /*
2070 * Arrays are special, since we don't want
2071 * to read the arg as is.
2072 */
2073 if (arg->op.left->type != PRINT_FIELD)
2074 goto default_op; /* oops, all bets off */
2075 larg = arg->op.left;
2076 if (!larg->field.field) {
2077 larg->field.field =
2078 find_any_field(event, larg->field.name);
2079 if (!larg->field.field)
2080 die("field %s not found", larg->field.name);
2081 }
2082 right = eval_num_arg(data, size, event, arg->op.right);
2083 val = read_size(data + larg->field.field->offset +
2084 right * long_size, long_size);
2085 break;
2086 }
2087 default_op:
1900 left = eval_num_arg(data, size, event, arg->op.left); 2088 left = eval_num_arg(data, size, event, arg->op.left);
1901 right = eval_num_arg(data, size, event, arg->op.right); 2089 right = eval_num_arg(data, size, event, arg->op.right);
1902 switch (arg->op.op[0]) { 2090 switch (arg->op.op[0]) {
@@ -1947,6 +2135,12 @@ static unsigned long long eval_num_arg(void *data, int size,
1947 die("unknown op '%s'", arg->op.op); 2135 die("unknown op '%s'", arg->op.op);
1948 val = left == right; 2136 val = left == right;
1949 break; 2137 break;
2138 case '-':
2139 val = left - right;
2140 break;
2141 case '+':
2142 val = left + right;
2143 break;
1950 default: 2144 default:
1951 die("unknown op '%s'", arg->op.op); 2145 die("unknown op '%s'", arg->op.op);
1952 } 2146 }
@@ -1978,7 +2172,7 @@ static const struct flag flags[] = {
1978 { "HRTIMER_RESTART", 1 }, 2172 { "HRTIMER_RESTART", 1 },
1979}; 2173};
1980 2174
1981static unsigned long long eval_flag(const char *flag) 2175unsigned long long eval_flag(const char *flag)
1982{ 2176{
1983 int i; 2177 int i;
1984 2178
@@ -2145,8 +2339,9 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
2145 case 'u': 2339 case 'u':
2146 case 'x': 2340 case 'x':
2147 case 'i': 2341 case 'i':
2148 bptr = (void *)(((unsigned long)bptr + (long_size - 1)) & 2342 /* the pointers are always 4 bytes aligned */
2149 ~(long_size - 1)); 2343 bptr = (void *)(((unsigned long)bptr + 3) &
2344 ~3);
2150 switch (ls) { 2345 switch (ls) {
2151 case 0: 2346 case 0:
2152 case 1: 2347 case 1:
@@ -2270,7 +2465,27 @@ static void pretty_print(void *data, int size, struct event *event)
2270 2465
2271 for (; *ptr; ptr++) { 2466 for (; *ptr; ptr++) {
2272 ls = 0; 2467 ls = 0;
2273 if (*ptr == '%') { 2468 if (*ptr == '\\') {
2469 ptr++;
2470 switch (*ptr) {
2471 case 'n':
2472 printf("\n");
2473 break;
2474 case 't':
2475 printf("\t");
2476 break;
2477 case 'r':
2478 printf("\r");
2479 break;
2480 case '\\':
2481 printf("\\");
2482 break;
2483 default:
2484 printf("%c", *ptr);
2485 break;
2486 }
2487
2488 } else if (*ptr == '%') {
2274 saveptr = ptr; 2489 saveptr = ptr;
2275 show_func = 0; 2490 show_func = 0;
2276 cont_process: 2491 cont_process:
@@ -2377,6 +2592,41 @@ static inline int log10_cpu(int nb)
2377 return 1; 2592 return 1;
2378} 2593}
2379 2594
2595static void print_lat_fmt(void *data, int size __unused)
2596{
2597 unsigned int lat_flags;
2598 unsigned int pc;
2599 int lock_depth;
2600 int hardirq;
2601 int softirq;
2602
2603 lat_flags = parse_common_flags(data);
2604 pc = parse_common_pc(data);
2605 lock_depth = parse_common_lock_depth(data);
2606
2607 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2608 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2609
2610 printf("%c%c%c",
2611 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2612 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2613 'X' : '.',
2614 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2615 'N' : '.',
2616 (hardirq && softirq) ? 'H' :
2617 hardirq ? 'h' : softirq ? 's' : '.');
2618
2619 if (pc)
2620 printf("%x", pc);
2621 else
2622 printf(".");
2623
2624 if (lock_depth < 0)
2625 printf(".");
2626 else
2627 printf("%d", lock_depth);
2628}
2629
2380/* taken from Linux, written by Frederic Weisbecker */ 2630/* taken from Linux, written by Frederic Weisbecker */
2381static void print_graph_cpu(int cpu) 2631static void print_graph_cpu(int cpu)
2382{ 2632{
@@ -2452,7 +2702,7 @@ get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2452 if (!(event->flags & EVENT_FL_ISFUNCRET)) 2702 if (!(event->flags & EVENT_FL_ISFUNCRET))
2453 return NULL; 2703 return NULL;
2454 2704
2455 pid = parse_common_pid(next->data); 2705 pid = trace_parse_common_pid(next->data);
2456 field = find_field(event, "func"); 2706 field = find_field(event, "func");
2457 if (!field) 2707 if (!field)
2458 die("function return does not have field func"); 2708 die("function return does not have field func");
@@ -2620,6 +2870,11 @@ pretty_print_func_ent(void *data, int size, struct event *event,
2620 2870
2621 printf(" | "); 2871 printf(" | ");
2622 2872
2873 if (latency_format) {
2874 print_lat_fmt(data, size);
2875 printf(" | ");
2876 }
2877
2623 field = find_field(event, "func"); 2878 field = find_field(event, "func");
2624 if (!field) 2879 if (!field)
2625 die("function entry does not have func field"); 2880 die("function entry does not have func field");
@@ -2663,6 +2918,11 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,
2663 2918
2664 printf(" | "); 2919 printf(" | ");
2665 2920
2921 if (latency_format) {
2922 print_lat_fmt(data, size);
2923 printf(" | ");
2924 }
2925
2666 field = find_field(event, "rettime"); 2926 field = find_field(event, "rettime");
2667 if (!field) 2927 if (!field)
2668 die("can't find rettime in return graph"); 2928 die("can't find rettime in return graph");
@@ -2724,19 +2984,30 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2724 2984
2725 event = trace_find_event(type); 2985 event = trace_find_event(type);
2726 if (!event) { 2986 if (!event) {
2727 printf("ug! no event found for type %d\n", type); 2987 warning("ug! no event found for type %d", type);
2728 return; 2988 return;
2729 } 2989 }
2730 2990
2731 pid = parse_common_pid(data); 2991 pid = trace_parse_common_pid(data);
2732 2992
2733 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET)) 2993 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
2734 return pretty_print_func_graph(data, size, event, cpu, 2994 return pretty_print_func_graph(data, size, event, cpu,
2735 pid, comm, secs, usecs); 2995 pid, comm, secs, usecs);
2736 2996
2737 printf("%16s-%-5d [%03d] %5lu.%09Lu: %s: ", 2997 if (latency_format) {
2738 comm, pid, cpu, 2998 printf("%8.8s-%-5d %3d",
2739 secs, nsecs, event->name); 2999 comm, pid, cpu);
3000 print_lat_fmt(data, size);
3001 } else
3002 printf("%16s-%-5d [%03d]", comm, pid, cpu);
3003
3004 printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
3005
3006 if (event->flags & EVENT_FL_FAILED) {
3007 printf("EVENT '%s' FAILED TO PARSE\n",
3008 event->name);
3009 return;
3010 }
2740 3011
2741 pretty_print(data, size, event); 3012 pretty_print(data, size, event);
2742 printf("\n"); 3013 printf("\n");
@@ -2807,46 +3078,71 @@ static void print_args(struct print_arg *args)
2807 } 3078 }
2808} 3079}
2809 3080
2810static void parse_header_field(char *type, 3081static void parse_header_field(const char *field,
2811 int *offset, int *size) 3082 int *offset, int *size)
2812{ 3083{
2813 char *token; 3084 char *token;
3085 int type;
2814 3086
2815 if (read_expected(EVENT_ITEM, (char *)"field") < 0) 3087 if (read_expected(EVENT_ITEM, "field") < 0)
2816 return; 3088 return;
2817 if (read_expected(EVENT_OP, (char *)":") < 0) 3089 if (read_expected(EVENT_OP, ":") < 0)
2818 return; 3090 return;
3091
2819 /* type */ 3092 /* type */
2820 if (read_expect_type(EVENT_ITEM, &token) < 0) 3093 if (read_expect_type(EVENT_ITEM, &token) < 0)
2821 return; 3094 goto fail;
2822 free_token(token); 3095 free_token(token);
2823 3096
2824 if (read_expected(EVENT_ITEM, type) < 0) 3097 if (read_expected(EVENT_ITEM, field) < 0)
2825 return; 3098 return;
2826 if (read_expected(EVENT_OP, (char *)";") < 0) 3099 if (read_expected(EVENT_OP, ";") < 0)
2827 return; 3100 return;
2828 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 3101 if (read_expected(EVENT_ITEM, "offset") < 0)
2829 return; 3102 return;
2830 if (read_expected(EVENT_OP, (char *)":") < 0) 3103 if (read_expected(EVENT_OP, ":") < 0)
2831 return; 3104 return;
2832 if (read_expect_type(EVENT_ITEM, &token) < 0) 3105 if (read_expect_type(EVENT_ITEM, &token) < 0)
2833 return; 3106 goto fail;
2834 *offset = atoi(token); 3107 *offset = atoi(token);
2835 free_token(token); 3108 free_token(token);
2836 if (read_expected(EVENT_OP, (char *)";") < 0) 3109 if (read_expected(EVENT_OP, ";") < 0)
2837 return; 3110 return;
2838 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 3111 if (read_expected(EVENT_ITEM, "size") < 0)
2839 return; 3112 return;
2840 if (read_expected(EVENT_OP, (char *)":") < 0) 3113 if (read_expected(EVENT_OP, ":") < 0)
2841 return; 3114 return;
2842 if (read_expect_type(EVENT_ITEM, &token) < 0) 3115 if (read_expect_type(EVENT_ITEM, &token) < 0)
2843 return; 3116 goto fail;
2844 *size = atoi(token); 3117 *size = atoi(token);
2845 free_token(token); 3118 free_token(token);
2846 if (read_expected(EVENT_OP, (char *)";") < 0) 3119 if (read_expected(EVENT_OP, ";") < 0)
2847 return;
2848 if (read_expect_type(EVENT_NEWLINE, &token) < 0)
2849 return; 3120 return;
3121 type = read_token(&token);
3122 if (type != EVENT_NEWLINE) {
3123 /* newer versions of the kernel have a "signed" type */
3124 if (type != EVENT_ITEM)
3125 goto fail;
3126
3127 if (strcmp(token, "signed") != 0)
3128 goto fail;
3129
3130 free_token(token);
3131
3132 if (read_expected(EVENT_OP, ":") < 0)
3133 return;
3134
3135 if (read_expect_type(EVENT_ITEM, &token))
3136 goto fail;
3137
3138 free_token(token);
3139 if (read_expected(EVENT_OP, ";") < 0)
3140 return;
3141
3142 if (read_expect_type(EVENT_NEWLINE, &token))
3143 goto fail;
3144 }
3145 fail:
2850 free_token(token); 3146 free_token(token);
2851} 3147}
2852 3148
@@ -2854,11 +3150,11 @@ int parse_header_page(char *buf, unsigned long size)
2854{ 3150{
2855 init_input_buf(buf, size); 3151 init_input_buf(buf, size);
2856 3152
2857 parse_header_field((char *)"timestamp", &header_page_ts_offset, 3153 parse_header_field("timestamp", &header_page_ts_offset,
2858 &header_page_ts_size); 3154 &header_page_ts_size);
2859 parse_header_field((char *)"commit", &header_page_size_offset, 3155 parse_header_field("commit", &header_page_size_offset,
2860 &header_page_size_size); 3156 &header_page_size_size);
2861 parse_header_field((char *)"data", &header_page_data_offset, 3157 parse_header_field("data", &header_page_data_offset,
2862 &header_page_data_size); 3158 &header_page_data_size);
2863 3159
2864 return 0; 3160 return 0;
@@ -2909,6 +3205,9 @@ int parse_ftrace_file(char *buf, unsigned long size)
2909 if (ret < 0) 3205 if (ret < 0)
2910 die("failed to read ftrace event print fmt"); 3206 die("failed to read ftrace event print fmt");
2911 3207
3208 /* New ftrace handles args */
3209 if (ret > 0)
3210 return 0;
2912 /* 3211 /*
2913 * The arguments for ftrace files are parsed by the fields. 3212 * The arguments for ftrace files are parsed by the fields.
2914 * Set up the fields as their arguments. 3213 * Set up the fields as their arguments.
@@ -2926,7 +3225,7 @@ int parse_ftrace_file(char *buf, unsigned long size)
2926 return 0; 3225 return 0;
2927} 3226}
2928 3227
2929int parse_event_file(char *buf, unsigned long size, char *system__unused __unused) 3228int parse_event_file(char *buf, unsigned long size, char *sys)
2930{ 3229{
2931 struct event *event; 3230 struct event *event;
2932 int ret; 3231 int ret;
@@ -2946,12 +3245,18 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2946 die("failed to read event id"); 3245 die("failed to read event id");
2947 3246
2948 ret = event_read_format(event); 3247 ret = event_read_format(event);
2949 if (ret < 0) 3248 if (ret < 0) {
2950 die("failed to read event format"); 3249 warning("failed to read event format for %s", event->name);
3250 goto event_failed;
3251 }
2951 3252
2952 ret = event_read_print(event); 3253 ret = event_read_print(event);
2953 if (ret < 0) 3254 if (ret < 0) {
2954 die("failed to read event print fmt"); 3255 warning("failed to read event print fmt for %s", event->name);
3256 goto event_failed;
3257 }
3258
3259 event->system = strdup(sys);
2955 3260
2956#define PRINT_ARGS 0 3261#define PRINT_ARGS 0
2957 if (PRINT_ARGS && event->print_fmt.args) 3262 if (PRINT_ARGS && event->print_fmt.args)
@@ -2959,6 +3264,12 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2959 3264
2960 add_event(event); 3265 add_event(event);
2961 return 0; 3266 return 0;
3267
3268 event_failed:
3269 event->flags |= EVENT_FL_FAILED;
3270 /* still add it even if it failed */
3271 add_event(event);
3272 return -1;
2962} 3273}
2963 3274
2964void parse_set_info(int nr_cpus, int long_sz) 3275void parse_set_info(int nr_cpus, int long_sz)
diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c
new file mode 100644
index 000000000000..51e833fd58c3
--- /dev/null
+++ b/tools/perf/util/trace-event-perl.c
@@ -0,0 +1,598 @@
1/*
2 * trace-event-perl. Feed perf trace events to an embedded Perl interpreter.
3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26#include <errno.h>
27
28#include "../perf.h"
29#include "util.h"
30#include "trace-event.h"
31#include "trace-event-perl.h"
32
33void xs_init(pTHX);
34
35void boot_Perf__Trace__Context(pTHX_ CV *cv);
36void boot_DynaLoader(pTHX_ CV *cv);
37
38void xs_init(pTHX)
39{
40 const char *file = __FILE__;
41 dXSUB_SYS;
42
43 newXS("Perf::Trace::Context::bootstrap", boot_Perf__Trace__Context,
44 file);
45 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
46}
47
48INTERP my_perl;
49
50#define FTRACE_MAX_EVENT \
51 ((1 << (sizeof(unsigned short) * 8)) - 1)
52
53struct event *events[FTRACE_MAX_EVENT];
54
55static struct scripting_context *scripting_context;
56
57static char *cur_field_name;
58static int zero_flag_atom;
59
60static void define_symbolic_value(const char *ev_name,
61 const char *field_name,
62 const char *field_value,
63 const char *field_str)
64{
65 unsigned long long value;
66 dSP;
67
68 value = eval_flag(field_value);
69
70 ENTER;
71 SAVETMPS;
72 PUSHMARK(SP);
73
74 XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
75 XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
76 XPUSHs(sv_2mortal(newSVuv(value)));
77 XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
78
79 PUTBACK;
80 if (get_cv("main::define_symbolic_value", 0))
81 call_pv("main::define_symbolic_value", G_SCALAR);
82 SPAGAIN;
83 PUTBACK;
84 FREETMPS;
85 LEAVE;
86}
87
88static void define_symbolic_values(struct print_flag_sym *field,
89 const char *ev_name,
90 const char *field_name)
91{
92 define_symbolic_value(ev_name, field_name, field->value, field->str);
93 if (field->next)
94 define_symbolic_values(field->next, ev_name, field_name);
95}
96
97static void define_symbolic_field(const char *ev_name,
98 const char *field_name)
99{
100 dSP;
101
102 ENTER;
103 SAVETMPS;
104 PUSHMARK(SP);
105
106 XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
107 XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
108
109 PUTBACK;
110 if (get_cv("main::define_symbolic_field", 0))
111 call_pv("main::define_symbolic_field", G_SCALAR);
112 SPAGAIN;
113 PUTBACK;
114 FREETMPS;
115 LEAVE;
116}
117
118static void define_flag_value(const char *ev_name,
119 const char *field_name,
120 const char *field_value,
121 const char *field_str)
122{
123 unsigned long long value;
124 dSP;
125
126 value = eval_flag(field_value);
127
128 ENTER;
129 SAVETMPS;
130 PUSHMARK(SP);
131
132 XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
133 XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
134 XPUSHs(sv_2mortal(newSVuv(value)));
135 XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
136
137 PUTBACK;
138 if (get_cv("main::define_flag_value", 0))
139 call_pv("main::define_flag_value", G_SCALAR);
140 SPAGAIN;
141 PUTBACK;
142 FREETMPS;
143 LEAVE;
144}
145
146static void define_flag_values(struct print_flag_sym *field,
147 const char *ev_name,
148 const char *field_name)
149{
150 define_flag_value(ev_name, field_name, field->value, field->str);
151 if (field->next)
152 define_flag_values(field->next, ev_name, field_name);
153}
154
155static void define_flag_field(const char *ev_name,
156 const char *field_name,
157 const char *delim)
158{
159 dSP;
160
161 ENTER;
162 SAVETMPS;
163 PUSHMARK(SP);
164
165 XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
166 XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
167 XPUSHs(sv_2mortal(newSVpv(delim, 0)));
168
169 PUTBACK;
170 if (get_cv("main::define_flag_field", 0))
171 call_pv("main::define_flag_field", G_SCALAR);
172 SPAGAIN;
173 PUTBACK;
174 FREETMPS;
175 LEAVE;
176}
177
178static void define_event_symbols(struct event *event,
179 const char *ev_name,
180 struct print_arg *args)
181{
182 switch (args->type) {
183 case PRINT_NULL:
184 break;
185 case PRINT_ATOM:
186 define_flag_value(ev_name, cur_field_name, "0",
187 args->atom.atom);
188 zero_flag_atom = 0;
189 break;
190 case PRINT_FIELD:
191 if (cur_field_name)
192 free(cur_field_name);
193 cur_field_name = strdup(args->field.name);
194 break;
195 case PRINT_FLAGS:
196 define_event_symbols(event, ev_name, args->flags.field);
197 define_flag_field(ev_name, cur_field_name, args->flags.delim);
198 define_flag_values(args->flags.flags, ev_name, cur_field_name);
199 break;
200 case PRINT_SYMBOL:
201 define_event_symbols(event, ev_name, args->symbol.field);
202 define_symbolic_field(ev_name, cur_field_name);
203 define_symbolic_values(args->symbol.symbols, ev_name,
204 cur_field_name);
205 break;
206 case PRINT_STRING:
207 break;
208 case PRINT_TYPE:
209 define_event_symbols(event, ev_name, args->typecast.item);
210 break;
211 case PRINT_OP:
212 if (strcmp(args->op.op, ":") == 0)
213 zero_flag_atom = 1;
214 define_event_symbols(event, ev_name, args->op.left);
215 define_event_symbols(event, ev_name, args->op.right);
216 break;
217 default:
218 /* we should warn... */
219 return;
220 }
221
222 if (args->next)
223 define_event_symbols(event, ev_name, args->next);
224}
225
226static inline struct event *find_cache_event(int type)
227{
228 static char ev_name[256];
229 struct event *event;
230
231 if (events[type])
232 return events[type];
233
234 events[type] = event = trace_find_event(type);
235 if (!event)
236 return NULL;
237
238 sprintf(ev_name, "%s::%s", event->system, event->name);
239
240 define_event_symbols(event, ev_name, event->print_fmt.args);
241
242 return event;
243}
244
245int common_pc(struct scripting_context *context)
246{
247 int pc;
248
249 pc = parse_common_pc(context->event_data);
250
251 return pc;
252}
253
254int common_flags(struct scripting_context *context)
255{
256 int flags;
257
258 flags = parse_common_flags(context->event_data);
259
260 return flags;
261}
262
263int common_lock_depth(struct scripting_context *context)
264{
265 int lock_depth;
266
267 lock_depth = parse_common_lock_depth(context->event_data);
268
269 return lock_depth;
270}
271
272static void perl_process_event(int cpu, void *data,
273 int size __attribute((unused)),
274 unsigned long long nsecs, char *comm)
275{
276 struct format_field *field;
277 static char handler[256];
278 unsigned long long val;
279 unsigned long s, ns;
280 struct event *event;
281 int type;
282 int pid;
283
284 dSP;
285
286 type = trace_parse_common_type(data);
287
288 event = find_cache_event(type);
289 if (!event)
290 die("ug! no event found for type %d", type);
291
292 pid = trace_parse_common_pid(data);
293
294 sprintf(handler, "%s::%s", event->system, event->name);
295
296 s = nsecs / NSECS_PER_SEC;
297 ns = nsecs - s * NSECS_PER_SEC;
298
299 scripting_context->event_data = data;
300
301 ENTER;
302 SAVETMPS;
303 PUSHMARK(SP);
304
305 XPUSHs(sv_2mortal(newSVpv(handler, 0)));
306 XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
307 XPUSHs(sv_2mortal(newSVuv(cpu)));
308 XPUSHs(sv_2mortal(newSVuv(s)));
309 XPUSHs(sv_2mortal(newSVuv(ns)));
310 XPUSHs(sv_2mortal(newSViv(pid)));
311 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
312
313 /* common fields other than pid can be accessed via xsub fns */
314
315 for (field = event->format.fields; field; field = field->next) {
316 if (field->flags & FIELD_IS_STRING) {
317 int offset;
318 if (field->flags & FIELD_IS_DYNAMIC) {
319 offset = *(int *)(data + field->offset);
320 offset &= 0xffff;
321 } else
322 offset = field->offset;
323 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
324 } else { /* FIELD_IS_NUMERIC */
325 val = read_size(data + field->offset, field->size);
326 if (field->flags & FIELD_IS_SIGNED) {
327 XPUSHs(sv_2mortal(newSViv(val)));
328 } else {
329 XPUSHs(sv_2mortal(newSVuv(val)));
330 }
331 }
332 }
333
334 PUTBACK;
335
336 if (get_cv(handler, 0))
337 call_pv(handler, G_SCALAR);
338 else if (get_cv("main::trace_unhandled", 0)) {
339 XPUSHs(sv_2mortal(newSVpv(handler, 0)));
340 XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
341 XPUSHs(sv_2mortal(newSVuv(cpu)));
342 XPUSHs(sv_2mortal(newSVuv(nsecs)));
343 XPUSHs(sv_2mortal(newSViv(pid)));
344 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
345 call_pv("main::trace_unhandled", G_SCALAR);
346 }
347 SPAGAIN;
348 PUTBACK;
349 FREETMPS;
350 LEAVE;
351}
352
353static void run_start_sub(void)
354{
355 dSP; /* access to Perl stack */
356 PUSHMARK(SP);
357
358 if (get_cv("main::trace_begin", 0))
359 call_pv("main::trace_begin", G_DISCARD | G_NOARGS);
360}
361
362/*
363 * Start trace script
364 */
365static int perl_start_script(const char *script)
366{
367 const char *command_line[2] = { "", NULL };
368
369 command_line[1] = script;
370
371 my_perl = perl_alloc();
372 perl_construct(my_perl);
373
374 if (perl_parse(my_perl, xs_init, 2, (char **)command_line,
375 (char **)NULL))
376 return -1;
377
378 perl_run(my_perl);
379 if (SvTRUE(ERRSV))
380 return -1;
381
382 run_start_sub();
383
384 fprintf(stderr, "perf trace started with Perl script %s\n\n", script);
385
386 return 0;
387}
388
389/*
390 * Stop trace script
391 */
392static int perl_stop_script(void)
393{
394 dSP; /* access to Perl stack */
395 PUSHMARK(SP);
396
397 if (get_cv("main::trace_end", 0))
398 call_pv("main::trace_end", G_DISCARD | G_NOARGS);
399
400 perl_destruct(my_perl);
401 perl_free(my_perl);
402
403 fprintf(stderr, "\nperf trace Perl script stopped\n");
404
405 return 0;
406}
407
408static int perl_generate_script(const char *outfile)
409{
410 struct event *event = NULL;
411 struct format_field *f;
412 char fname[PATH_MAX];
413 int not_first, count;
414 FILE *ofp;
415
416 sprintf(fname, "%s.pl", outfile);
417 ofp = fopen(fname, "w");
418 if (ofp == NULL) {
419 fprintf(stderr, "couldn't open %s\n", fname);
420 return -1;
421 }
422
423 fprintf(ofp, "# perf trace event handlers, "
424 "generated by perf trace -g perl\n");
425
426 fprintf(ofp, "# Licensed under the terms of the GNU GPL"
427 " License version 2\n\n");
428
429 fprintf(ofp, "# The common_* event handler fields are the most useful "
430 "fields common to\n");
431
432 fprintf(ofp, "# all events. They don't necessarily correspond to "
433 "the 'common_*' fields\n");
434
435 fprintf(ofp, "# in the format files. Those fields not available as "
436 "handler params can\n");
437
438 fprintf(ofp, "# be retrieved using Perl functions of the form "
439 "common_*($context).\n");
440
441 fprintf(ofp, "# See Context.pm for the list of available "
442 "functions.\n\n");
443
444 fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/"
445 "Perf-Trace-Util/lib\";\n");
446
447 fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n");
448 fprintf(ofp, "use Perf::Trace::Core;\n");
449 fprintf(ofp, "use Perf::Trace::Context;\n");
450 fprintf(ofp, "use Perf::Trace::Util;\n\n");
451
452 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
453 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
454
455 while ((event = trace_find_next_event(event))) {
456 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
457 fprintf(ofp, "\tmy (");
458
459 fprintf(ofp, "$event_name, ");
460 fprintf(ofp, "$context, ");
461 fprintf(ofp, "$common_cpu, ");
462 fprintf(ofp, "$common_secs, ");
463 fprintf(ofp, "$common_nsecs,\n");
464 fprintf(ofp, "\t $common_pid, ");
465 fprintf(ofp, "$common_comm,\n\t ");
466
467 not_first = 0;
468 count = 0;
469
470 for (f = event->format.fields; f; f = f->next) {
471 if (not_first++)
472 fprintf(ofp, ", ");
473 if (++count % 5 == 0)
474 fprintf(ofp, "\n\t ");
475
476 fprintf(ofp, "$%s", f->name);
477 }
478 fprintf(ofp, ") = @_;\n\n");
479
480 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
481 "$common_secs, $common_nsecs,\n\t "
482 "$common_pid, $common_comm);\n\n");
483
484 fprintf(ofp, "\tprintf(\"");
485
486 not_first = 0;
487 count = 0;
488
489 for (f = event->format.fields; f; f = f->next) {
490 if (not_first++)
491 fprintf(ofp, ", ");
492 if (count && count % 4 == 0) {
493 fprintf(ofp, "\".\n\t \"");
494 }
495 count++;
496
497 fprintf(ofp, "%s=", f->name);
498 if (f->flags & FIELD_IS_STRING ||
499 f->flags & FIELD_IS_FLAG ||
500 f->flags & FIELD_IS_SYMBOLIC)
501 fprintf(ofp, "%%s");
502 else if (f->flags & FIELD_IS_SIGNED)
503 fprintf(ofp, "%%d");
504 else
505 fprintf(ofp, "%%u");
506 }
507
508 fprintf(ofp, "\\n\",\n\t ");
509
510 not_first = 0;
511 count = 0;
512
513 for (f = event->format.fields; f; f = f->next) {
514 if (not_first++)
515 fprintf(ofp, ", ");
516
517 if (++count % 5 == 0)
518 fprintf(ofp, "\n\t ");
519
520 if (f->flags & FIELD_IS_FLAG) {
521 if ((count - 1) % 5 != 0) {
522 fprintf(ofp, "\n\t ");
523 count = 4;
524 }
525 fprintf(ofp, "flag_str(\"");
526 fprintf(ofp, "%s::%s\", ", event->system,
527 event->name);
528 fprintf(ofp, "\"%s\", $%s)", f->name,
529 f->name);
530 } else if (f->flags & FIELD_IS_SYMBOLIC) {
531 if ((count - 1) % 5 != 0) {
532 fprintf(ofp, "\n\t ");
533 count = 4;
534 }
535 fprintf(ofp, "symbol_str(\"");
536 fprintf(ofp, "%s::%s\", ", event->system,
537 event->name);
538 fprintf(ofp, "\"%s\", $%s)", f->name,
539 f->name);
540 } else
541 fprintf(ofp, "$%s", f->name);
542 }
543
544 fprintf(ofp, ");\n");
545 fprintf(ofp, "}\n\n");
546 }
547
548 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
549 "$common_cpu, $common_secs, $common_nsecs,\n\t "
550 "$common_pid, $common_comm) = @_;\n\n");
551
552 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
553 "$common_secs, $common_nsecs,\n\t $common_pid, "
554 "$common_comm);\n}\n\n");
555
556 fprintf(ofp, "sub print_header\n{\n"
557 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
558 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t "
559 "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}");
560
561 fclose(ofp);
562
563 fprintf(stderr, "generated Perl script: %s\n", fname);
564
565 return 0;
566}
567
568struct scripting_ops perl_scripting_ops = {
569 .name = "Perl",
570 .start_script = perl_start_script,
571 .stop_script = perl_stop_script,
572 .process_event = perl_process_event,
573 .generate_script = perl_generate_script,
574};
575
576#ifdef NO_LIBPERL
577void setup_perl_scripting(void)
578{
579 fprintf(stderr, "Perl scripting not supported."
580 " Install libperl and rebuild perf to enable it. e.g. "
581 "apt-get install libperl-dev (ubuntu), yum install "
582 "perl-ExtUtils-Embed (Fedora), etc.\n");
583}
584#else
585void setup_perl_scripting(void)
586{
587 int err;
588 err = script_spec_register("Perl", &perl_scripting_ops);
589 if (err)
590 die("error registering Perl script extension");
591
592 err = script_spec_register("pl", &perl_scripting_ops);
593 if (err)
594 die("error registering pl script extension");
595
596 scripting_context = malloc(sizeof(struct scripting_context));
597}
598#endif
diff --git a/tools/perf/util/trace-event-perl.h b/tools/perf/util/trace-event-perl.h
new file mode 100644
index 000000000000..8fe0d866fe1a
--- /dev/null
+++ b/tools/perf/util/trace-event-perl.h
@@ -0,0 +1,51 @@
1#ifndef __PERF_TRACE_EVENT_PERL_H
2#define __PERF_TRACE_EVENT_PERL_H
3#ifdef NO_LIBPERL
4typedef int INTERP;
5#define dSP
6#define ENTER
7#define SAVETMPS
8#define PUTBACK
9#define SPAGAIN
10#define FREETMPS
11#define LEAVE
12#define SP
13#define ERRSV
14#define G_SCALAR (0)
15#define G_DISCARD (0)
16#define G_NOARGS (0)
17#define PUSHMARK(a)
18#define SvTRUE(a) (0)
19#define XPUSHs(s)
20#define sv_2mortal(a)
21#define newSVpv(a,b)
22#define newSVuv(a)
23#define newSViv(a)
24#define get_cv(a,b) (0)
25#define call_pv(a,b) (0)
26#define perl_alloc() (0)
27#define perl_construct(a) (0)
28#define perl_parse(a,b,c,d,e) (0)
29#define perl_run(a) (0)
30#define perl_destruct(a) (0)
31#define perl_free(a) (0)
32#define pTHX void
33#define CV void
34#define dXSUB_SYS
35#define pTHX_
36static inline void newXS(const char *a, void *b, const char *c) {}
37#else
38#include <EXTERN.h>
39#include <perl.h>
40typedef PerlInterpreter * INTERP;
41#endif
42
43struct scripting_context {
44 void *event_data;
45};
46
47int common_pc(struct scripting_context *context);
48int common_flags(struct scripting_context *context);
49int common_lock_depth(struct scripting_context *context);
50
51#endif /* __PERF_TRACE_EVENT_PERL_H */
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 1b5c847d2c22..342dfdd43f87 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -458,9 +458,8 @@ struct record *trace_read_data(int cpu)
458 return data; 458 return data;
459} 459}
460 460
461void trace_report(void) 461void trace_report(int fd)
462{ 462{
463 const char *input_file = "trace.info";
464 char buf[BUFSIZ]; 463 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 464 char test[] = { 23, 8, 68 };
466 char *version; 465 char *version;
@@ -468,17 +467,15 @@ void trace_report(void)
468 int show_funcs = 0; 467 int show_funcs = 0;
469 int show_printk = 0; 468 int show_printk = 0;
470 469
471 input_fd = open(input_file, O_RDONLY); 470 input_fd = fd;
472 if (input_fd < 0)
473 die("opening '%s'\n", input_file);
474 471
475 read_or_die(buf, 3); 472 read_or_die(buf, 3);
476 if (memcmp(buf, test, 3) != 0) 473 if (memcmp(buf, test, 3) != 0)
477 die("not an trace data file"); 474 die("no trace data in the file");
478 475
479 read_or_die(buf, 7); 476 read_or_die(buf, 7);
480 if (memcmp(buf, "tracing", 7) != 0) 477 if (memcmp(buf, "tracing", 7) != 0)
481 die("not a trace file (missing tracing)"); 478 die("not a trace file (missing 'tracing' tag)");
482 479
483 version = read_string(); 480 version = read_string();
484 if (show_version) 481 if (show_version)
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 693f815c9429..81698d5e6503 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,5 +1,5 @@
1#ifndef _TRACE_EVENTS_H 1#ifndef __PERF_TRACE_EVENTS_H
2#define _TRACE_EVENTS_H 2#define __PERF_TRACE_EVENTS_H
3 3
4#include "parse-events.h" 4#include "parse-events.h"
5 5
@@ -26,6 +26,11 @@ enum {
26enum format_flags { 26enum format_flags {
27 FIELD_IS_ARRAY = 1, 27 FIELD_IS_ARRAY = 1,
28 FIELD_IS_POINTER = 2, 28 FIELD_IS_POINTER = 2,
29 FIELD_IS_SIGNED = 4,
30 FIELD_IS_STRING = 8,
31 FIELD_IS_DYNAMIC = 16,
32 FIELD_IS_FLAG = 32,
33 FIELD_IS_SYMBOLIC = 64,
29}; 34};
30 35
31struct format_field { 36struct format_field {
@@ -132,15 +137,18 @@ struct event {
132 int flags; 137 int flags;
133 struct format format; 138 struct format format;
134 struct print_fmt print_fmt; 139 struct print_fmt print_fmt;
140 char *system;
135}; 141};
136 142
137enum { 143enum {
138 EVENT_FL_ISFTRACE = 1, 144 EVENT_FL_ISFTRACE = 0x01,
139 EVENT_FL_ISPRINT = 2, 145 EVENT_FL_ISPRINT = 0x02,
140 EVENT_FL_ISBPRINT = 4, 146 EVENT_FL_ISBPRINT = 0x04,
141 EVENT_FL_ISFUNC = 8, 147 EVENT_FL_ISFUNC = 0x08,
142 EVENT_FL_ISFUNCENT = 16, 148 EVENT_FL_ISFUNCENT = 0x10,
143 EVENT_FL_ISFUNCRET = 32, 149 EVENT_FL_ISFUNCRET = 0x20,
150
151 EVENT_FL_FAILED = 0x80000000
144}; 152};
145 153
146struct record { 154struct record {
@@ -154,7 +162,7 @@ struct record *trace_read_data(int cpu);
154 162
155void parse_set_info(int nr_cpus, int long_sz); 163void parse_set_info(int nr_cpus, int long_sz);
156 164
157void trace_report(void); 165void trace_report(int fd);
158 166
159void *malloc_or_die(unsigned int size); 167void *malloc_or_die(unsigned int size);
160 168
@@ -166,7 +174,7 @@ void print_funcs(void);
166void print_printk(void); 174void print_printk(void);
167 175
168int parse_ftrace_file(char *buf, unsigned long size); 176int parse_ftrace_file(char *buf, unsigned long size);
169int parse_event_file(char *buf, unsigned long size, char *system); 177int parse_event_file(char *buf, unsigned long size, char *sys);
170void print_event(int cpu, void *data, int size, unsigned long long nsecs, 178void print_event(int cpu, void *data, int size, unsigned long long nsecs,
171 char *comm); 179 char *comm);
172 180
@@ -233,13 +241,45 @@ extern int header_page_size_size;
233extern int header_page_data_offset; 241extern int header_page_data_offset;
234extern int header_page_data_size; 242extern int header_page_data_size;
235 243
244extern int latency_format;
245
236int parse_header_page(char *buf, unsigned long size); 246int parse_header_page(char *buf, unsigned long size);
237int trace_parse_common_type(void *data); 247int trace_parse_common_type(void *data);
248int trace_parse_common_pid(void *data);
249int parse_common_pc(void *data);
250int parse_common_flags(void *data);
251int parse_common_lock_depth(void *data);
238struct event *trace_find_event(int id); 252struct event *trace_find_event(int id);
253struct event *trace_find_next_event(struct event *event);
254unsigned long long read_size(void *ptr, int size);
239unsigned long long 255unsigned long long
240raw_field_value(struct event *event, const char *name, void *data); 256raw_field_value(struct event *event, const char *name, void *data);
241void *raw_field_ptr(struct event *event, const char *name, void *data); 257void *raw_field_ptr(struct event *event, const char *name, void *data);
258unsigned long long eval_flag(const char *flag);
259
260int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
261
262/* taken from kernel/trace/trace.h */
263enum trace_flag_type {
264 TRACE_FLAG_IRQS_OFF = 0x01,
265 TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
266 TRACE_FLAG_NEED_RESCHED = 0x04,
267 TRACE_FLAG_HARDIRQ = 0x08,
268 TRACE_FLAG_SOFTIRQ = 0x10,
269};
270
271struct scripting_ops {
272 const char *name;
273 int (*start_script) (const char *);
274 int (*stop_script) (void);
275 void (*process_event) (int cpu, void *data, int size,
276 unsigned long long nsecs, char *comm);
277 int (*generate_script) (const char *outfile);
278};
279
280int script_spec_register(const char *spec, struct scripting_ops *ops);
242 281
243void read_tracing_data(struct perf_event_attr *pattrs, int nb_events); 282extern struct scripting_ops perl_scripting_ops;
283void setup_perl_scripting(void);
244 284
245#endif /* _TRACE_EVENTS_H */ 285#endif /* __PERF_TRACE_EVENTS_H */
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 5e75f9005940..7d6b8331f898 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_TYPES_H 1#ifndef __PERF_TYPES_H
2#define _PERF_TYPES_H 2#define __PERF_TYPES_H
3 3
4/* 4/*
5 * We define u64 as unsigned long long for every architecture 5 * We define u64 as unsigned long long for every architecture
@@ -14,4 +14,4 @@ typedef signed short s16;
14typedef unsigned char u8; 14typedef unsigned char u8;
15typedef signed char s8; 15typedef signed char s8;
16 16
17#endif /* _PERF_TYPES_H */ 17#endif /* __PERF_TYPES_H */
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 9de2329dd44d..c673d8825883 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -84,6 +84,9 @@
84#include <iconv.h> 84#include <iconv.h>
85#endif 85#endif
86 86
87extern const char *graph_line;
88extern const char *graph_dotted_line;
89
87/* On most systems <limits.h> would have given us this, but 90/* On most systems <limits.h> would have given us this, but
88 * not on some systems (e.g. GNU/Hurd). 91 * not on some systems (e.g. GNU/Hurd).
89 */ 92 */
@@ -134,6 +137,15 @@ extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1,
134extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); 137extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
135extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); 138extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
136 139
140#include "../../../include/linux/stringify.h"
141
142#define DIE_IF(cnd) \
143 do { if (cnd) \
144 die(" at (" __FILE__ ":" __stringify(__LINE__) "): " \
145 __stringify(cnd) "\n"); \
146 } while (0)
147
148
137extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 149extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
138 150
139extern int prefixcmp(const char *str, const char *prefix); 151extern int prefixcmp(const char *str, const char *prefix);
@@ -278,17 +290,15 @@ static inline char *gitstrchrnul(const char *s, int c)
278 * Wrappers: 290 * Wrappers:
279 */ 291 */
280extern char *xstrdup(const char *str); 292extern char *xstrdup(const char *str);
281extern void *xmalloc(size_t size); 293extern void *xmalloc(size_t size) __attribute__((weak));
282extern void *xmemdupz(const void *data, size_t len); 294extern void *xmemdupz(const void *data, size_t len);
283extern char *xstrndup(const char *str, size_t len); 295extern char *xstrndup(const char *str, size_t len);
284extern void *xrealloc(void *ptr, size_t size); 296extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
285extern void *xcalloc(size_t nmemb, size_t size); 297
286extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); 298static inline void *zalloc(size_t size)
287extern ssize_t xread(int fd, void *buf, size_t len); 299{
288extern ssize_t xwrite(int fd, const void *buf, size_t len); 300 return calloc(1, size);
289extern int xdup(int fd); 301}
290extern FILE *xfdopen(int fd, const char *mode);
291extern int xmkstemp(char *template);
292 302
293static inline size_t xsize_t(off_t len) 303static inline size_t xsize_t(off_t len)
294{ 304{
@@ -306,6 +316,7 @@ static inline int has_extension(const char *filename, const char *ext)
306#undef isascii 316#undef isascii
307#undef isspace 317#undef isspace
308#undef isdigit 318#undef isdigit
319#undef isxdigit
309#undef isalpha 320#undef isalpha
310#undef isprint 321#undef isprint
311#undef isalnum 322#undef isalnum
@@ -323,6 +334,8 @@ extern unsigned char sane_ctype[256];
323#define isascii(x) (((x) & ~0x7f) == 0) 334#define isascii(x) (((x) & ~0x7f) == 0)
324#define isspace(x) sane_istest(x,GIT_SPACE) 335#define isspace(x) sane_istest(x,GIT_SPACE)
325#define isdigit(x) sane_istest(x,GIT_DIGIT) 336#define isdigit(x) sane_istest(x,GIT_DIGIT)
337#define isxdigit(x) \
338 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
326#define isalpha(x) sane_istest(x,GIT_ALPHA) 339#define isalpha(x) sane_istest(x,GIT_ALPHA)
327#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 340#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
328#define isprint(x) sane_istest(x,GIT_PRINT) 341#define isprint(x) sane_istest(x,GIT_PRINT)
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index cadf8cf2a590..2fa967e1a88a 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_VALUES_H 1#ifndef __PERF_VALUES_H
2#define _PERF_VALUES_H 2#define __PERF_VALUES_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -24,4 +24,4 @@ void perf_read_values_add_value(struct perf_read_values *values,
24void perf_read_values_display(FILE *fp, struct perf_read_values *values, 24void perf_read_values_display(FILE *fp, struct perf_read_values *values,
25 int raw); 25 int raw);
26 26
27#endif /* _PERF_VALUES_H */ 27#endif /* __PERF_VALUES_H */
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index 4574ac28396f..bf44ca85d23b 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -79,43 +79,12 @@ void *xrealloc(void *ptr, size_t size)
79 return ret; 79 return ret;
80} 80}
81 81
82void *xcalloc(size_t nmemb, size_t size)
83{
84 void *ret = calloc(nmemb, size);
85 if (!ret && (!nmemb || !size))
86 ret = calloc(1, 1);
87 if (!ret) {
88 release_pack_memory(nmemb * size, -1);
89 ret = calloc(nmemb, size);
90 if (!ret && (!nmemb || !size))
91 ret = calloc(1, 1);
92 if (!ret)
93 die("Out of memory, calloc failed");
94 }
95 return ret;
96}
97
98void *xmmap(void *start, size_t length,
99 int prot, int flags, int fd, off_t offset)
100{
101 void *ret = mmap(start, length, prot, flags, fd, offset);
102 if (ret == MAP_FAILED) {
103 if (!length)
104 return NULL;
105 release_pack_memory(length, fd);
106 ret = mmap(start, length, prot, flags, fd, offset);
107 if (ret == MAP_FAILED)
108 die("Out of memory? mmap failed: %s", strerror(errno));
109 }
110 return ret;
111}
112
113/* 82/*
114 * xread() is the same a read(), but it automatically restarts read() 83 * xread() is the same a read(), but it automatically restarts read()
115 * operations with a recoverable error (EAGAIN and EINTR). xread() 84 * operations with a recoverable error (EAGAIN and EINTR). xread()
116 * DOES NOT GUARANTEE that "len" bytes is read even if the data is available. 85 * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
117 */ 86 */
118ssize_t xread(int fd, void *buf, size_t len) 87static ssize_t xread(int fd, void *buf, size_t len)
119{ 88{
120 ssize_t nr; 89 ssize_t nr;
121 while (1) { 90 while (1) {
@@ -131,7 +100,7 @@ ssize_t xread(int fd, void *buf, size_t len)
131 * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT 100 * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
132 * GUARANTEE that "len" bytes is written even if the operation is successful. 101 * GUARANTEE that "len" bytes is written even if the operation is successful.
133 */ 102 */
134ssize_t xwrite(int fd, const void *buf, size_t len) 103static ssize_t xwrite(int fd, const void *buf, size_t len)
135{ 104{
136 ssize_t nr; 105 ssize_t nr;
137 while (1) { 106 while (1) {
@@ -179,29 +148,3 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
179 148
180 return total; 149 return total;
181} 150}
182
183int xdup(int fd)
184{
185 int ret = dup(fd);
186 if (ret < 0)
187 die("dup failed: %s", strerror(errno));
188 return ret;
189}
190
191FILE *xfdopen(int fd, const char *mode)
192{
193 FILE *stream = fdopen(fd, mode);
194 if (stream == NULL)
195 die("Out of memory? fdopen failed: %s", strerror(errno));
196 return stream;
197}
198
199int xmkstemp(char *template)
200{
201 int fd;
202
203 fd = mkstemp(template);
204 if (fd < 0)
205 die("Unable to create temporary file: %s", strerror(errno));
206 return fd;
207}