diff options
484 files changed, 8273 insertions, 6623 deletions
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index e3698666357..f3f37f141db 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -184,8 +184,6 @@ usage should require reading the full document. !Finclude/net/mac80211.h ieee80211_ctstoself_get !Finclude/net/mac80211.h ieee80211_ctstoself_duration !Finclude/net/mac80211.h ieee80211_generic_frame_duration -!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb -!Finclude/net/mac80211.h ieee80211_hdrlen !Finclude/net/mac80211.h ieee80211_wake_queue !Finclude/net/mac80211.h ieee80211_stop_queue !Finclude/net/mac80211.h ieee80211_wake_queues diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index a52adfc9a57..3d1b0ab70c8 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -25,7 +25,7 @@ use IO::Handle; "tda10046lifeview", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "or51211", "or51132_qam", "or51132_vsb", "bluebird", - "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" ); + "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718" ); # Check args syntax() if (scalar(@ARGV) != 1); @@ -381,6 +381,57 @@ sub cx18 { $allfiles; } +sub mpc718 { + my $archive = 'Yuan MPC718 TV Tuner Card 2.13.10.1016.zip'; + my $url = "ftp://ftp.work.acer-euro.com/desktop/aspire_idea510/vista/Drivers/$archive"; + my $fwfile = "dvb-cx18-mpc718-mt352.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + + checkstandard(); + wgetfile($archive, $url); + unzip($archive, $tmpdir); + + my $sourcefile = "$tmpdir/Yuan MPC718 TV Tuner Card 2.13.10.1016/mpc718_32bit/yuanrap.sys"; + my $found = 0; + + open IN, '<', $sourcefile or die "Couldn't open $sourcefile to extract $fwfile data\n"; + binmode IN; + open OUT, '>', $fwfile; + binmode OUT; + { + # Block scope because we change the line terminator variable $/ + my $prevlen = 0; + my $currlen; + + # Buried in the data segment are 3 runs of almost identical + # register-value pairs that end in 0x5d 0x01 which is a "TUNER GO" + # command for the MT352. + # Pull out the middle run (because it's easy) of register-value + # pairs to make the "firmware" file. + + local $/ = "\x5d\x01"; # MT352 "TUNER GO" + + while (<IN>) { + $currlen = length($_); + if ($prevlen == $currlen && $currlen <= 64) { + chop; chop; # Get rid of "TUNER GO" + s/^\0\0//; # get rid of leading 00 00 if it's there + printf OUT "$_"; + $found = 1; + last; + } + $prevlen = $currlen; + } + } + close OUT; + close IN; + if (!$found) { + unlink $fwfile; + die "Couldn't find valid register-value sequence in $sourcefile for $fwfile\n"; + } + $fwfile; +} + sub cx23885 { my $url = "http://linuxtv.org/downloads/firmware/"; diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index f8cd450be9a..09e031c5588 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -458,3 +458,13 @@ Why: Remove the old legacy 32bit machine check code. This has been but the old version has been kept around for easier testing. Note this doesn't impact the old P5 and WinChip machine check handlers. Who: Andi Kleen <andi@firstfloor.org> + +---------------------------- + +What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be + exported interface anymore. +When: 2.6.33 +Why: cpu_policy_rwsem has a new cleaner definition making it local to + cpufreq core and contained inside cpufreq.c. Other dependent + drivers should not use it in order to safely avoid lockdep issues. +Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d77fbd8b79a..dd1a6d4bb74 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1720,8 +1720,8 @@ and is between 256 and 4096 characters. It is defined in the file oprofile.cpu_type= Force an oprofile cpu type This might be useful if you have an older oprofile userland or if you want common events. - Format: { archperfmon } - archperfmon: [X86] Force use of architectural + Format: { arch_perfmon } + arch_perfmon: [X86] Force use of architectural perfmon on Intel CPUs instead of the CPU specific event set. diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 873630e7e53..014d255231f 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -66,3 +66,4 @@ 68 -> Terratec AV350 (em2860) [0ccd:0084] 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313] 70 -> Evga inDtube (em2882) + 71 -> Silvercrest Webcam 1.3mpix (em2820/em2840) diff --git a/MAINTAINERS b/MAINTAINERS index 381190c7949..e4b1a3d596c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5803,17 +5803,17 @@ P: Jiri Kosina M: trivial@kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git S: Maintained -F: drivers/char/tty_* -F: drivers/serial/serial_core.c -F: include/linux/serial_core.h -F: include/linux/serial.h -F: include/linux/tty.h TTY LAYER P: Alan Cox M: alan@lxorguk.ukuu.org.uk S: Maintained T: stgit http://zeniv.linux.org.uk/~alan/ttydev/ +F: drivers/char/tty_* +F: drivers/serial/serial_core.c +F: include/linux/serial_core.h +F: include/linux/serial.h +F: include/linux/tty.h TULIP NETWORK DRIVERS P: Grant Grundler diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h index d069526bd76..60c83abfde7 100644 --- a/arch/alpha/include/asm/thread_info.h +++ b/arch/alpha/include/asm/thread_info.h @@ -37,6 +37,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .addr_limit = KERNEL_DS, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig index 8e74c66f239..605a8462f17 100644 --- a/arch/arm/configs/kb9202_defconfig +++ b/arch/arm/configs/kb9202_defconfig @@ -1,109 +1,246 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Sun Aug 14 19:26:59 2005 +# Linux kernel version: 2.6.30-rc8 +# Wed Jun 3 13:52:33 2009 # CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -CONFIG_UID16=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # -# CONFIG_EXPERIMENTAL is not set -CONFIG_CLEAN_COMPILE=y +CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -# CONFIG_KOBJECT_UEVENT is not set -# CONFIG_IKCONFIG is not set +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_TRACEPOINTS=y +CONFIG_MARKERS=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # -# Loadable module support +# IO Schedulers # -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set # # System Type # -# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set -CONFIG_ARCH_AT91=y +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# Atmel AT91 System-on-Chip +# CONFIG_ARCH_AT91RM9200=y +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y # -# AT91RM9200 Implementations +# AT91RM9200 Board Type # +# CONFIG_MACH_ONEARM is not set # CONFIG_ARCH_AT91RM9200DK is not set # CONFIG_MACH_AT91RM9200EK is not set # CONFIG_MACH_CSB337 is not set # CONFIG_MACH_CSB637 is not set # CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_ATEB9200 is not set CONFIG_MACH_KB9200=y +# CONFIG_MACH_PICOTUX2XX is not set +# CONFIG_MACH_KAFA is not set +# CONFIG_MACH_ECBAT91 is not set +# CONFIG_MACH_YL9200 is not set + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_TIMER_HZ=128 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set # # Processor Type # CONFIG_CPU_32=y CONFIG_CPU_ARM920T=y -CONFIG_CPU_32v4=y +CONFIG_CPU_32v4T=y CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_V4WT=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y # # Processor Features @@ -112,23 +249,48 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set # # Bus support # -CONFIG_ISA_DMA_API=y - -# -# PCCARD (PCMCIA/CardBus) support -# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -137,8 +299,16 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x10000000 CONFIG_ZBOOT_ROM_BSS=0x20040000 -CONFIG_ZBOOT_ROM=y -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" +# CONFIG_ZBOOT_ROM is not set +CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -149,74 +319,251 @@ CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" # CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set # # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y -# CONFIG_ARTHUR is not set # # Power management options # # CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y # -# Device Drivers +# Networking options # +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # -# Generic Driver Options +# Network testing # -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -CONFIG_DEBUG_DRIVER=y +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # -# Memory Technology Devices (MTD) +# Device Drivers # -# CONFIG_MTD is not set # -# Parallel port support +# Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set +CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=y + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +CONFIG_ATMEL_TCLIB=y +CONFIG_ATMEL_TCB_CLKSRC=y +CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 +CONFIG_ATMEL_SSC=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set # -# IO Schedulers +# EEPROM support # -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -232,145 +579,87 @@ CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # -# CONFIG_SCSI_SPI_ATTRS is not set +CONFIG_SCSI_SPI_ATTRS=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_ARM_AT91_ETHER=y +# CONFIG_AX88796 is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set # -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices +# Wireless LAN # +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wireless LAN (non-hamradio) +# Enable WiMAX (Networking options) to see the WiMAX drivers # -# CONFIG_NET_RADIO is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set - -# -# ISDN subsystem -# +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_ISDN is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -380,7 +669,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -390,23 +678,25 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set # # Hardware I/O ports # -CONFIG_SERIO=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set # # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -419,215 +709,362 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set # -# IPMI +# Memory mapped GPIO expanders: # -# CONFIG_IPMI_HANDLER is not set # -# Watchdog Cards +# I2C GPIO expanders: # -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_AT91RM9200_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set # -# Ftape, the floppy tape device driver +# PCI GPIO expanders: # -# CONFIG_RAW_DRIVER is not set # -# TPM devices +# SPI GPIO expanders: # -# CONFIG_AT91_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set # -# I2C support +# Watchdog Device Drivers # -# CONFIG_I2C is not set +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91RM9200_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # -# Misc devices +# Sonics Silicon Backplane # +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set # -# Digital Video Broadcasting Devices +# Multimedia drivers # -# CONFIG_DVB is not set +# CONFIG_DAB is not set # # Graphics support # -# CONFIG_FB is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +CONFIG_FONT_MINI_4x6=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_LOGO is not set # CONFIG_SOUND is not set - -# -# USB support -# +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y -CONFIG_USB_DEBUG=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set # # USB Device Class drivers # -# CONFIG_USB_BLUETOOTH_TTY is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DEBUG=y -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_DPCM is not set - -# -# USB Input Devices -# -# CONFIG_USB_HID is not set # -# USB HID Boot Protocol drivers +# also be needed; see USB_STORAGE Help for more info # -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y # # USB Imaging devices # +# CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set # -# USB Multimedia devices +# USB port drivers # -# CONFIG_USB_DABUSB is not set +# CONFIG_USB_SERIAL is not set # -# Video4Linux support is needed for USB Multimedia device support +# USB Miscellaneous drivers # +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set # -# USB Network Adapters +# OTG and related infrastructure # -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_MON is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set # -# USB port drivers +# MMC/SD/SDIO Card Drivers # +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set # -# USB Serial Converter support +# MMC/SD/SDIO Host Controller Drivers # -# CONFIG_USB_SERIAL is not set +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# USB Miscellaneous drivers +# RTC interfaces # -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# USB DSL modem support +# SPI RTC drivers # # -# USB Gadget Support +# Platform RTC drivers # -# CONFIG_USB_GADGET is not set +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# MMC/SD Card support +# on-CPU RTC drivers # -# CONFIG_MMC is not set +CONFIG_RTC_DRV_AT91RM9200=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems # CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # -# XFS support +# Caches # -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +# CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems @@ -639,7 +1076,7 @@ CONFIG_AUTOFS4_FS=y # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" @@ -649,53 +1086,70 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_UBIFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFSD is not set +# CONFIG_NFS_V4 is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y -CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -719,7 +1173,7 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -733,47 +1187,119 @@ CONFIG_NLS_ASCII=y # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set # # Security options # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set # CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# +# CONFIG_BINARY_PRINTF is not set # # Library routines # +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig index 2d827e12114..4762d900129 100644 --- a/arch/arm/configs/u300_defconfig +++ b/arch/arm/configs/u300_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.30-rc6 -# Mon Jun 1 09:18:22 2009 +# Linux kernel version: 2.6.31-rc1 +# Thu Jul 2 00:16:59 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -9,7 +9,7 @@ CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -# CONFIG_NO_IOPORT is not set +CONFIG_HAVE_TCM=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -18,13 +18,12 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y # # General setup @@ -68,7 +67,6 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y @@ -81,8 +79,13 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set + +# +# Performance Counters +# # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y @@ -94,6 +97,10 @@ CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -106,7 +113,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y -# CONFIG_LBD is not set +CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -138,9 +145,9 @@ CONFIG_DEFAULT_IOSCHED="deadline" # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IMX is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -216,8 +223,8 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_CPU_CACHE_ROUND_ROBIN is not set -# CONFIG_OUTER_CACHE is not set CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 CONFIG_COMMON_CLKDEV=y # @@ -243,7 +250,6 @@ CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -CONFIG_ARCH_FLATMEM_HAS_HOLES=y # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_HIGHMEM is not set @@ -258,17 +264,18 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y -CONFIG_UNEVICTABLE_LRU=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set # # Boot options # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/mtdblock2 rw rootfstype=yaffs2 console=ttyAMA0,115200n8 ab3100.force=0,0x48 mtdparts=u300nand:128k@0x0(bootrecords)ro,8064k@128k(free)ro,253952k@8192k(platform) lpj=515072" +CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set @@ -359,6 +366,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -497,6 +505,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_AT24 is not set # CONFIG_EEPROM_AT25 is not set # CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -538,6 +547,7 @@ CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_GPIO is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set @@ -597,9 +607,11 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_STU300=y # # External I2C/SMBus adapter drivers @@ -620,7 +632,6 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set @@ -635,6 +646,7 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set +CONFIG_SPI_PL022=y # # SPI Protocol Masters @@ -647,6 +659,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_PDA_POWER is not set # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set @@ -657,6 +670,7 @@ CONFIG_WATCHDOG=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set +CONFIG_COH901327_WATCHDOG=y CONFIG_SSB_POSSIBLE=y # @@ -678,22 +692,9 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_PCF50633 is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set +CONFIG_AB3100_CORE=y +# CONFIG_EZX_PCAP is not set +# CONFIG_MEDIA_SUPPORT is not set # # Graphics support @@ -760,6 +761,11 @@ CONFIG_SND_JACK=y # CONFIG_SND_VERBOSE_PROCFS is not set # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set # CONFIG_SND_DRIVERS is not set # CONFIG_SND_ARM is not set # CONFIG_SND_SPI is not set @@ -770,7 +776,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DEBUG=y # CONFIG_MMC_UNSAFE_RESUME is not set # @@ -797,7 +803,7 @@ CONFIG_LEDS_CLASS=y # # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_GPIO is not set -# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_BD2802 is not set @@ -845,6 +851,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set # # SPI RTC drivers @@ -887,7 +894,10 @@ CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_LP3971 is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set @@ -900,16 +910,20 @@ CONFIG_REGULATOR=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set # # Caches @@ -1033,6 +1047,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1063,18 +1078,16 @@ CONFIG_DEBUG_INFO=y # CONFIG_PAGE_POISONING is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y - -# -# Tracers -# +CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_EVENT_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set # CONFIG_BOOT_TRACER is not set -# CONFIG_TRACE_BRANCH_PROFILING is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1109,6 +1122,7 @@ CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC32 is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_ALLOCATOR=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 1cd2d6416bd..c433c6c7311 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -285,15 +285,6 @@ extern struct page *empty_zero_page; #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) #define pte_special(pte) (0) -/* - * The following only works if pte_present() is not true. - */ -#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) -#define pte_to_pgoff(x) (pte_val(x) >> 2) -#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) - -#define PTE_FILE_MAX_BITS 30 - #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -384,16 +375,50 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -/* Encode and decode a swap entry. +/* + * Encode and decode a swap entry. Swap entries are stored in the Linux + * page tables as follows: * - * We support up to 32GB of swap on 4k machines + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * <--------------- offset --------------------> <--- type --> 0 0 + * + * This gives us up to 127 swap files and 32GB per swap file. Note that + * the offset field is always non-zero. */ -#define __swp_type(x) (((x).val >> 2) & 0x7f) -#define __swp_offset(x) ((x).val >> 9) -#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) +#define __SWP_TYPE_SHIFT 2 +#define __SWP_TYPE_BITS 7 +#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) +#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) + +#define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) +#define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) + #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) +/* + * It is an error for the kernel to have more swap files than we can + * encode in the PTEs. This ensures that we know when MAX_SWAPFILES + * is increased beyond what we presently support. + */ +#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) + +/* + * Encode and decode a file entry. File entries are stored in the Linux + * page tables as follows: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * <------------------------ offset -------------------------> 1 0 + */ +#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) +#define pte_to_pgoff(x) (pte_val(x) >> 2) +#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) + +#define PTE_FILE_MAX_BITS 30 + /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ #define kern_addr_valid(addr) (1) diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 4f8848260ee..73394e50cbc 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -73,7 +73,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 5cd04d6751b..111f7ea32b3 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/timer.h> #include <linux/io.h> +#include <linux/seq_file.h> #include <asm/clkdev.h> #include <mach/hardware.h> @@ -702,6 +703,7 @@ static struct clk amba_clk = { .rate = 52000000, /* this varies! */ .hw_ctrld = true, .reset = false, + .lock = __SPIN_LOCK_UNLOCKED(amba_clk.lock), }; /* @@ -720,6 +722,7 @@ static struct clk cpu_clk = { .set_rate = clk_set_rate_cpuclk, .get_rate = clk_get_rate_cpuclk, .round_rate = clk_round_rate_cpuclk, + .lock = __SPIN_LOCK_UNLOCKED(cpu_clk.lock), }; static struct clk nandif_clk = { @@ -732,6 +735,7 @@ static struct clk nandif_clk = { .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(nandif_clk.lock), }; static struct clk semi_clk = { @@ -744,6 +748,7 @@ static struct clk semi_clk = { .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(semi_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -758,6 +763,7 @@ static struct clk isp_clk = { .clk_val = U300_SYSCON_SBCER_ISP_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(isp_clk.lock), }; static struct clk cds_clk = { @@ -771,6 +777,7 @@ static struct clk cds_clk = { .clk_val = U300_SYSCON_SBCER_CDS_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(cds_clk.lock), }; #endif @@ -785,6 +792,7 @@ static struct clk dma_clk = { .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(dma_clk.lock), }; static struct clk aaif_clk = { @@ -798,6 +806,7 @@ static struct clk aaif_clk = { .clk_val = U300_SYSCON_SBCER_AAIF_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(aaif_clk.lock), }; static struct clk apex_clk = { @@ -811,6 +820,7 @@ static struct clk apex_clk = { .clk_val = U300_SYSCON_SBCER_APEX_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(apex_clk.lock), }; static struct clk video_enc_clk = { @@ -825,6 +835,7 @@ static struct clk video_enc_clk = { .clk_val = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock), }; static struct clk xgam_clk = { @@ -839,6 +850,7 @@ static struct clk xgam_clk = { .get_rate = clk_get_rate_xgamclk, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(xgam_clk.lock), }; /* This clock is used to activate the video encoder */ @@ -854,6 +866,7 @@ static struct clk ahb_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_ahb_clk, + .lock = __SPIN_LOCK_UNLOCKED(ahb_clk.lock), }; @@ -871,6 +884,7 @@ static struct clk ahb_subsys_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_ahb_clk, + .lock = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock), }; static struct clk intcon_clk = { @@ -882,6 +896,8 @@ static struct clk intcon_clk = { .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, .res_mask = U300_SYSCON_RRR_INTCON_RESET_EN, /* INTCON can be reset but not clock-gated */ + .lock = __SPIN_LOCK_UNLOCKED(intcon_clk.lock), + }; static struct clk mspro_clk = { @@ -895,6 +911,7 @@ static struct clk mspro_clk = { .clk_val = U300_SYSCON_SBCER_MSPRO_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(mspro_clk.lock), }; static struct clk emif_clk = { @@ -909,6 +926,7 @@ static struct clk emif_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_emif_clk, + .lock = __SPIN_LOCK_UNLOCKED(emif_clk.lock), }; @@ -926,6 +944,7 @@ static struct clk fast_clk = { .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(fast_clk.lock), }; static struct clk mmcsd_clk = { @@ -942,6 +961,7 @@ static struct clk mmcsd_clk = { .round_rate = clk_round_rate_mclk, .disable = syscon_clk_disable, .enable = syscon_clk_enable, + .lock = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock), }; static struct clk i2s0_clk = { @@ -956,6 +976,7 @@ static struct clk i2s0_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock), }; static struct clk i2s1_clk = { @@ -970,6 +991,7 @@ static struct clk i2s1_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock), }; static struct clk i2c0_clk = { @@ -984,6 +1006,7 @@ static struct clk i2c0_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock), }; static struct clk i2c1_clk = { @@ -998,6 +1021,7 @@ static struct clk i2c1_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock), }; static struct clk spi_clk = { @@ -1012,6 +1036,7 @@ static struct clk spi_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(spi_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -1026,6 +1051,7 @@ static struct clk uart1_clk = { .clk_val = U300_SYSCON_SBCER_UART1_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(uart1_clk.lock), }; #endif @@ -1044,6 +1070,7 @@ static struct clk slow_clk = { .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(slow_clk.lock), }; /* TODO: implement SYSCON clock? */ @@ -1055,6 +1082,7 @@ static struct clk wdog_clk = { .rate = 32768, .reset = false, /* This is always on, cannot be enabled/disabled or reset */ + .lock = __SPIN_LOCK_UNLOCKED(wdog_clk.lock), }; /* This one is hardwired to PLL13 */ @@ -1069,6 +1097,7 @@ static struct clk uart_clk = { .clk_val = U300_SYSCON_SBCER_UART_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(uart_clk.lock), }; static struct clk keypad_clk = { @@ -1082,6 +1111,7 @@ static struct clk keypad_clk = { .clk_val = U300_SYSCON_SBCER_KEYPAD_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(keypad_clk.lock), }; static struct clk gpio_clk = { @@ -1095,6 +1125,7 @@ static struct clk gpio_clk = { .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(gpio_clk.lock), }; static struct clk rtc_clk = { @@ -1106,6 +1137,7 @@ static struct clk rtc_clk = { .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, .res_mask = U300_SYSCON_RSR_RTC_RESET_EN, /* This clock is always on, cannot be enabled/disabled */ + .lock = __SPIN_LOCK_UNLOCKED(rtc_clk.lock), }; static struct clk bustr_clk = { @@ -1119,6 +1151,7 @@ static struct clk bustr_clk = { .clk_val = U300_SYSCON_SBCER_BTR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(bustr_clk.lock), }; static struct clk evhist_clk = { @@ -1132,6 +1165,7 @@ static struct clk evhist_clk = { .clk_val = U300_SYSCON_SBCER_EH_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(evhist_clk.lock), }; static struct clk timer_clk = { @@ -1145,6 +1179,7 @@ static struct clk timer_clk = { .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(timer_clk.lock), }; static struct clk app_timer_clk = { @@ -1158,6 +1193,7 @@ static struct clk app_timer_clk = { .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -1172,6 +1208,7 @@ static struct clk ppm_clk = { .clk_val = U300_SYSCON_SBCER_PPM_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(ppm_clk.lock), }; #endif @@ -1187,53 +1224,53 @@ static struct clk ppm_clk = { */ static struct clk_lookup lookups[] = { /* Connected directly to the AMBA bus */ - DEF_LOOKUP("amba", &amba_clk), - DEF_LOOKUP("cpu", &cpu_clk), - DEF_LOOKUP("nandif", &nandif_clk), - DEF_LOOKUP("semi", &semi_clk), + DEF_LOOKUP("amba", &amba_clk), + DEF_LOOKUP("cpu", &cpu_clk), + DEF_LOOKUP("fsmc", &nandif_clk), + DEF_LOOKUP("semi", &semi_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("isp", &isp_clk), - DEF_LOOKUP("cds", &cds_clk), + DEF_LOOKUP("isp", &isp_clk), + DEF_LOOKUP("cds", &cds_clk), #endif - DEF_LOOKUP("dma", &dma_clk), - DEF_LOOKUP("aaif", &aaif_clk), - DEF_LOOKUP("apex", &apex_clk), + DEF_LOOKUP("dma", &dma_clk), + DEF_LOOKUP("msl", &aaif_clk), + DEF_LOOKUP("apex", &apex_clk), DEF_LOOKUP("video_enc", &video_enc_clk), - DEF_LOOKUP("xgam", &xgam_clk), - DEF_LOOKUP("ahb", &ahb_clk), + DEF_LOOKUP("xgam", &xgam_clk), + DEF_LOOKUP("ahb", &ahb_clk), /* AHB bridge clocks */ - DEF_LOOKUP("ahb", &ahb_subsys_clk), - DEF_LOOKUP("intcon", &intcon_clk), - DEF_LOOKUP("mspro", &mspro_clk), - DEF_LOOKUP("pl172", &emif_clk), + DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk), + DEF_LOOKUP("intcon", &intcon_clk), + DEF_LOOKUP("mspro", &mspro_clk), + DEF_LOOKUP("pl172", &emif_clk), /* FAST bridge clocks */ - DEF_LOOKUP("fast", &fast_clk), - DEF_LOOKUP("mmci", &mmcsd_clk), + DEF_LOOKUP("fast", &fast_clk), + DEF_LOOKUP("mmci", &mmcsd_clk), /* * The .0 and .1 identifiers on these comes from the platform device * .id field and are assigned when the platform devices are registered. */ - DEF_LOOKUP("i2s.0", &i2s0_clk), - DEF_LOOKUP("i2s.1", &i2s1_clk), - DEF_LOOKUP("stddci2c.0", &i2c0_clk), - DEF_LOOKUP("stddci2c.1", &i2c1_clk), - DEF_LOOKUP("pl022", &spi_clk), + DEF_LOOKUP("i2s.0", &i2s0_clk), + DEF_LOOKUP("i2s.1", &i2s1_clk), + DEF_LOOKUP("stu300.0", &i2c0_clk), + DEF_LOOKUP("stu300.1", &i2c1_clk), + DEF_LOOKUP("pl022", &spi_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("uart1", &uart1_clk), + DEF_LOOKUP("uart1", &uart1_clk), #endif /* SLOW bridge clocks */ - DEF_LOOKUP("slow", &slow_clk), - DEF_LOOKUP("wdog", &wdog_clk), - DEF_LOOKUP("uart0", &uart_clk), - DEF_LOOKUP("apptimer", &app_timer_clk), - DEF_LOOKUP("keypad", &keypad_clk), + DEF_LOOKUP("slow", &slow_clk), + DEF_LOOKUP("coh901327_wdog", &wdog_clk), + DEF_LOOKUP("uart0", &uart_clk), + DEF_LOOKUP("apptimer", &app_timer_clk), + DEF_LOOKUP("coh901461-keypad", &keypad_clk), DEF_LOOKUP("u300-gpio", &gpio_clk), - DEF_LOOKUP("rtc0", &rtc_clk), - DEF_LOOKUP("bustr", &bustr_clk), - DEF_LOOKUP("evhist", &evhist_clk), - DEF_LOOKUP("timer", &timer_clk), + DEF_LOOKUP("rtc-coh901331", &rtc_clk), + DEF_LOOKUP("bustr", &bustr_clk), + DEF_LOOKUP("evhist", &evhist_clk), + DEF_LOOKUP("timer", &timer_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("ppm", &ppm_clk), + DEF_LOOKUP("ppm", &ppm_clk), #endif }; @@ -1427,16 +1464,20 @@ static const struct file_operations u300_clocks_operations = { .release = single_release, }; -static void init_clk_read_procfs(void) +static int __init init_clk_read_debugfs(void) { /* Expose a simple debugfs interface to view all clocks */ (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO, - NULL, NULL, &u300_clocks_operations); -} -#else -static inline void init_clk_read_procfs(void) -{ + NULL, NULL, + &u300_clocks_operations); + return 0; } +/* + * This needs to come in after the core_initcall() for the + * overall clocks, because debugfs is not available until + * the subsystems come up. + */ +module_init(init_clk_read_debugfs); #endif static int __init u300_clock_init(void) @@ -1462,8 +1503,6 @@ static int __init u300_clock_init(void) clk_register(); - init_clk_read_procfs(); - /* * Some of these may be on when we boot the system so make sure they * are turned OFF. diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index 195e48edd8c..ac5c80062b7 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all); EXPORT_SYMBOL(__cpuc_flush_user_all); EXPORT_SYMBOL(__cpuc_flush_user_range); EXPORT_SYMBOL(__cpuc_coherent_kern_range); +EXPORT_SYMBOL(__cpuc_flush_dcache_page); EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */ #else EXPORT_SYMBOL(cpu_cache); diff --git a/arch/avr32/include/asm/thread_info.h b/arch/avr32/include/asm/thread_info.h index 4442f8d2d42..fc42de5ca20 100644 --- a/arch/avr32/include/asm/thread_info.h +++ b/arch/avr32/include/asm/thread_info.h @@ -40,7 +40,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall \ } \ diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 6e3d491184e..b91b2044af9 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -32,22 +32,25 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); - printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG, + printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); + + printk(KERN_EMERG); + #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk(KERN_CONT "PREEMPT "); #endif #ifdef CONFIG_FRAME_POINTER - printk("FRAME_POINTER "); + printk(KERN_CONT "FRAME_POINTER "); #endif if (current_cpu_data.features & AVR32_FEATURE_OCD) { unsigned long did = ocd_read(DID); - printk("chip: 0x%03lx:0x%04lx rev %lu\n", + printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n", (did >> 1) & 0x7ff, (did >> 12) & 0x7fff, (did >> 28) & 0xf); } else { - printk("cpu: arch %u r%u / core %u r%u\n", + printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n", current_cpu_data.arch_type, current_cpu_data.arch_revision, current_cpu_data.cpu_type, diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h index 2920087516f..2bbfdd950af 100644 --- a/arch/blackfin/include/asm/thread_info.h +++ b/arch/blackfin/include/asm/thread_info.h @@ -77,7 +77,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 298f023bcc0..6136c33e919 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -408,13 +408,14 @@ static void __init print_memory_map(char *who) bfin_memmap.map[i].addr + bfin_memmap.map[i].size); switch (bfin_memmap.map[i].type) { case BFIN_MEMMAP_RAM: - printk("(usable)\n"); - break; + printk(KERN_CONT "(usable)\n"); + break; case BFIN_MEMMAP_RESERVED: - printk("(reserved)\n"); - break; - default: printk("type %lu\n", bfin_memmap.map[i].type); - break; + printk(KERN_CONT "(reserved)\n"); + break; + default: + printk(KERN_CONT "type %lu\n", bfin_memmap.map[i].type); + break; } } } @@ -614,19 +615,19 @@ static __init void memory_setup(void) printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); printk(KERN_INFO "Memory map:\n" - KERN_INFO " fixedcode = 0x%p-0x%p\n" - KERN_INFO " text = 0x%p-0x%p\n" - KERN_INFO " rodata = 0x%p-0x%p\n" - KERN_INFO " bss = 0x%p-0x%p\n" - KERN_INFO " data = 0x%p-0x%p\n" - KERN_INFO " stack = 0x%p-0x%p\n" - KERN_INFO " init = 0x%p-0x%p\n" - KERN_INFO " available = 0x%p-0x%p\n" + " fixedcode = 0x%p-0x%p\n" + " text = 0x%p-0x%p\n" + " rodata = 0x%p-0x%p\n" + " bss = 0x%p-0x%p\n" + " data = 0x%p-0x%p\n" + " stack = 0x%p-0x%p\n" + " init = 0x%p-0x%p\n" + " available = 0x%p-0x%p\n" #ifdef CONFIG_MTD_UCLINUX - KERN_INFO " rootfs = 0x%p-0x%p\n" + " rootfs = 0x%p-0x%p\n" #endif #if DMA_UNCACHED_REGION > 0 - KERN_INFO " DMA Zone = 0x%p-0x%p\n" + " DMA Zone = 0x%p-0x%p\n" #endif , (void *)FIXED_CODE_START, (void *)FIXED_CODE_END, _stext, _etext, @@ -859,13 +860,13 @@ void __init setup_arch(char **cmdline_p) #endif printk(KERN_INFO "Hardware Trace "); if (bfin_read_TBUFCTL() & 0x1) - printk("Active "); + printk(KERN_CONT "Active "); else - printk("Off "); + printk(KERN_CONT "Off "); if (bfin_read_TBUFCTL() & 0x2) - printk("and Enabled\n"); + printk(KERN_CONT "and Enabled\n"); else - printk("and Disabled\n"); + printk(KERN_CONT "and Disabled\n"); #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) /* we need to initialize the Flashrom device here since we might diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8eeb457ce5d..8a1caf2bb5b 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -212,7 +212,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) console_verbose(); oops_in_progress = 1; #ifdef CONFIG_DEBUG_VERBOSE - printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); + printk(KERN_EMERG "Double Fault\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { unsigned int cpu = smp_processor_id(); @@ -583,15 +583,14 @@ asmlinkage void trap_c(struct pt_regs *fp) #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) verbose_printk(KERN_NOTICE "No trace since you do not have " - "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" - KERN_NOTICE "\n"); + "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n"); else #endif dump_bfin_trace_buffer(); if (oops_in_progress) { /* Dump the current kernel stack */ - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); + verbose_printk(KERN_NOTICE "Kernel Stack\n"); show_stack(current, NULL); print_modules(); #ifndef CONFIG_ACCESS_CHECK @@ -906,7 +905,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) ret_addr = 0; if (!j && i % 8 == 0) - printk("\n" KERN_NOTICE "%p:",addr); + printk(KERN_NOTICE "%p:",addr); /* if it is an odd address, or zero, just skip it */ if (*addr & 0x1 || !*addr) @@ -996,9 +995,9 @@ void dump_bfin_process(struct pt_regs *fp) printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu); if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) - verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" - KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" - KERN_NOTICE "\n", + verbose_printk(KERN_NOTICE + "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + " BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n", (void *)current->mm->start_code, (void *)current->mm->end_code, (void *)current->mm->start_data, @@ -1009,8 +1008,8 @@ void dump_bfin_process(struct pt_regs *fp) else verbose_printk(KERN_NOTICE "invalid mm\n"); } else - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE - "No Valid process in current context\n"); + verbose_printk(KERN_NOTICE + "No Valid process in current context\n"); #endif } @@ -1028,7 +1027,7 @@ void dump_bfin_mem(struct pt_regs *fp) addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; addr++) { if (!((unsigned long)addr & 0xF)) - verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); + verbose_printk(KERN_NOTICE "0x%p: ", addr); if (!get_instruction(&val, addr)) { val = 0; @@ -1056,9 +1055,9 @@ void dump_bfin_mem(struct pt_regs *fp) oops_in_progress)){ verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); #ifndef CONFIG_DEBUG_HWERR - verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" - KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" - " better idea where it came from\n"); + verbose_printk(KERN_NOTICE +"The remaining message may be meaningless\n" +"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n"); #else /* If we are handling only one peripheral interrupt * and current mm and pid are valid, and the last error @@ -1114,9 +1113,10 @@ void show_regs(struct pt_regs *fp) verbose_printk(KERN_NOTICE "%s", linux_banner); - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); + verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", + print_tainted()); verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", - (long)fp->seqstat, fp->ipend, fp->syscfg); + (long)fp->seqstat, fp->ipend, fp->syscfg); if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); @@ -1184,7 +1184,7 @@ unlock: verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); } - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); + verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n"); verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", fp->r0, fp->r1, fp->r2, fp->r3); verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h index bc5b2935ca5..c3aade36c33 100644 --- a/arch/cris/include/asm/thread_info.h +++ b/arch/cris/include/asm/thread_info.h @@ -50,8 +50,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ #define INIT_THREAD_INFO(tsk) \ @@ -60,7 +58,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h index e8a5ed7be02..e608e056bb5 100644 --- a/arch/frv/include/asm/thread_info.h +++ b/arch/frv/include/asm/thread_info.h @@ -56,8 +56,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -67,7 +65,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h index 700014d2155..8bbc8b0ee45 100644 --- a/arch/h8300/include/asm/thread_info.h +++ b/arch/h8300/include/asm/thread_info.h @@ -36,7 +36,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h index ae6922626bf..8ce2e388e37 100644 --- a/arch/ia64/include/asm/thread_info.h +++ b/arch/ia64/include/asm/thread_info.h @@ -48,7 +48,7 @@ struct thread_info { .flags = 0, \ .cpu = 0, \ .addr_limit = KERNEL_DS, \ - .preempt_count = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 729298f4b23..7de76dd352f 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -537,7 +537,7 @@ pcibios_align_resource (void *data, struct resource *res, /* * PCI BIOS setup, always defaults to SAL interface */ -char * __devinit +char * __init pcibios_setup (char *str) { return str; diff --git a/arch/m32r/include/asm/thread_info.h b/arch/m32r/include/asm/thread_info.h index 8589d462df2..07bb5bd00e2 100644 --- a/arch/m32r/include/asm/thread_info.h +++ b/arch/m32r/include/asm/thread_info.h @@ -57,8 +57,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -68,7 +66,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/m68k/include/asm/thread_info_mm.h b/arch/m68k/include/asm/thread_info_mm.h index af0fda46e94..6ea5c33b3c5 100644 --- a/arch/m68k/include/asm/thread_info_mm.h +++ b/arch/m68k/include/asm/thread_info_mm.h @@ -19,6 +19,7 @@ struct thread_info { { \ .task = &tsk, \ .exec_domain = &default_exec_domain, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/m68k/include/asm/thread_info_no.h b/arch/m68k/include/asm/thread_info_no.h index 82529f424ea..c2bde5e24b0 100644 --- a/arch/m68k/include/asm/thread_info_no.h +++ b/arch/m68k/include/asm/thread_info_no.h @@ -49,6 +49,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 1e96c6eb631..8f8f4abab2f 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -290,7 +290,7 @@ void dump(struct pt_regs *fp) unsigned char *tp; int i; - printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\nCURRENT PROCESS:\n\n"); printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); if (current->mm) { @@ -301,8 +301,7 @@ void dump(struct pt_regs *fp) (int) current->mm->end_data, (int) current->mm->end_data, (int) current->mm->brk); - printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n" - KERN_EMERG "\n", + printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n", (int) current->mm->start_stack, (int)(((unsigned long) current) + THREAD_SIZE)); } @@ -313,35 +312,35 @@ void dump(struct pt_regs *fp) fp->d0, fp->d1, fp->d2, fp->d3); printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", fp->d4, fp->d5, fp->a0, fp->a1); - printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x TRAPFRAME: %08x\n", + printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(), (unsigned int) fp); - printk(KERN_EMERG "\n" KERN_EMERG "CODE:"); + printk(KERN_EMERG "\nCODE:"); tp = ((unsigned char *) fp->pc) - 0x20; for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); printk(KERN_EMERG "KERNEL STACK:"); tp = ((unsigned char *) fp) - 0x40; for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); printk(KERN_EMERG "USER STACK:"); tp = (unsigned char *) (rdusp() - 0x10); for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); } /* diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 51d325343ab..3739c8f657d 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -111,7 +111,7 @@ static void print_this_address(unsigned long addr, int i) if (i % 5) printk(KERN_CONT " [%08lx] ", addr); else - printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr); + printk(KERN_EMERG " [%08lx] ", addr); i++; #endif } @@ -137,8 +137,8 @@ static void __show_stack(struct task_struct *task, unsigned long *stack) if (stack + 1 + i > endstack) break; if (i % 8 == 0) - printk("\n" KERN_EMERG " "); - printk(" %08lx", *(stack + i)); + printk(KERN_EMERG " "); + printk(KERN_CONT " %08lx", *(stack + i)); } printk("\n"); i = 0; diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index b50b845fdd5..2db722d80d4 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -53,6 +53,9 @@ config GENERIC_HARDIRQS_NO__DO_IRQ config GENERIC_GPIO def_bool y +config GENERIC_CSUM + def_bool y + config PCI def_bool n diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 0de612ad7cb..6d2e1d418be 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h @@ -1,95 +1,7 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - #ifndef _ASM_MICROBLAZE_ATOMIC_H #define _ASM_MICROBLAZE_ATOMIC_H -#include <linux/types.h> -#include <linux/compiler.h> /* likely */ -#include <asm/system.h> /* local_irq_XXX and friends */ - -#define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) -#define atomic_set(v, i) (((v)->counter) = (i)) - -#define atomic_inc(v) (atomic_add_return(1, (v))) -#define atomic_dec(v) (atomic_sub_return(1, (v))) - -#define atomic_add(i, v) (atomic_add_return(i, (v))) -#define atomic_sub(i, v) (atomic_sub_return(i, (v))) - -#define atomic_inc_return(v) (atomic_add_return(1, (v))) -#define atomic_dec_return(v) (atomic_sub_return(1, (v))) - -#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) -#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) - -#define atomic_inc_not_zero(v) (atomic_add_unless((v), 1, 0)) - -#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) - -static inline int atomic_cmpxchg(atomic_t *v, int old, int new) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (likely(ret == old)) - v->counter = new; - local_irq_restore(flags); - - return ret; -} - -static inline int atomic_add_unless(atomic_t *v, int a, int u) -{ - int c, old; - - c = atomic_read(v); - while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) - c = old; - return c != u; -} - -static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) -{ - unsigned long flags; - - local_irq_save(flags); - *addr &= ~mask; - local_irq_restore(flags); -} - -/** - * atomic_add_return - add and return - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v and returns @i + @v - */ -static inline int atomic_add_return(int i, atomic_t *v) -{ - unsigned long flags; - int val; - - local_irq_save(flags); - val = v->counter; - v->counter = val += i; - local_irq_restore(flags); - - return val; -} - -static inline int atomic_sub_return(int i, atomic_t *v) -{ - return atomic_add_return(-i, v); -} +#include <asm-generic/atomic.h> /* * Atomically test *v and decrement if it is greater than 0. @@ -109,15 +21,4 @@ static inline int atomic_dec_if_positive(atomic_t *v) return res; } -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - -/* Atomic operations are already serializing */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#include <asm-generic/atomic-long.h> - #endif /* _ASM_MICROBLAZE_ATOMIC_H */ diff --git a/arch/microblaze/include/asm/bitops.h b/arch/microblaze/include/asm/bitops.h index d6df1fd4e1e..a72468f15c8 100644 --- a/arch/microblaze/include/asm/bitops.h +++ b/arch/microblaze/include/asm/bitops.h @@ -1,27 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BITOPS_H -#define _ASM_MICROBLAZE_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - */ - -#include <asm/byteorder.h> /* swab32 */ -#include <asm/system.h> /* save_flags */ - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() #include <asm-generic/bitops.h> -#include <asm-generic/bitops/__fls.h> - -#endif /* _ASM_MICROBLAZE_BITOPS_H */ diff --git a/arch/microblaze/include/asm/bug.h b/arch/microblaze/include/asm/bug.h index 8eb2cdde11d..b12fd89e42e 100644 --- a/arch/microblaze/include/asm/bug.h +++ b/arch/microblaze/include/asm/bug.h @@ -1,15 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BUG_H -#define _ASM_MICROBLAZE_BUG_H - -#include <linux/kernel.h> #include <asm-generic/bug.h> - -#endif /* _ASM_MICROBLAZE_BUG_H */ diff --git a/arch/microblaze/include/asm/bugs.h b/arch/microblaze/include/asm/bugs.h index f2c6593653f..61791e1ad9f 100644 --- a/arch/microblaze/include/asm/bugs.h +++ b/arch/microblaze/include/asm/bugs.h @@ -1,17 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BUGS_H -#define _ASM_MICROBLAZE_BUGS_H - -static inline void check_bugs(void) -{ - /* nothing to do */ -} - -#endif /* _ASM_MICROBLAZE_BUGS_H */ +#include <asm-generic/bugs.h> diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h index 97ea46b5cf8..128bf03b54b 100644 --- a/arch/microblaze/include/asm/checksum.h +++ b/arch/microblaze/include/asm/checksum.h @@ -10,12 +10,11 @@ #ifndef _ASM_MICROBLAZE_CHECKSUM_H #define _ASM_MICROBLAZE_CHECKSUM_H -#include <linux/in6.h> - /* * computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ +#define csum_tcpudp_nofold csum_tcpudp_nofold static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) @@ -30,71 +29,6 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, return sum; } -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -extern __wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * the same as csum_partial, but copies from src while it - * checksums - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -extern __wsum csum_partial_copy(const void *src, void *dst, int len, - __wsum sum); - -/* - * the same as csum_partial_copy, but copies from user space. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err); - -#define csum_partial_copy_nocheck(src, dst, len, sum) \ - csum_partial_copy((src), (dst), (len), (sum)) - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - * - */ -extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); - -/* - * Fold a partial checksum - */ -static inline __sum16 csum_fold(__wsum csum) -{ - u32 sum = (__force u32)csum; - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return (__force __sum16)~sum; -} - -static inline __sum16 -csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, - unsigned short proto, __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -extern __sum16 ip_compute_csum(const void *buff, int len); +#include <asm-generic/checksum.h> #endif /* _ASM_MICROBLAZE_CHECKSUM_H */ diff --git a/arch/microblaze/include/asm/fb.h b/arch/microblaze/include/asm/fb.h new file mode 100644 index 00000000000..3a4988e8df4 --- /dev/null +++ b/arch/microblaze/include/asm/fb.h @@ -0,0 +1 @@ +#include <asm-generic/fb.h> diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h index 0f2d6b013e1..41e1e1aa36a 100644 --- a/arch/microblaze/include/asm/hardirq.h +++ b/arch/microblaze/include/asm/hardirq.h @@ -9,21 +9,11 @@ #ifndef _ASM_MICROBLAZE_HARDIRQ_H #define _ASM_MICROBLAZE_HARDIRQ_H -#include <linux/cache.h> -#include <linux/irq.h> -#include <asm/irq.h> -#include <asm/current.h> -#include <linux/ptrace.h> - /* should be defined in each interrupt controller driver */ extern unsigned int get_irq(struct pt_regs *regs); -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - +#define ack_bad_irq ack_bad_irq void ack_bad_irq(unsigned int irq); - -#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ +#include <asm-generic/hardirq.h> #endif /* _ASM_MICROBLAZE_HARDIRQ_H */ diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h index 03582b24920..ec34c760665 100644 --- a/arch/microblaze/include/asm/ioctls.h +++ b/arch/microblaze/include/asm/ioctls.h @@ -1,91 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_IOCTLS_H -#define _ASM_MICROBLAZE_IOCTLS_H - -#include <linux/ioctl.h> - -/* 0x54 is just a magic number to make these relatively unique ('T') */ - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 -#define TCGETA 0x5405 -#define TCSETA 0x5406 -#define TCSETAW 0x5407 -#define TCSETAF 0x5408 -#define TCSBRK 0x5409 -#define TCXONC 0x540A -#define TCFLSH 0x540B -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E -#define TIOCGPGRP 0x540F -#define TIOCSPGRP 0x5410 -#define TIOCOUTQ 0x5411 -#define TIOCSTI 0x5412 -#define TIOCGWINSZ 0x5413 -#define TIOCSWINSZ 0x5414 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define FIONREAD 0x541B -#define TIOCINQ FIONREAD -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 -#define FIONBIO 0x5421 -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TIOCSBRK 0x5427 /* BSD compatibility */ -#define TIOCCBRK 0x5428 /* BSD compatibility */ -#define TIOCGSID 0x5429 /* Return the session ID of FD */ -/* Get Pty Number (of pty-mux device) */ -#define TIOCGPTN _IOR('T', 0x30, unsigned int) -#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ - -#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define FIOCLEX 0x5451 -#define FIOASYNC 0x5452 -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -#define FIOQSIZE 0x545E - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif /* _ASM_MICROBLAZE_IOCTLS_H */ +#include <asm-generic/ioctls.h> diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h index b056fa42065..84c7e51cb6d 100644 --- a/arch/microblaze/include/asm/ipcbuf.h +++ b/arch/microblaze/include/asm/ipcbuf.h @@ -1,36 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_IPCBUF_H -#define _ASM_MICROBLAZE_IPCBUF_H - -/* - * The user_ipc_perm structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 32-bit mode_t and seq - * - 2 miscellaneous 32-bit values - */ - -struct ipc64_perm { - __kernel_key_t key; - __kernel_uid32_t uid; - __kernel_gid32_t gid; - __kernel_uid32_t cuid; - __kernel_gid32_t cgid; - __kernel_mode_t mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _ASM_MICROBLAZE_IPCBUF_H */ +#include <asm-generic/ipcbuf.h> diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index db515deaa72..90f050535eb 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -10,6 +10,7 @@ #define _ASM_MICROBLAZE_IRQ_H #define NR_IRQS 32 +#include <asm-generic/irq.h> #include <linux/interrupt.h> @@ -17,11 +18,6 @@ extern unsigned int nr_irq; #define NO_IRQ (-1) -static inline int irq_canonicalize(int irq) -{ - return irq; -} - struct pt_regs; extern void do_IRQ(struct pt_regs *regs); diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h index 4914b132944..8eebf89f5ab 100644 --- a/arch/microblaze/include/asm/mman.h +++ b/arch/microblaze/include/asm/mman.h @@ -1,25 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_MMAN_H -#define _ASM_MICROBLAZE_MMAN_H - #include <asm-generic/mman.h> - -#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ -#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ -#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ -#define MAP_LOCKED 0x2000 /* pages are locked */ -#define MAP_NORESERVE 0x4000 /* don't check for reservations */ -#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -#define MCL_CURRENT 1 /* lock all current mappings */ -#define MCL_FUTURE 2 /* lock all future mappings */ - -#endif /* _ASM_MICROBLAZE_MMAN_H */ diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h index 66cad6a99d7..8d6a654ceff 100644 --- a/arch/microblaze/include/asm/mmu.h +++ b/arch/microblaze/include/asm/mmu.h @@ -12,12 +12,7 @@ #define _ASM_MICROBLAZE_MMU_H # ifndef CONFIG_MMU -# ifndef __ASSEMBLY__ -typedef struct { - struct vm_list_struct *vmlist; - unsigned long end_brk; -} mm_context_t; -# endif /* __ASSEMBLY__ */ +# include <asm-generic/mmu.h> # else /* CONFIG_MMU */ # ifdef __KERNEL__ # ifndef __ASSEMBLY__ diff --git a/arch/microblaze/include/asm/mmu_context.h b/arch/microblaze/include/asm/mmu_context.h index 385fed16bbf..24eab1674d3 100644 --- a/arch/microblaze/include/asm/mmu_context.h +++ b/arch/microblaze/include/asm/mmu_context.h @@ -1,5 +1,5 @@ #ifdef CONFIG_MMU # include "mmu_context_mm.h" #else -# include "mmu_context_no.h" +# include <asm-generic/mmu_context.h> #endif diff --git a/arch/microblaze/include/asm/mmu_context_no.h b/arch/microblaze/include/asm/mmu_context_no.h deleted file mode 100644 index ba556719015..00000000000 --- a/arch/microblaze/include/asm/mmu_context_no.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> - * Copyright (C) 2008-2009 PetaLogix - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H -#define _ASM_MICROBLAZE_MMU_CONTEXT_H - -# define init_new_context(tsk, mm) ({ 0; }) - -# define enter_lazy_tlb(mm, tsk) do {} while (0) -# define change_mm_context(old, ctx, _pml4) do {} while (0) -# define destroy_context(mm) do {} while (0) -# define deactivate_mm(tsk, mm) do {} while (0) -# define switch_mm(prev, next, tsk) do {} while (0) -# define activate_mm(prev, next) do {} while (0) - -#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */ diff --git a/arch/microblaze/include/asm/module.h b/arch/microblaze/include/asm/module.h index 914565a9031..7be1347fce4 100644 --- a/arch/microblaze/include/asm/module.h +++ b/arch/microblaze/include/asm/module.h @@ -9,6 +9,8 @@ #ifndef _ASM_MICROBLAZE_MODULE_H #define _ASM_MICROBLAZE_MODULE_H +#include <asm-generic/module.h> + /* Microblaze Relocations */ #define R_MICROBLAZE_NONE 0 #define R_MICROBLAZE_32 1 @@ -24,14 +26,6 @@ /* Keep this the last entry. */ #define R_MICROBLAZE_NUM 11 -struct mod_arch_specific { - int foo; -}; - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - typedef struct { volatile int counter; } module_t; #endif /* _ASM_MICROBLAZE_MODULE_H */ diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h index 09dd9709721..809134c644a 100644 --- a/arch/microblaze/include/asm/msgbuf.h +++ b/arch/microblaze/include/asm/msgbuf.h @@ -1,31 +1 @@ -#ifndef _ASM_MICROBLAZE_MSGBUF_H -#define _ASM_MICROBLAZE_MSGBUF_H - -/* - * The msqid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - unsigned long __unused1; - __kernel_time_t msg_rtime; /* last msgrcv time */ - unsigned long __unused2; - __kernel_time_t msg_ctime; /* last change time */ - unsigned long __unused3; - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif /* _ASM_MICROBLAZE_MSGBUF_H */ +#include <asm-generic/msgbuf.h> diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h index 8c538a49616..965d4542797 100644 --- a/arch/microblaze/include/asm/param.h +++ b/arch/microblaze/include/asm/param.h @@ -1,30 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_PARAM_H -#define _ASM_MICROBLAZE_PARAM_H - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ /* internal kernel timer frequency */ -#define USER_HZ 100 /* for user interfaces in "ticks" */ -#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ -#endif /* __KERNEL__ */ - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _ASM_MICROBLAZE_PARAM_H */ +#include <asm-generic/param.h> diff --git a/arch/microblaze/include/asm/parport.h b/arch/microblaze/include/asm/parport.h new file mode 100644 index 00000000000..cf252af6459 --- /dev/null +++ b/arch/microblaze/include/asm/parport.h @@ -0,0 +1 @@ +#include <asm-generic/parport.h> diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index ca03794cf3f..9f0df5faf2c 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -1 +1 @@ -#include <linux/io.h> +#include <asm-generic/pci.h> diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h index 8c758b231f3..0e15039673e 100644 --- a/arch/microblaze/include/asm/posix_types.h +++ b/arch/microblaze/include/asm/posix_types.h @@ -1,73 +1,9 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - #ifndef _ASM_MICROBLAZE_POSIX_TYPES_H #define _ASM_MICROBLAZE_POSIX_TYPES_H -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned long __kernel_ino_t; typedef unsigned short __kernel_mode_t; -typedef unsigned int __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned int __kernel_ipc_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef int __kernel_daddr_t; -typedef char *__kernel_caddr_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned int __kernel_old_dev_t; - -#ifdef __GNUC__ -typedef long long __kernel_loff_t; -#endif - -typedef struct { -#if defined(__KERNEL__) || defined(__USE_ALL) - int val[2]; -#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ - int __val[2]; -#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ -} __kernel_fsid_t; - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) - -#undef __FD_SET -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) - -#undef __FD_CLR -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) - -#undef __FD_ISSET -#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d))) - -#undef __FD_ZERO -#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp))) +#define __kernel_mode_t __kernel_mode_t -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#include <asm-generic/posix_types.h> #endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */ diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h index 08ff1d049b4..35d786fe93a 100644 --- a/arch/microblaze/include/asm/scatterlist.h +++ b/arch/microblaze/include/asm/scatterlist.h @@ -1,28 +1 @@ -/* - * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SCATTERLIST_H -#define _ASM_MICROBLAZE_SCATTERLIST_H - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - dma_addr_t dma_address; - unsigned int offset; - unsigned int length; -}; - -#define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->length) - -#define ISA_DMA_THRESHOLD (~0UL) - -#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */ +#include <asm-generic/scatterlist.h> diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h index b804ed71a57..7673b83cfef 100644 --- a/arch/microblaze/include/asm/sembuf.h +++ b/arch/microblaze/include/asm/sembuf.h @@ -1,34 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SEMBUF_H -#define _ASM_MICROBLAZE_SEMBUF_H - -/* - * The semid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - unsigned long __unused1; - __kernel_time_t sem_ctime; /* last change time */ - unsigned long __unused2; - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused3; - unsigned long __unused4; -}; - - -#endif /* _ASM_MICROBLAZE_SEMBUF_H */ +#include <asm-generic/sembuf.h> diff --git a/arch/microblaze/include/asm/serial.h b/arch/microblaze/include/asm/serial.h index 39bfc8ce6af..a0cb0caff15 100644 --- a/arch/microblaze/include/asm/serial.h +++ b/arch/microblaze/include/asm/serial.h @@ -1,14 +1 @@ -/* - * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SERIAL_H -#define _ASM_MICROBLAZE_SERIAL_H - -# define BASE_BAUD (1843200 / 16) - -#endif /* _ASM_MICROBLAZE_SERIAL_H */ +#include <asm-generic/serial.h> diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h index f829c584361..83c05fc2de3 100644 --- a/arch/microblaze/include/asm/shmbuf.h +++ b/arch/microblaze/include/asm/shmbuf.h @@ -1,42 +1 @@ -#ifndef _ASM_MICROBLAZE_SHMBUF_H -#define _ASM_MICROBLAZE_SHMBUF_H - -/* - * The shmid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - unsigned long __unused1; - __kernel_time_t shm_dtime; /* last detach time */ - unsigned long __unused2; - __kernel_time_t shm_ctime; /* last change time */ - unsigned long __unused3; - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused4; - unsigned long __unused5; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _ASM_MICROBLAZE_SHMBUF_H */ +#include <asm-generic/shmbuf.h> diff --git a/arch/microblaze/include/asm/shmparam.h b/arch/microblaze/include/asm/shmparam.h index 9f5fc2b3b6a..93f30deb95d 100644 --- a/arch/microblaze/include/asm/shmparam.h +++ b/arch/microblaze/include/asm/shmparam.h @@ -1,6 +1 @@ -#ifndef _ASM_MICROBLAZE_SHMPARAM_H -#define _ASM_MICROBLAZE_SHMPARAM_H - -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ - -#endif /* _ASM_MICROBLAZE_SHMPARAM_H */ +#include <asm-generic/shmparam.h> diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h index f162911a8f5..0815d29d82e 100644 --- a/arch/microblaze/include/asm/siginfo.h +++ b/arch/microblaze/include/asm/siginfo.h @@ -1,15 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SIGINFO_H -#define _ASM_MICROBLAZE_SIGINFO_H - -#include <linux/types.h> #include <asm-generic/siginfo.h> - -#endif /* _ASM_MICROBLAZE_SIGINFO_H */ diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h index 46bc2267d94..7b1573ce19d 100644 --- a/arch/microblaze/include/asm/signal.h +++ b/arch/microblaze/include/asm/signal.h @@ -1,165 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * Yasushi SHOJI <yashi@atmark-techno.com> - * Tetsuya OHKAWA <tetsuya@atmark-techno.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SIGNAL_H -#define _ASM_MICROBLAZE_SIGNAL_H - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -# ifndef __ASSEMBLY__ -# include <linux/types.h> -# include <asm-generic/signal-defs.h> - -/* Avoid too many header ordering problems. */ -struct siginfo; - -# ifdef __KERNEL__ -/* - * Most things should be clean enough to redefine this at will, if care - * is taken to make libc match. - */ -# define _NSIG 64 -# define _NSIG_BPW 32 -# define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; - void (*sa_restorer)(void); - sigset_t sa_mask; /* mask last for extensibility */ -}; - -struct k_sigaction { - struct sigaction sa; -}; - -# include <asm/sigcontext.h> -# undef __HAVE_ARCH_SIG_BITOPS - -# define ptrace_signal_deliver(regs, cookie) do { } while (0) - -# else /* !__KERNEL__ */ - -/* Here we must cater to libcs that poke about in kernel headers. */ - -# define NSIG 32 -typedef unsigned long sigset_t; - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -# define sa_handler _u._sa_handler -# define sa_sigaction _u._sa_sigaction - -# endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -# endif /* __ASSEMBLY__ */ -#endif /* _ASM_MICROBLAZE_SIGNAL_H */ +#include <asm-generic/signal.h> diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h index 82593686031..6b71384b9d8 100644 --- a/arch/microblaze/include/asm/socket.h +++ b/arch/microblaze/include/asm/socket.h @@ -1,69 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SOCKET_H -#define _ASM_MICROBLAZE_SOCKET_H - -#include <asm/sockios.h> - -/* For setsockoptions(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -/* To add :#define SO_REUSEPORT 15 */ -#define SO_PASSCRED 16 -#define SO_PEERCRED 17 -#define SO_RCVLOWAT 18 -#define SO_SNDLOWAT 19 -#define SO_RCVTIMEO 20 -#define SO_SNDTIMEO 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 -#define SO_PASSSEC 34 - -#define SO_TIMESTAMPNS 35 -#define SCM_TIMESTAMPNS SO_TIMESTAMPNS - -#define SO_MARK 36 - -#define SO_TIMESTAMPING 37 -#define SCM_TIMESTAMPING SO_TIMESTAMPING - -#endif /* _ASM_MICROBLAZE_SOCKET_H */ +#include <asm-generic/socket.h> diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h index 9fff57a701e..def6d4746ee 100644 --- a/arch/microblaze/include/asm/sockios.h +++ b/arch/microblaze/include/asm/sockios.h @@ -1,23 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SOCKIOS_H -#define _ASM_MICROBLAZE_SOCKIOS_H - -#include <linux/ioctl.h> - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ -#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ - -#endif /* _ASM_MICROBLAZE_SOCKIOS_H */ +#include <asm-generic/sockios.h> diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h index a15f77520bf..3dc90fa92c7 100644 --- a/arch/microblaze/include/asm/stat.h +++ b/arch/microblaze/include/asm/stat.h @@ -1,68 +1 @@ -/* - * Microblaze stat structure - * - * Copyright (C) 2001,02,03 NEC Electronics Corporation - * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -#ifndef _ASM_MICROBLAZE_STAT_H -#define _ASM_MICROBLAZE_STAT_H - -#include <linux/posix_types.h> - -#define STAT_HAVE_NSEC 1 - -struct stat { - unsigned long st_dev; - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long st_rdev; - unsigned long __pad1; - long st_size; - int st_blksize; - int __pad2; - long st_blocks; - int st_atime; - unsigned int st_atime_nsec; - int st_mtime; - unsigned int st_mtime_nsec; - int st_ctime; - unsigned int st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; -}; - -struct stat64 { - unsigned long long st_dev; /* Device. */ - unsigned long long st_ino; /* File serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group. */ - unsigned long long st_rdev; /* Device number, if device. */ - unsigned long long __pad1; - long long st_size; /* Size of file, in bytes. */ - int st_blksize; /* Optimal block size for I/O. */ - int __pad2; - long long st_blocks; /* Number 512-byte blocks allocated. */ - int st_atime; /* Time of last access. */ - unsigned int st_atime_nsec; - int st_mtime; /* Time of last modification. */ - unsigned int st_mtime_nsec; - int st_ctime; /* Time of last status change. */ - unsigned int st_ctime_nsec; - unsigned int __unused4; - unsigned int __unused5; -}; - -#endif /* _ASM_MICROBLAZE_STAT_H */ - +#include <asm-generic/stat.h> diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h index b375d7b65ad..7847e563ab6 100644 --- a/arch/microblaze/include/asm/swab.h +++ b/arch/microblaze/include/asm/swab.h @@ -1,8 +1 @@ -#ifndef _ASM_MICROBLAZE_SWAB_H -#define _ASM_MICROBLAZE_SWAB_H - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) -#define __SWAB_64_THRU_32__ -#endif - -#endif /* _ASM_MICROBLAZE_SWAB_H */ +#include <asm-generic/swab.h> diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h index ddea9eb31f8..720761cc741 100644 --- a/arch/microblaze/include/asm/syscalls.h +++ b/arch/microblaze/include/asm/syscalls.h @@ -1,48 +1,8 @@ #ifndef __ASM_MICROBLAZE_SYSCALLS_H -#define __ASM_MICROBLAZE_SYSCALLS_H -#ifdef __KERNEL__ -#include <linux/compiler.h> -#include <linux/linkage.h> -#include <linux/types.h> -#include <linux/signal.h> +asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs); +#define sys_clone sys_clone -/* FIXME will be removed */ -asmlinkage int sys_ipc(uint call, int first, int second, - int third, void *ptr, long fifth); +#include <asm-generic/syscalls.h> -struct pt_regs; -asmlinkage int sys_vfork(struct pt_regs *regs); -asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs); -asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, - char __user *__user *envp, struct pt_regs *regs); - -asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff); - -asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset); - -/* from signal.c */ -asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs); - -asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - struct pt_regs *regs); - -asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact); - -asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, - struct sigaction __user *oact, size_t sigsetsize); - -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs); - -asmlinkage int sys_sigreturn(struct pt_regs *regs); - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); - -#endif /* __KERNEL__ */ #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index c4e308850b5..b1ed6159066 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -13,6 +13,9 @@ #include <asm/setup.h> #include <asm/irqflags.h> +#include <asm-generic/cmpxchg.h> +#include <asm-generic/cmpxchg-local.h> + struct task_struct; struct thread_info; diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h index a1b64bc4724..3935b106de7 100644 --- a/arch/microblaze/include/asm/termbits.h +++ b/arch/microblaze/include/asm/termbits.h @@ -1,203 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TERMBITS_H -#define _ASM_MICROBLAZE_TERMBITS_H - -#include <linux/posix_types.h> - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -struct ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ - -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -/* c_iflag bits */ - -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ - -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ - -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define BOTHER 0010000 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ -#define CMSPAR 010000000000 /* mark or space (stick) parity */ -#define CRTSCTS 020000000000 /* flow control */ - -#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ - -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 - -/* tcflow() and TCXONC use these */ - -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ - -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ - -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* _ASM_MICROBLAZE_TERMBITS_H */ +#include <asm-generic/termbits.h> diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h index 47a46d1fbe2..280d78a9d96 100644 --- a/arch/microblaze/include/asm/termios.h +++ b/arch/microblaze/include/asm/termios.h @@ -1,88 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TERMIOS_H -#define _ASM_MICROBLAZE_TERMIOS_H - -#include <linux/string.h> -#include <asm/termbits.h> -#include <asm/ioctls.h> - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -#ifdef __KERNEL__ -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" -#endif - -/* Modem lines */ - -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -/* Line disciplines */ - -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 /* X.25 async */ -#define N_6PACK 7 -#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */ -#define N_R3964 9 /* Reserved for Simatic R3964 module */ -#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */ -#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ -#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards - about SMS messages */ -#define N_HDLC 13 /* synchronous HDLC */ -#define N_SYNC_PPP 14 -#define N_HCI 15 /* Bluetooth HCI UART */ - -#ifdef __KERNEL__ - -#include <asm-generic/termios-base.h> - -#endif /* __KERNEL__ */ - -#endif /* _ASM_MICROBLAZE_TERMIOS_H */ +#include <asm-generic/termios.h> diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h index 7fac4449844..6e92885d381 100644 --- a/arch/microblaze/include/asm/thread_info.h +++ b/arch/microblaze/include/asm/thread_info.h @@ -75,8 +75,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -84,7 +82,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/microblaze/include/asm/timex.h b/arch/microblaze/include/asm/timex.h index 678525dc6d0..befcf3de553 100644 --- a/arch/microblaze/include/asm/timex.h +++ b/arch/microblaze/include/asm/timex.h @@ -9,10 +9,8 @@ #ifndef _ASM_MICROBLAZE_TIMEX_H #define _ASM_MICROBLAZE_TIMEX_H -#define CLOCK_TICK_RATE 1000 /* Timer input freq. */ - -typedef unsigned long cycles_t; +#include <asm-generic/timex.h> -#define get_cycles() (0) +#define CLOCK_TICK_RATE 1000 /* Timer input freq. */ #endif /* _ASM_TIMEX_H */ diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h index bebc018318f..b9e79bc580d 100644 --- a/arch/microblaze/include/asm/types.h +++ b/arch/microblaze/include/asm/types.h @@ -1,38 +1 @@ -/* - * Copyright (C) Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TYPES_H -#define _ASM_MICROBLAZE_TYPES_H - -/* - * This file is never included by application software unless - * explicitly requested (e.g., via linux/types.h) in which case the - * application is Linux specific so (user-) name space pollution is - * not a major issue. However, for interoperability, libraries still - * need to be careful to avoid a name clashes. - */ - -#include <asm-generic/int-ll64.h> - -# ifndef __ASSEMBLY__ - -typedef unsigned short umode_t; - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -# ifdef __KERNEL__ -# define BITS_PER_LONG 32 - -/* Dma addresses are 32-bits wide. */ - -typedef u32 dma_addr_t; - -# endif/* __KERNEL__ */ -# endif /* __ASSEMBLY__ */ -#endif /* _ASM_MICROBLAZE_TYPES_H */ +#include <asm-generic/types.h> diff --git a/arch/microblaze/include/asm/ucontext.h b/arch/microblaze/include/asm/ucontext.h index 11f6bb3ae3a..9bc07b9f30f 100644 --- a/arch/microblaze/include/asm/ucontext.h +++ b/arch/microblaze/include/asm/ucontext.h @@ -1,22 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_UCONTEXT_H -#define _ASM_MICROBLAZE_UCONTEXT_H - -#include <asm/sigcontext.h> - -struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ -}; - -#endif /* _ASM_MICROBLAZE_UCONTEXT_H */ +#include <asm-generic/ucontext.h> diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index b5e2f5fa5c5..0b852327c0e 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -380,8 +380,10 @@ #define __NR_accept04 362 /* new */ #define __NR_preadv 363 /* new */ #define __NR_pwritev 364 /* new */ +#define __NR_rt_tgsigqueueinfo 365 /* new */ +#define __NR_perf_counter_open 366 /* new */ -#define __NR_syscalls 365 +#define __NR_syscalls 367 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -408,7 +410,7 @@ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION -/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */ +#define __ARCH_WANT_SYS_RT_SIGSUSPEND /* * "Conditional" syscalls diff --git a/arch/microblaze/include/asm/vga.h b/arch/microblaze/include/asm/vga.h index 8b137891791..89d82fd8fcf 100644 --- a/arch/microblaze/include/asm/vga.h +++ b/arch/microblaze/include/asm/vga.h @@ -1 +1 @@ - +#include <asm-generic/vga.h> diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 1fce6b803f5..9083d85376a 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -551,30 +551,22 @@ no_work_pending: rtid r14, 0 nop -sys_vfork_wrapper: - brid sys_vfork +sys_vfork: + brid microblaze_vfork addk r5, r1, r0 -sys_clone_wrapper: - brid sys_clone +sys_clone: + brid microblaze_clone addk r7, r1, r0 -sys_execve_wrapper: - brid sys_execve +sys_execve: + brid microblaze_execve addk r8, r1, r0 -sys_sigreturn_wrapper: - brid sys_sigreturn - addk r5, r1, r0 - sys_rt_sigreturn_wrapper: brid sys_rt_sigreturn addk r5, r1, r0 -sys_sigsuspend_wrapper: - brid sys_rt_sigsuspend - addk r6, r1, r0 - sys_rt_sigsuspend_wrapper: brid sys_rt_sigsuspend addk r7, r1, r0 diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 91a0e7b185d..c7353e79f4a 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -429,12 +429,11 @@ C_ENTRY(ret_from_fork): brid ret_from_trap; /* Do normal trap return */ nop; -C_ENTRY(sys_vfork_wrapper): +C_ENTRY(sys_vfork): + brid microblaze_vfork /* Do real work (tail-call) */ la r5, r1, PTO - brid sys_vfork /* Do real work (tail-call) */ - nop -C_ENTRY(sys_clone_wrapper): +C_ENTRY(sys_clone): bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ lwi r6, r1, PTO+PT_R1; /* If so, use paret's stack ptr */ 1: la r7, r1, PTO; /* Arg 2: parent context */ @@ -444,20 +443,9 @@ C_ENTRY(sys_clone_wrapper): brid do_fork /* Do real work (tail-call) */ nop; -C_ENTRY(sys_execve_wrapper): +C_ENTRY(sys_execve): la r8, r1, PTO; /* add user context as 4th arg */ - brid sys_execve; /* Do real work (tail-call).*/ - nop; - -C_ENTRY(sys_sigsuspend_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r6, r1, PTO; /* add user context as 2nd arg */ - bralid r15, sys_sigsuspend; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ + brid microblaze_execve; /* Do real work (tail-call).*/ nop; C_ENTRY(sys_rt_sigsuspend_wrapper): @@ -471,18 +459,6 @@ C_ENTRY(sys_rt_sigsuspend_wrapper): bri ret_from_trap /* fall through will not work here due to align */ nop; - -C_ENTRY(sys_sigreturn_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r5, r1, PTO; /* add user context as 1st arg */ - brlid r15, sys_sigreturn; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; - C_ENTRY(sys_rt_sigreturn_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 4c0e6521b11..493819c25fb 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -45,91 +45,8 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r3 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset, 1)) - return -EINTR; - } -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r3 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset, 1)) - return -EINTR; - } -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage int +asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) { @@ -139,7 +56,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ - struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; @@ -176,40 +92,7 @@ static int restore_sigcontext(struct pt_regs *regs, return err; } -asmlinkage int sys_sigreturn(struct pt_regs *regs) -{ - struct sigframe *frame = - (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE); - - sigset_t set; - int rval; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->sc, &rval)) - goto badframe; - return rval; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE); @@ -324,21 +207,17 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" */ - if (ka->sa.sa_flags & SA_RESTORER) { - regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; - } else { - /* addi r12, r0, __NR_sigreturn */ - err |= __put_user(0x31800000 | __NR_rt_sigreturn , - frame->tramp + 0); - /* brki r14, 0x8 */ - err |= __put_user(0xb9cc0008, frame->tramp + 1); - - /* Return from sighandler will jump to the tramp. - Negative 8 offset because return is rtsd r15, 8 */ - regs->r15 = ((unsigned long)frame->tramp)-8; - - __invalidate_cache_sigtramp((unsigned long)frame->tramp); - } + /* addi r12, r0, __NR_sigreturn */ + err |= __put_user(0x31800000 | __NR_rt_sigreturn , + frame->tramp + 0); + /* brki r14, 0x8 */ + err |= __put_user(0xb9cc0008, frame->tramp + 1); + + /* Return from sighandler will jump to the tramp. + Negative 8 offset because return is rtsd r15, 8 */ + regs->r15 = ((unsigned long)frame->tramp)-8; + + __invalidate_cache_sigtramp((unsigned long)frame->tramp); if (err) goto give_sigsegv; @@ -405,7 +284,7 @@ do_restart: * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -426,6 +305,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } + return 1; } /* @@ -456,7 +336,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) if (kernel_mode(regs)) return 1; - if (!oldset) + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -464,13 +346,31 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ka, 1); - handle_signal(signr, &ka, &info, oldset, regs); + if (handle_signal(signr, &ka, &info, oldset, regs)) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= + ~TS_RESTORE_SIGMASK; + } return 1; } if (in_syscall) handle_restart(regs, NULL, 0); + /* + * If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + /* Did we come from a system call? */ return 0; } diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 31905ff590b..8c9ebac5da1 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -39,7 +39,7 @@ * * This is really horribly ugly. This will be remove with new toolchain. */ -asmlinkage int +asmlinkage long sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) { int version, ret; @@ -134,20 +134,20 @@ sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) return ret; } -asmlinkage int sys_vfork(struct pt_regs *regs) +asmlinkage long microblaze_vfork(struct pt_regs *regs) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, regs, 0, NULL, NULL); } -asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs) +asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs) { if (!stack) stack = regs->r1; return do_fork(flags, stack, regs, 0, NULL, NULL); } -asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, +asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv, char __user *__user *envp, struct pt_regs *regs) { int error; @@ -163,8 +163,8 @@ out: return error; } -asmlinkage unsigned long -sys_mmap2(unsigned long addr, size_t len, +asmlinkage long +sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { @@ -189,18 +189,18 @@ out: return ret; } -asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) + unsigned long fd, off_t pgoff) { int err = -EINVAL; - if (offset & ~PAGE_MASK) { + if (pgoff & ~PAGE_MASK) { printk(KERN_INFO "no pagemask in mmap\r\n"); goto out; } - err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); out: return err; } diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 376d1789f7c..31b32a6c5f4 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -15,7 +15,7 @@ ENTRY(sys_call_table) .long sys_creat .long sys_link .long sys_unlink /* 10 */ - .long sys_execve_wrapper + .long sys_execve .long sys_chdir .long sys_time .long sys_mknod @@ -71,12 +71,12 @@ ENTRY(sys_call_table) .long sys_getppid .long sys_getpgrp /* 65 */ .long sys_setsid - .long sys_sigaction + .long sys_ni_syscall /* sys_sigaction */ .long sys_sgetmask .long sys_ssetmask .long sys_setreuid /* 70 */ .long sys_setregid - .long sys_sigsuspend_wrapper + .long sys_ni_syscall /* sys_sigsuspend_wrapper */ .long sys_sigpending .long sys_sethostname .long sys_setrlimit /* 75 */ @@ -123,8 +123,8 @@ ENTRY(sys_call_table) .long sys_sysinfo .long sys_ipc .long sys_fsync - .long sys_sigreturn_wrapper - .long sys_clone_wrapper /* 120 */ + .long sys_ni_syscall /* sys_sigreturn_wrapper */ + .long sys_clone /* 120 */ .long sys_setdomainname .long sys_newuname .long sys_ni_syscall /* modify_ldt */ @@ -194,7 +194,7 @@ ENTRY(sys_call_table) .long sys_sendfile .long sys_ni_syscall /* reserved for streams1 */ .long sys_ni_syscall /* reserved for streams2 */ - .long sys_vfork_wrapper /* 190 */ + .long sys_vfork /* 190 */ .long sys_getrlimit .long sys_mmap2 /* mmap2 */ .long sys_truncate64 @@ -369,3 +369,5 @@ ENTRY(sys_call_table) .long sys_ni_syscall .long sys_ni_syscall .long sys_ni_syscall + .long sys_rt_tgsigqueueinfo /* 365 */ + .long sys_perf_counter_open diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index 71c8cb6c9e4..b579db068c0 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -2,7 +2,7 @@ # Makefile # -lib-y := memset.o checksum.o +lib-y := memset.o ifeq ($(CONFIG_OPT_LIB_ASM),y) lib-y += fastcopy.o diff --git a/arch/microblaze/lib/checksum.c b/arch/microblaze/lib/checksum.c deleted file mode 100644 index f08e7459141..00000000000 --- a/arch/microblaze/lib/checksum.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, <jorge@laser.satlink.net> - * Arnt Gulbrandsen, <agulbra@nvg.unit.no> - * Tom May, <ftom@netcom.com> - * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: - * Fixed some nasty bugs, causing some horrible crashes. - * A: At some points, the sum (%0) was used as - * length-counter instead of the length counter - * (%1). Thanks to Roman Hodek for pointing this out. - * B: GCC seems to mess up if one uses too many - * data-registers to hold input values and one tries to - * specify d0 and d1 as scratch registers. Letting gcc - * choose these registers itself solves the problem. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access - kills, so most of the assembly has to go. */ - -#include <linux/module.h> -#include <net/checksum.h> - -#include <asm/byteorder.h> - -static inline unsigned short from32to16(unsigned long x) -{ - /* add up 16-bit and 16-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static unsigned int do_csum(const unsigned char *buff, int len) -{ - int odd, count; - unsigned long result = 0; - - if (len <= 0) - goto out; - odd = 1 & (unsigned long) buff; - if (odd) { - result = *buff; - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - count--; - buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffff) + (result >> 16); - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += (*buff << 8); - result = from32to16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); -out: - return result; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -__sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - return (__force __sum16)~do_csum(iph, ihl*4); -} -EXPORT_SYMBOL(ip_fast_csum); - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -__wsum csum_partial(const void *buff, int len, __wsum wsum) -{ - unsigned int sum = (__force unsigned int)wsum; - unsigned int result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - if (sum > result) - result += 1; - return (__force __wsum)result; -} -EXPORT_SYMBOL(csum_partial); - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -__sum16 ip_compute_csum(const void *buff, int len) -{ - return (__force __sum16)~do_csum(buff, len); -} -EXPORT_SYMBOL(ip_compute_csum); - -/* - * copy from fs while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *csum_err) -{ - int missing; - - missing = __copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *csum_err = -EFAULT; - } else - *csum_err = 0; - - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy_from_user); - -/* - * copy from ds while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy(const void *src, void *dst, int len, __wsum sum) -{ - memcpy(dst, src, len); - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy); diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index b5a701cd71e..8d92c4efe9a 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -80,15 +80,15 @@ void __init setup_memory(void) memory_size = memory_end - memory_start; PAGE_OFFSET = memory_start; printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, " - "size 0x%08x\n", __func__, memory_start, - memory_end, memory_size); + "size 0x%08x\n", __func__, (u32) memory_start, + (u32) memory_end, (u32) memory_size); break; } } if (!memory_start || !memory_end) { panic("%s: Missing memory setting 0x%08x-0x%08x\n", - __func__, memory_start, memory_end); + __func__, (u32) memory_start, (u32) memory_end); } /* reservation of region where is the kernel */ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 143a48136a4..f9df720d2e4 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -39,8 +39,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -48,7 +46,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = _TIF_FIXADE, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h index e58b9a46e1b..35d2ed6396f 100644 --- a/arch/mn10300/include/asm/pci.h +++ b/arch/mn10300/include/asm/pci.h @@ -70,10 +70,6 @@ struct pci_dev; */ #define PCI_DMA_BUS_IS_PHYS (1) - -/* This is always fine. */ -#define pci_dac_dma_supported(pci_dev, mask) (0) - /* Return the index of the PCI controller for device. */ static inline int pci_controller_num(struct pci_dev *dev) { diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h index 78a3881f3c1..58d64f8b2cc 100644 --- a/arch/mn10300/include/asm/thread_info.h +++ b/arch/mn10300/include/asm/thread_info.h @@ -65,8 +65,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -76,7 +74,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index 681ad8c9e4f..0dfdc500112 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c @@ -136,8 +136,7 @@ void show_trace(unsigned long *sp) unsigned long *stack, addr, module_start, module_end; int i; - printk(KERN_EMERG "\n" - KERN_EMERG "Call Trace:"); + printk(KERN_EMERG "\nCall Trace:"); stack = sp; i = 0; @@ -153,7 +152,7 @@ void show_trace(unsigned long *sp) printk("\n"); #else if ((i % 6) == 0) - printk("\n" KERN_EMERG " "); + printk(KERN_EMERG " "); printk("[<%08lx>] ", addr); i++; #endif @@ -180,7 +179,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) if (((long) stack & (THREAD_SIZE - 1)) == 0) break; if ((i % 8) == 0) - printk("\n" KERN_EMERG " "); + printk(KERN_EMERG " "); printk("%08lx ", *stack++); } @@ -264,8 +263,7 @@ void show_registers(struct pt_regs *regs) show_stack(current, (unsigned long *) sp); #if 0 - printk(KERN_EMERG "\n" - KERN_EMERG "Code: "); + printk(KERN_EMERG "\nCode: "); if (regs->pc < PAGE_OFFSET) goto bad; @@ -311,16 +309,14 @@ void die(const char *str, struct pt_regs *regs, enum exception_code code) { console_verbose(); spin_lock_irq(&die_lock); - printk(KERN_EMERG "\n" - KERN_EMERG "%s: %04x\n", + printk(KERN_EMERG "\n%s: %04x\n", str, code & 0xffff); show_registers(regs); if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 && (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) { printk(KERN_EMERG "Exception in usermode interrupt handler\n"); - printk(KERN_EMERG "\n" - KERN_EMERG " Please connect to kernel debugger !!\n"); + printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n"); asm volatile ("0: bra 0b"); } @@ -429,9 +425,8 @@ asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs) { console_verbose(); - printk(KERN_EMERG "\n" - KERN_EMERG "Asynchronous I/O Bus Error\n" - KERN_EMERG "==========================\n"); + printk(KERN_EMERG "Asynchronous I/O Bus Error\n"); + printk(KERN_EMERG "==========================\n"); if (bcberr & BCBERR_BEME) printk(KERN_EMERG "- Multiple recorded errors\n"); diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 0407959da48..4ce0edfbe96 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h @@ -23,7 +23,7 @@ struct thread_info { .flags = 0, \ .cpu = 0, \ .addr_limit = KERNEL_DS, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall \ } \ diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 61c07078c07..1f3aa8db020 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -156,7 +156,7 @@ void machine_power_off(void) * software. The user has to press the button himself. */ printk(KERN_EMERG "System shut down completed.\n" - KERN_EMERG "Please power this system off now."); + "Please power this system off now."); } void (*pm_power_off)(void) = machine_power_off; diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index c32f5d6d778..528f0ff9b27 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -250,15 +250,14 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) oops_enter(); /* Amuse the user in a SPARC fashion */ - if (err) printk( -KERN_CRIT " _______________________________ \n" -KERN_CRIT " < Your System ate a SPARC! Gah! >\n" -KERN_CRIT " ------------------------------- \n" -KERN_CRIT " \\ ^__^\n" -KERN_CRIT " \\ (xx)\\_______\n" -KERN_CRIT " (__)\\ )\\/\\\n" -KERN_CRIT " U ||----w |\n" -KERN_CRIT " || ||\n"); + if (err) printk(KERN_CRIT + " _______________________________ \n" + " < Your System ate a SPARC! Gah! >\n" + " ------------------------------- \n" + " \\ ^__^\n" + " (__)\\ )\\/\\\n" + " U ||----w |\n" + " || ||\n"); /* unlock the pdc lock if necessary */ pdc_emergency_unlock(); @@ -797,7 +796,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs) else printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ", code); - printk("pid=%d command='%s'\n", task_pid_nr(current), current->comm); + printk(KERN_CONT "pid=%d command='%s'\n", + task_pid_nr(current), current->comm); show_regs(regs); #endif si.si_signo = SIGSEGV; diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index 01bfb56bbe8..31605ee4afb 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts @@ -261,10 +261,11 @@ compatible = "gpio-leds"; green { gpios = <&GPIO1 0 0>; - default-state = "on"; + default-state = "keep"; }; red { gpios = <&GPIO1 1 0>; + default-state = "keep"; }; }; diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig index 3b77f092abe..787635f23d8 100644 --- a/arch/powerpc/configs/44x/warp_defconfig +++ b/arch/powerpc/configs/44x/warp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.29-rc2 -# Fri Jan 23 07:57:16 2009 +# Linux kernel version: 2.6.30 +# Tue Jun 9 23:35:36 2009 # # CONFIG_PPC64 is not set @@ -41,6 +41,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_NO_VIRT_TO_BUS is not set CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -53,10 +54,12 @@ CONFIG_PPC_UDBG_16550=y # CONFIG_GENERIC_TBSYNC is not set CONFIG_AUDIT_ARCH=y CONFIG_GENERIC_BUG=y +CONFIG_DTC=y # CONFIG_DEFAULT_UIMAGE is not set CONFIG_PPC_DCR_NATIVE=y # CONFIG_PPC_DCR_MMIO is not set CONFIG_PPC_DCR=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -74,7 +77,17 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y @@ -82,27 +95,29 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_HOTPLUG is not set +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y @@ -110,10 +125,13 @@ CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y @@ -121,6 +139,7 @@ CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_SLOW_WORK is not set # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -133,7 +152,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y # CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -149,11 +167,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_FREEZER is not set # @@ -173,10 +186,11 @@ CONFIG_WARP=y # CONFIG_ARCHES is not set # CONFIG_CANYONLANDS is not set # CONFIG_GLACIER is not set +# CONFIG_REDWOOD is not set # CONFIG_YOSEMITE is not set # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set # CONFIG_PPC44x_SIMPLE is not set -# CONFIG_PPC4xx_GPIO is not set +CONFIG_PPC4xx_GPIO=y CONFIG_440EP=y CONFIG_IBM440EP_ERR42=y # CONFIG_IPIC is not set @@ -235,9 +249,13 @@ CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_STDBINUTILS=y CONFIG_PPC_4K_PAGES=y # CONFIG_PPC_16K_PAGES is not set # CONFIG_PPC_64K_PAGES is not set +# CONFIG_PPC_256K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y CONFIG_CMDLINE_BOOL=y @@ -256,6 +274,7 @@ CONFIG_PPC_PCI_CHOICE=y # CONFIG_PCI_DOMAINS is not set # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set # CONFIG_HAS_RAPIDIO is not set # @@ -271,14 +290,12 @@ CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_KERNEL_START=0xc0000000 CONFIG_PHYSICAL_START=0x00000000 CONFIG_TASK_SIZE=0xc0000000 -CONFIG_CONSISTENT_START=0xff100000 CONFIG_CONSISTENT_SIZE=0x00200000 CONFIG_NET=y # # Networking options # -CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -353,6 +370,7 @@ CONFIG_VLAN_8021Q=y # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -365,7 +383,6 @@ CONFIG_VLAN_8021Q=y # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set -# CONFIG_PHONET is not set # CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set @@ -378,8 +395,12 @@ CONFIG_VLAN_8021Q=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -471,13 +492,21 @@ CONFIG_MTD_NAND_NDFC=y # LPDDR flash memory drivers # # CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_QINFO_PROBE is not set # # UBI - Unsorted block images # -# CONFIG_MTD_UBI is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y CONFIG_OF_I2C=y # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y @@ -495,10 +524,17 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_XILINX_SYSACE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y -# CONFIG_EEPROM_93CX6 is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set # CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -529,7 +565,7 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCSI_WAIT_SCAN is not set # # SCSI Transports @@ -541,10 +577,12 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set # CONFIG_ATA is not set # CONFIG_MD is not set # CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -554,6 +592,8 @@ CONFIG_NETDEVICES=y # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_ETHOC is not set +# CONFIG_DNET is not set CONFIG_IBM_NEW_EMAC=y CONFIG_IBM_NEW_EMAC_RXB=128 CONFIG_IBM_NEW_EMAC_TXB=64 @@ -577,7 +617,6 @@ CONFIG_IBM_NEW_EMAC_ZMII=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -646,6 +685,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_NVRAM is not set # CONFIG_GEN_RTC is not set # CONFIG_R3964 is not set @@ -663,6 +703,7 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_GPIO is not set CONFIG_I2C_IBM_IIC=y # CONFIG_I2C_MPC is not set # CONFIG_I2C_OCORES is not set @@ -685,12 +726,9 @@ CONFIG_I2C_IBM_IIC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_LEGACY=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -699,7 +737,30 @@ CONFIG_EEPROM_LEGACY=y # CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -# CONFIG_GPIOLIB is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_XILINX is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y @@ -721,6 +782,7 @@ CONFIG_SENSORS_AD7414=y # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set @@ -735,11 +797,15 @@ CONFIG_SENSORS_AD7414=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set @@ -785,6 +851,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set @@ -870,11 +937,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # -# see USB_STORAGE Help for more information +# also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -915,7 +982,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set @@ -929,6 +995,8 @@ CONFIG_USB_STORAGE=y # # OTG and related infrastructure # +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set @@ -946,6 +1014,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y # # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_WBSD is not set +CONFIG_MMC_PIKASD=y # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -953,16 +1022,31 @@ CONFIG_LEDS_CLASS=y # # LED drivers # +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_GPIO_PLATFORM is not set +CONFIG_LEDS_GPIO_OF=y +# CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set # # LED Triggers # -# CONFIG_LEDS_TRIGGERS is not set +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# # CONFIG_ACCESSIBILITY is not set # CONFIG_EDAC is not set # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set @@ -973,6 +1057,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set # CONFIG_EXT4_FS is not set CONFIG_JBD=y @@ -993,6 +1078,11 @@ CONFIG_INOTIFY_USER=y # CONFIG_FUSE_FS is not set # +# Caches +# +# CONFIG_FSCACHE is not set + +# # CD-ROM/DVD Filesystems # # CONFIG_ISO9660_FS is not set @@ -1039,6 +1129,12 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_XATTR is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1049,6 +1145,7 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1060,7 +1157,6 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1115,6 +1211,7 @@ CONFIG_NLS_ISO8859_15=y # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y # CONFIG_DLM is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines @@ -1122,7 +1219,7 @@ CONFIG_NLS_UTF8=y CONFIG_BITREVERSE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y -# CONFIG_CRC16 is not set +CONFIG_CRC16=y CONFIG_CRC_T10DIF=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y @@ -1130,16 +1227,19 @@ CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_HAVE_LMB=y +CONFIG_NLATTR=y # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set +CONFIG_PRINTK_TIME=y CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 @@ -1152,11 +1252,15 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1180,9 +1284,12 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y # # Tracers @@ -1190,24 +1297,27 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set # CONFIG_BOOT_TRACER is not set # CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set -# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set # CONFIG_MSI_BITMAP_SELFTEST is not set # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_VIRQ_DEBUG is not set -CONFIG_BDI_SWITCH=y +# CONFIG_BDI_SWITCH is not set # CONFIG_PPC_EARLY_DEBUG is not set # @@ -1223,6 +1333,8 @@ CONFIG_CRYPTO=y # Crypto core or helper # # CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y # CONFIG_CRYPTO_MANAGER is not set # CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set @@ -1294,13 +1406,15 @@ CONFIG_CRYPTO=y # # Compression # -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y # # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_PPC4XX is not set # CONFIG_PPC_CLOCK is not set # CONFIG_VIRTUALIZATION is not set diff --git a/arch/powerpc/include/asm/delay.h b/arch/powerpc/include/asm/delay.h index 1e2eb41fa05..52e4d54da2a 100644 --- a/arch/powerpc/include/asm/delay.h +++ b/arch/powerpc/include/asm/delay.h @@ -63,6 +63,8 @@ extern void udelay(unsigned long usecs); udelay(delay); \ else \ cpu_relax(); \ + if (!__ret) \ + __ret = (condition); \ __ret; \ }) diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 9aba5a38a7c..c8b32925567 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -46,15 +46,13 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ .task = &tsk, \ .exec_domain = &default_exec_domain, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c index 75ff47fed7b..c244133c67a 100644 --- a/arch/powerpc/kernel/mpc7450-pmu.c +++ b/arch/powerpc/kernel/mpc7450-pmu.c @@ -10,7 +10,6 @@ */ #include <linux/string.h> #include <linux/perf_counter.h> -#include <linux/string.h> #include <asm/reg.h> #include <asm/cputable.h> diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c index 5d755ef7ac8..5a9f5cbd40a 100644 --- a/arch/powerpc/kernel/power7-pmu.c +++ b/arch/powerpc/kernel/power7-pmu.c @@ -358,6 +358,7 @@ static struct power_pmu power7_pmu = { .get_constraint = power7_get_constraint, .get_alternatives = power7_get_alternatives, .disable_pmc = power7_disable_pmc, + .flags = PPMU_ALT_SIPR, .n_generic = ARRAY_SIZE(power7_generic_events), .generic_events = power7_generic_events, .cache_events = &power7_cache_events, diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index 6637c87fe70..833097ac45d 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c @@ -10,7 +10,6 @@ */ #include <linux/string.h> #include <linux/perf_counter.h> -#include <linux/string.h> #include <asm/reg.h> #include <asm/cputable.h> diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c index bc400c78c97..bc122a120bf 100644 --- a/arch/powerpc/mm/gup.c +++ b/arch/powerpc/mm/gup.c @@ -159,7 +159,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, int psize; #endif - pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); + pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); start &= PAGE_MASK; addr = start; @@ -170,7 +170,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, start, len))) goto slow_irqon; - pr_debug(" aligned: %lx .. %lx\n", start, end); + pr_devel(" aligned: %lx .. %lx\n", start, end); #ifdef CONFIG_HUGETLB_PAGE /* We bail out on slice boundary crossing when hugetlb is @@ -234,7 +234,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, do { VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift); ptep = huge_pte_offset(mm, a); - pr_debug(" %016lx: huge ptep %p\n", a, ptep); + pr_devel(" %016lx: huge ptep %p\n", a, ptep); if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages, &nr)) goto slow; @@ -249,7 +249,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, #ifdef CONFIG_PPC64 VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift); #endif - pr_debug(" %016lx: normal pgd %p\n", addr, + pr_devel(" %016lx: normal pgd %p\n", addr, (void *)pgd_val(pgd)); next = pgd_addr_end(addr, end); if (pgd_none(pgd)) @@ -269,7 +269,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, slow: local_irq_enable(); slow_irqon: - pr_debug(" slow path ! nr = %d\n", nr); + pr_devel(" slow path ! nr = %d\n", nr); /* Try to get the remaining pages with get_user_pages */ start += nr << PAGE_SHIFT; diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index 8343986809c..92a197117d5 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c @@ -89,7 +89,7 @@ static unsigned int steal_context_smp(unsigned int id) id = first_context; continue; } - pr_debug("[%d] steal context %d from mm @%p\n", + pr_devel("[%d] steal context %d from mm @%p\n", smp_processor_id(), id, mm); /* Mark this mm has having no context anymore */ @@ -126,7 +126,7 @@ static unsigned int steal_context_up(unsigned int id) /* Pick up the victim mm */ mm = context_mm[id]; - pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm); + pr_devel("[%d] steal context %d from mm @%p\n", cpu, id, mm); /* Flush the TLB for that context */ local_flush_tlb_mm(mm); @@ -180,7 +180,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) spin_lock(&context_lock); #ifndef DEBUG_STEAL_ONLY - pr_debug("[%d] activating context for mm @%p, active=%d, id=%d\n", + pr_devel("[%d] activating context for mm @%p, active=%d, id=%d\n", cpu, next, next->context.active, next->context.id); #endif @@ -189,7 +189,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) next->context.active++; if (prev) { #ifndef DEBUG_STEAL_ONLY - pr_debug(" old context %p active was: %d\n", + pr_devel(" old context %p active was: %d\n", prev, prev->context.active); #endif WARN_ON(prev->context.active < 1); @@ -236,7 +236,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) next->context.id = id; #ifndef DEBUG_STEAL_ONLY - pr_debug("[%d] picked up new id %d, nrf is now %d\n", + pr_devel("[%d] picked up new id %d, nrf is now %d\n", cpu, id, nr_free_contexts); #endif @@ -247,7 +247,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) * local TLB for it and unmark it before we use it */ if (test_bit(id, stale_map[cpu])) { - pr_debug("[%d] flushing stale context %d for mm @%p !\n", + pr_devel("[%d] flushing stale context %d for mm @%p !\n", cpu, id, next); local_flush_tlb_mm(next); @@ -314,13 +314,13 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - pr_debug("MMU: Allocating stale context map for CPU %d\n", cpu); + pr_devel("MMU: Allocating stale context map for CPU %d\n", cpu); stale_map[cpu] = kzalloc(CTX_MAP_SIZE, GFP_KERNEL); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: case CPU_DEAD_FROZEN: - pr_debug("MMU: Freeing stale context map for CPU %d\n", cpu); + pr_devel("MMU: Freeing stale context map for CPU %d\n", cpu); kfree(stale_map[cpu]); stale_map[cpu] = NULL; break; diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index ae1d67cc090..627767d6169 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -129,12 +129,12 @@ static pte_t do_dcache_icache_coherency(pte_t pte) page = pfn_to_page(pfn); if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { - pr_debug("do_dcache_icache_coherency... flushing\n"); + pr_devel("do_dcache_icache_coherency... flushing\n"); flush_dcache_icache_page(page); set_bit(PG_arch_1, &page->flags); } else - pr_debug("do_dcache_icache_coherency... already clean\n"); + pr_devel("do_dcache_icache_coherency... already clean\n"); return __pte(pte_val(pte) | _PAGE_HWEXEC); } diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 3b52c80e5e3..5b7038f248b 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -14,8 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#undef DEBUG - #include <asm/pgtable.h> #include <asm/mmu.h> #include <asm/mmu_context.h> @@ -27,11 +25,6 @@ #include <linux/compiler.h> #include <asm/udbg.h> -#ifdef DEBUG -#define DBG(fmt...) printk(fmt) -#else -#define DBG pr_debug -#endif extern void slb_allocate_realmode(unsigned long ea); extern void slb_allocate_user(unsigned long ea); @@ -285,13 +278,13 @@ void slb_initialize(void) patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size); - DBG("SLB: linear LLP = %04lx\n", linear_llp); - DBG("SLB: io LLP = %04lx\n", io_llp); + pr_devel("SLB: linear LLP = %04lx\n", linear_llp); + pr_devel("SLB: io LLP = %04lx\n", io_llp); #ifdef CONFIG_SPARSEMEM_VMEMMAP patch_slb_encoding(slb_miss_kernel_load_vmemmap, SLB_VSID_KERNEL | vmemmap_llp); - DBG("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); + pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); #endif } diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 1be1b5e5979..937eb90677d 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -72,7 +72,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, */ if (huge) { #ifdef CONFIG_HUGETLB_PAGE - psize = get_slice_psize(mm, addr);; + psize = get_slice_psize(mm, addr); #else BUG(); psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */ diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c index 258fa4411e9..c591339daf5 100644 --- a/arch/powerpc/oprofile/cell/vma_map.c +++ b/arch/powerpc/oprofile/cell/vma_map.c @@ -185,7 +185,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu, goto fail; if (shdr_str.sh_type != SHT_STRTAB) - goto fail;; + goto fail; for (j = 0; j < shdr.sh_size / sizeof (sym); j++) { if (copy_from_user(&sym, spu_elf_start + diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 0362c88f47d..e5c1b096c3e 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -64,8 +64,6 @@ define_machine(warp) { }; -static u32 post_info; - static int __init warp_post_info(void) { struct device_node *np; @@ -87,10 +85,9 @@ static int __init warp_post_info(void) iounmap(fpga); - if (post1 || post2) { + if (post1 || post2) printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2); - post_info = 1; - } else + else printk(KERN_INFO "Warp POST OK\n"); return 0; @@ -166,6 +163,9 @@ static irqreturn_t temp_isr(int irq, void *context) value ^= 1; mdelay(500); } + + /* Not reached */ + return IRQ_HANDLED; } static int pika_setup_leds(void) @@ -179,15 +179,10 @@ static int pika_setup_leds(void) } for_each_child_of_node(np, child) - if (strcmp(child->name, "green") == 0) { + if (strcmp(child->name, "green") == 0) green_led = of_get_gpio(child, 0); - /* Turn back on the green LED */ - gpio_set_value(green_led, 1); - } else if (strcmp(child->name, "red") == 0) { + else if (strcmp(child->name, "red") == 0) red_led = of_get_gpio(child, 0); - /* Set based on post */ - gpio_set_value(red_led, post_info); - } of_node_put(np); diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index ddf0bdc0fc8..7ee979f323d 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c @@ -147,7 +147,7 @@ int __init pq2ads_pci_init_irq(void) goto out; } - priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic)); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { of_node_put(np); ret = -ENOMEM; diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index c71498dbf21..aca5741ddc6 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -85,7 +85,7 @@ static inline void axon_msi_debug_setup(struct device_node *dn, static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) { - pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); + pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); dcr_write(msic->dcr_host, dcr_n, val); } @@ -98,7 +98,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) int retry = 0; write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG); - pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); + pr_devel("axon_msi: original write_offset 0x%x\n", write_offset); /* write_offset doesn't wrap properly, so we have to mask it */ write_offset &= MSIC_FIFO_SIZE_MASK; @@ -108,7 +108,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) msi = le32_to_cpu(msic->fifo_virt[idx]); msi &= 0xFFFF; - pr_debug("axon_msi: woff %x roff %x msi %x\n", + pr_devel("axon_msi: woff %x roff %x msi %x\n", write_offset, msic->read_offset, msi); if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) { @@ -123,12 +123,12 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) */ udelay(1); retry++; - pr_debug("axon_msi: invalid irq 0x%x!\n", msi); + pr_devel("axon_msi: invalid irq 0x%x!\n", msi); continue; } if (retry) { - pr_debug("axon_msi: late irq 0x%x, retry %d\n", + pr_devel("axon_msi: late irq 0x%x, retry %d\n", msi, retry); retry = 0; } @@ -332,7 +332,7 @@ static int axon_msi_shutdown(struct of_device *device) struct axon_msic *msic = dev_get_drvdata(&device->dev); u32 tmp; - pr_debug("axon_msi: disabling %s\n", + pr_devel("axon_msi: disabling %s\n", msic->irq_host->of_node->full_name); tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; @@ -349,7 +349,7 @@ static int axon_msi_probe(struct of_device *device, unsigned int virq; int dcr_base, dcr_len; - pr_debug("axon_msi: setting up dn %s\n", dn->full_name); + pr_devel("axon_msi: setting up dn %s\n", dn->full_name); msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL); if (!msic) { @@ -403,7 +403,7 @@ static int axon_msi_probe(struct of_device *device, set_irq_data(virq, msic); set_irq_chained_handler(virq, axon_msi_cascade); - pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); + pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq); /* Enable the MSIC hardware */ msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32); @@ -484,13 +484,13 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) addr = of_translate_address(dn, of_get_property(dn, "reg", NULL)); if (addr == OF_BAD_ADDR) { - pr_debug("axon_msi: couldn't translate reg property\n"); + pr_devel("axon_msi: couldn't translate reg property\n"); return; } msic->trigger = ioremap(addr, 0x4); if (!msic->trigger) { - pr_debug("axon_msi: ioremap failed\n"); + pr_devel("axon_msi: ioremap failed\n"); return; } @@ -498,7 +498,7 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) if (!debugfs_create_file(name, 0600, powerpc_debugfs_root, msic, &fops_msic)) { - pr_debug("axon_msi: debugfs_create_file failed!\n"); + pr_devel("axon_msi: debugfs_create_file failed!\n"); return; } } diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 22ecfbe7183..708c7513337 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -251,7 +251,7 @@ static void g5_pfunc_switch_volt(int speed_mode) static struct pmf_function *pfunc_cpu_setfreq_high; static struct pmf_function *pfunc_cpu_setfreq_low; static struct pmf_function *pfunc_cpu_getfreq; -static struct pmf_function *pfunc_slewing_done;; +static struct pmf_function *pfunc_slewing_done; static int g5_pfunc_switch_freq(int speed_mode) { diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index dce73634910..d212006a5b3 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -609,7 +609,7 @@ static int pmacpic_find_viaint(void) np = of_find_node_by_name(NULL, "via-pmu"); if (np == NULL) goto not_found; - viaint = irq_of_parse_and_map(np, 0);; + viaint = irq_of_parse_and_map(np, 0); not_found: #endif /* CONFIG_ADB_PMU */ diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 9fead0faf38..3f763c5284a 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -284,7 +284,6 @@ static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) int result; dump_mmio_region(r); -; result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, r->lpar_addr); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e3139fa5e55..903eb9eec68 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -286,7 +286,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long hpte_v, hpte_r; if (!(vflags & HPTE_V_BOLTED)) - pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " + pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " "rflags=%lx, vflags=%lx, psize=%d)\n", hpte_group, va, pa, rflags, vflags, psize); @@ -294,7 +294,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, hpte_r = hpte_encode_r(pa, psize) | rflags; if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); + pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); /* Now fill in the actual HPTE */ /* Set CEC cookie to 0 */ @@ -311,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); if (unlikely(lpar_rc == H_PTEG_FULL)) { if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" full\n"); + pr_devel(" full\n"); return -1; } @@ -322,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, */ if (unlikely(lpar_rc != H_SUCCESS)) { if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" lpar err %lu\n", lpar_rc); + pr_devel(" lpar err %lu\n", lpar_rc); return -2; } if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" -> slot: %lu\n", slot & 7); + pr_devel(" -> slot: %lu\n", slot & 7); /* Because of iSeries, we have to pass down the secondary * bucket bit here as well @@ -418,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, want_v = hpte_encode_avpn(va, psize, ssize); - pr_debug(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", + pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", want_v, slot, flags, psize); lpar_rc = plpar_pte_protect(flags, slot, want_v); if (lpar_rc == H_NOT_FOUND) { - pr_debug("not found !\n"); + pr_devel("not found !\n"); return -1; } - pr_debug("ok\n"); + pr_devel("ok\n"); BUG_ON(lpar_rc != H_SUCCESS); @@ -503,7 +503,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, unsigned long lpar_rc; unsigned long dummy1, dummy2; - pr_debug(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", + pr_devel(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", slot, va, psize, local); want_v = hpte_encode_avpn(va, psize, ssize); diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index be3581a8c29..419f8a637ff 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -190,10 +190,10 @@ static void xics_unmask_irq(unsigned int virq) int call_status; int server; - pr_debug("xics: unmask virq %d\n", virq); + pr_devel("xics: unmask virq %d\n", virq); irq = (unsigned int)irq_map[virq].hwirq; - pr_debug(" -> map to hwirq 0x%x\n", irq); + pr_devel(" -> map to hwirq 0x%x\n", irq); if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) return; @@ -252,7 +252,7 @@ static void xics_mask_irq(unsigned int virq) { unsigned int irq; - pr_debug("xics: mask virq %d\n", virq); + pr_devel("xics: mask virq %d\n", virq); irq = (unsigned int)irq_map[virq].hwirq; if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) @@ -414,7 +414,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node) static int xics_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw); + pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); /* Insert the interrupt mapping into the radix tree for fast lookup */ irq_radix_revmap_insert(xics_host, virq, hw); diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 39db9d1155d..cbb3bed75d3 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -965,7 +965,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr) break; default: str = "Unknown"; - break;; + break; } dev_info(dev, "Hardware port width: %s\n", str); diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index a86d3ce01ea..69e2630c906 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -728,12 +728,10 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) if (ret) return NULL; - ipic = alloc_bootmem(sizeof(struct ipic)); + ipic = kzalloc(sizeof(*ipic), GFP_KERNEL); if (ipic == NULL) return NULL; - memset(ipic, 0, sizeof(struct ipic)); - ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, NR_IPIC_INTS, &ipic_host_ops, 0); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d46de1f0f3e..3981ae4cb58 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -508,9 +508,8 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n"); /* Allocate fixups array */ - mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup)); + mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL); BUG_ON(mpic->fixups == NULL); - memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup)); /* Init spinlock */ spin_lock_init(&mpic->fixup_lock); @@ -1109,9 +1108,8 @@ struct mpic * __init mpic_alloc(struct device_node *node, psize /= 4; bits = intvec_top + 1; mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); - mpic->protected = alloc_bootmem(mapsize); + mpic->protected = kzalloc(mapsize, GFP_KERNEL); BUG_ON(mpic->protected == NULL); - memset(mpic->protected, 0, mapsize); for (i = 0; i < psize; i++) { if (psrc[i] > intvec_top) continue; @@ -1353,7 +1351,8 @@ void __init mpic_init(struct mpic *mpic) #ifdef CONFIG_PM /* allocate memory to save mpic state */ - mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save)); + mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data), + GFP_KERNEL); BUG_ON(mpic->save_data == NULL); #endif } diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index daefc93ddff..6ff9d71b4c0 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1531,7 +1531,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, */ /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(ep_size));; + sa = (0xffffffffffffffffull << ilog2(ep_size)); /* Setup BAR0 */ out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); @@ -1550,7 +1550,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); } else { /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; + sa = (0xffffffffffffffffull << ilog2(size)); if (res->flags & IORESOURCE_PREFETCH) sa |= 0x8; diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index 63cdf9887f3..074905c3ee5 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -333,12 +333,10 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags, if (ret) return; - qe_ic = alloc_bootmem(sizeof(struct qe_ic)); + qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL); if (qe_ic == NULL) return; - memset(qe_ic, 0, sizeof(struct qe_ic)); - qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, NR_QE_IC_INTS, &qe_ic_host_ops, 0); if (qe_ic->irqhost == NULL) diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index d35405c5943..466ce9ace12 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -258,11 +258,10 @@ static struct uic * __init uic_init_one(struct device_node *node) BUG_ON(! of_device_is_compatible(node, "ibm,uic")); - uic = alloc_bootmem(sizeof(*uic)); + uic = kzalloc(sizeof(*uic), GFP_KERNEL); if (! uic) return NULL; /* FIXME: panic? */ - memset(uic, 0, sizeof(*uic)); spin_lock_init(&uic->lock); indexp = of_get_property(node, "cell-index", &len); if (!indexp || (len != sizeof(u32))) { diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 925bcc64903..ba1cab9fc1f 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -61,7 +61,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 46d1a5e71f7..120bd31a46e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -34,6 +34,7 @@ config SUPERH32 select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_SYSCALLS + select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB select ARCH_HIBERNATION_POSSIBLE if MMU diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 39224b57c6e..52a132c24aa 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -123,4 +123,15 @@ config SH64_SR_WATCH bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" depends on SUPERH64 +config STACK_DEBUG + bool "Enable diagnostic checks of the kernel stack" + depends on FUNCTION_TRACER + select DEBUG_STACKOVERFLOW + default n + help + This option allows checks to be performed on the kernel stack + at runtime. Saying Y here will add overhead to every function + call and will therefore incur a major performance hit. Most + users should say N. + endmenu diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index b09311ad1db..7e0bcc4d4a9 100644 --- a/arch/sh/include/asm/ftrace.h +++ b/arch/sh/include/asm/ftrace.h @@ -13,8 +13,11 @@ extern void mcount(void); #ifdef CONFIG_DYNAMIC_FTRACE #define CALL_ADDR ((long)(ftrace_call)) #define STUB_ADDR ((long)(ftrace_stub)) +#define GRAPH_ADDR ((long)(ftrace_graph_call)) +#define CALLER_ADDR ((long)(ftrace_caller)) #define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALL_ADDR) - 4) +#define GRAPH_INSN_OFFSET ((CALLER_ADDR - GRAPH_ADDR) - 4) struct dyn_arch_ftrace { /* No extra data needed on sh */ diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index 499e315f4be..5123bcaa850 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h @@ -51,7 +51,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index fee924a9c46..94ed99b6800 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -30,6 +30,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index 99aceb28ee2..d218e808294 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c @@ -26,6 +26,7 @@ int main(void) DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); + DEFINE(TI_SIZE, sizeof(struct thread_info)); #ifdef CONFIG_HIBERNATION DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 4f62eced0ae..6647dfcb781 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c @@ -16,11 +16,13 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/kernel.h> #include <asm/ftrace.h> #include <asm/cacheflush.h> #include <asm/unistd.h> #include <trace/syscall.h> +#ifdef CONFIG_DYNAMIC_FTRACE static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; static unsigned char ftrace_nop[4]; @@ -133,6 +135,126 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifdef CONFIG_DYNAMIC_FTRACE +extern void ftrace_graph_call(void); + +static int ftrace_mod(unsigned long ip, unsigned long old_addr, + unsigned long new_addr) +{ + unsigned char code[MCOUNT_INSN_SIZE]; + + if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) + return -EFAULT; + + if (old_addr != __raw_readl((unsigned long *)code)) + return -EINVAL; + + __raw_writel(new_addr, ip); + return 0; +} + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned long ip, old_addr, new_addr; + + ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET; + old_addr = (unsigned long)(&skip_trace); + new_addr = (unsigned long)(&ftrace_graph_caller); + + return ftrace_mod(ip, old_addr, new_addr); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned long ip, old_addr, new_addr; + + ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET; + old_addr = (unsigned long)(&ftrace_graph_caller); + new_addr = (unsigned long)(&skip_trace); + + return ftrace_mod(ip, old_addr, new_addr); +} +#endif /* CONFIG_DYNAMIC_FTRACE */ + +/* + * Hook the return address and push it in the stack of return addrs + * in the current thread info. + * + * This is the main routine for the function graph tracer. The function + * graph tracer essentially works like this: + * + * parent is the stack address containing self_addr's return address. + * We pull the real return address out of parent and store it in + * current's ret_stack. Then, we replace the return address on the stack + * with the address of return_to_handler. self_addr is the function that + * called mcount. + * + * When self_addr returns, it will jump to return_to_handler which calls + * ftrace_return_to_handler. ftrace_return_to_handler will pull the real + * return address off of current's ret_stack and jump to it. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + int faulted, err; + struct ftrace_graph_ent trace; + unsigned long return_hooker = (unsigned long)&return_to_handler; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + /* + * Protect against fault, even if it shouldn't + * happen. This tool is too much intrusive to + * ignore such a protection. + */ + __asm__ __volatile__( + "1: \n\t" + "mov.l @%2, %0 \n\t" + "2: \n\t" + "mov.l %3, @%2 \n\t" + "mov #0, %1 \n\t" + "3: \n\t" + ".section .fixup, \"ax\" \n\t" + "4: \n\t" + "mov.l 5f, %0 \n\t" + "jmp @%0 \n\t" + " mov #1, %1 \n\t" + ".balign 4 \n\t" + "5: .long 3b \n\t" + ".previous \n\t" + ".section __ex_table,\"a\" \n\t" + ".long 1b, 4b \n\t" + ".long 2b, 4b \n\t" + ".previous \n\t" + : "=&r" (old), "=r" (faulted) + : "r" (parent), "r" (return_hooker) + ); + + if (unlikely(faulted)) { + ftrace_graph_stop(); + WARN_ON(1); + return; + } + + err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0); + if (err == -EBUSY) { + __raw_writel(old, parent); + return; + } + + trace.func = self_addr; + + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + __raw_writel(old, parent); + } +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #ifdef CONFIG_FTRACE_SYSCALLS diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 92d7740faab..9fee977f176 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -23,6 +23,7 @@ #include <linux/tick.h> #include <linux/reboot.h> #include <linux/fs.h> +#include <linux/ftrace.h> #include <linux/preempt.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -264,8 +265,8 @@ static void ubc_set_tracing(int asid, unsigned long pc) * switch_to(x,y) should switch tasks from x to y. * */ -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *next) +__notrace_funcgraph struct task_struct * +__switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(CONFIG_SH_FPU) unlazy_fpu(prev, task_pt_regs(prev)); diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/arch/sh/kernel/vmlinux_64.lds.S diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index aaea580b65b..19328d90a2d 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -25,6 +25,7 @@ memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o lib-$(CONFIG_MMU) += copy_page.o clear_page.o lib-$(CONFIG_FUNCTION_TRACER) += mcount.o +lib-$(CONFIG_FUNCTION_GRAPH_TRACER) += mcount.o lib-y += $(memcpy-y) $(udivsi3-y) EXTRA_CFLAGS += -Werror diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 71e87f9b4fd..bd3ec648bec 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -9,6 +9,8 @@ * for more details. */ #include <asm/ftrace.h> +#include <asm/thread_info.h> +#include <asm/asm-offsets.h> #define MCOUNT_ENTER() \ mov.l r4, @-r15; \ @@ -28,6 +30,55 @@ rts; \ mov.l @r15+, r4 +#ifdef CONFIG_STACK_DEBUG +/* + * Perform diagnostic checks on the state of the kernel stack. + * + * Check for stack overflow. If there is less than 1KB free + * then it has overflowed. + * + * Make sure the stack pointer contains a valid address. Valid + * addresses for kernel stacks are anywhere after the bss + * (after _ebss) and anywhere in init_thread_union (init_stack). + */ +#define STACK_CHECK() \ + mov #(THREAD_SIZE >> 10), r0; \ + shll8 r0; \ + shll2 r0; \ + \ + /* r1 = sp & (THREAD_SIZE - 1) */ \ + mov #-1, r1; \ + add r0, r1; \ + and r15, r1; \ + \ + mov #TI_SIZE, r3; \ + mov #(STACK_WARN >> 8), r2; \ + shll8 r2; \ + add r3, r2; \ + \ + /* Is the stack overflowing? */ \ + cmp/hi r2, r1; \ + bf stack_panic; \ + \ + /* If sp > _ebss then we're OK. */ \ + mov.l .L_ebss, r1; \ + cmp/hi r1, r15; \ + bt 1f; \ + \ + /* If sp < init_stack, we're not OK. */ \ + mov.l .L_init_thread_union, r1; \ + cmp/hs r1, r15; \ + bf stack_panic; \ + \ + /* If sp > init_stack && sp < _ebss, not OK. */ \ + add r0, r1; \ + cmp/hs r1, r15; \ + bt stack_panic; \ +1: +#else +#define STACK_CHECK() +#endif /* CONFIG_STACK_DEBUG */ + .align 2 .globl _mcount .type _mcount,@function @@ -41,6 +92,8 @@ mcount: tst r0, r0 bf ftrace_stub #endif + STACK_CHECK() + MCOUNT_ENTER() #ifdef CONFIG_DYNAMIC_FTRACE @@ -58,14 +111,62 @@ mcount_call: jsr @r6 nop +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + mov.l .Lftrace_graph_return, r6 + mov.l .Lftrace_stub, r7 + cmp/eq r6, r7 + bt 1f + + mov.l .Lftrace_graph_caller, r0 + jmp @r0 + nop + +1: + mov.l .Lftrace_graph_entry, r6 + mov.l .Lftrace_graph_entry_stub, r7 + cmp/eq r6, r7 + bt skip_trace + + mov.l .Lftrace_graph_caller, r0 + jmp @r0 + nop + + .align 2 +.Lftrace_graph_return: + .long ftrace_graph_return +.Lftrace_graph_entry: + .long ftrace_graph_entry +.Lftrace_graph_entry_stub: + .long ftrace_graph_entry_stub +.Lftrace_graph_caller: + .long ftrace_graph_caller +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + + .globl skip_trace skip_trace: MCOUNT_LEAVE() .align 2 .Lftrace_trace_function: - .long ftrace_trace_function + .long ftrace_trace_function #ifdef CONFIG_DYNAMIC_FTRACE +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* + * NOTE: Do not move either ftrace_graph_call or ftrace_caller + * as this will affect the calculation of GRAPH_INSN_OFFSET. + */ + .globl ftrace_graph_call +ftrace_graph_call: + mov.l .Lskip_trace, r0 + jmp @r0 + nop + + .align 2 +.Lskip_trace: + .long skip_trace +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + .globl ftrace_caller ftrace_caller: mov.l .Lfunction_trace_stop, r0 @@ -73,6 +174,8 @@ ftrace_caller: tst r0, r0 bf ftrace_stub + STACK_CHECK() + MCOUNT_ENTER() .globl ftrace_call @@ -81,7 +184,12 @@ ftrace_call: jsr @r6 nop +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + bra ftrace_graph_call + nop +#else MCOUNT_LEAVE() +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #endif /* CONFIG_DYNAMIC_FTRACE */ /* @@ -100,6 +208,98 @@ ftrace_stub: rts nop +#ifdef CONFIG_STACK_DEBUG + .globl stack_panic +stack_panic: + mov.l .Ldump_stack, r0 + jsr @r0 + nop + + mov.l .Lpanic, r0 + jsr @r0 + mov.l .Lpanic_s, r4 + + rts + nop + .align 2 .Lfunction_trace_stop: .long function_trace_stop +.L_ebss: + .long _ebss +.L_init_thread_union: + .long init_thread_union +.Lpanic: + .long panic +.Lpanic_s: + .long .Lpanic_str +.Ldump_stack: + .long dump_stack + + .section .rodata + .align 2 +.Lpanic_str: + .string "Stack error" +#endif /* CONFIG_STACK_DEBUG */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_caller +ftrace_graph_caller: + mov.l 2f, r0 + mov.l @r0, r0 + tst r0, r0 + bt 1f + + mov.l 3f, r1 + jmp @r1 + nop +1: + /* + * MCOUNT_ENTER() pushed 5 registers onto the stack, so + * the stack address containing our return address is + * r15 + 20. + */ + mov #20, r0 + add r15, r0 + mov r0, r4 + + mov.l .Lprepare_ftrace_return, r0 + jsr @r0 + nop + + MCOUNT_LEAVE() + + .align 2 +2: .long function_trace_stop +3: .long skip_trace +.Lprepare_ftrace_return: + .long prepare_ftrace_return + + .globl return_to_handler +return_to_handler: + /* + * Save the return values. + */ + mov.l r0, @-r15 + mov.l r1, @-r15 + + mov #0, r4 + + mov.l .Lftrace_return_to_handler, r0 + jsr @r0 + nop + + /* + * The return value from ftrace_return_handler has the real + * address that we should return to. + */ + lds r0, pr + mov.l @r15+, r1 + rts + mov.l @r15+, r0 + + + .align 2 +.Lftrace_return_to_handler: + .long ftrace_return_to_handler +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index 0f7b0e5fb1c..844d73a0340 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -54,8 +54,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -64,7 +62,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 65865726b28..1b45a7bbe40 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -125,8 +125,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -135,7 +133,7 @@ struct thread_info { .task = &tsk, \ .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ .exec_domain = &default_exec_domain, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 62274ab9471..fd911f85536 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -32,7 +32,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 56d43d0a396..0960de54495 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -70,8 +70,8 @@ void show_stack(struct task_struct *task, unsigned long *esp) if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) - printk("\n" KERN_INFO " "); - printk("%08lx ", *stack++); + printk(KERN_INFO " "); + printk(KERN_CONT "%08lx ", *stack++); } show_trace(task, esp); diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c07f7220590..738bdc6b0f8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1913,6 +1913,18 @@ config DMAR_DEFAULT_ON recommended you say N here while the DMAR code remains experimental. +config DMAR_BROKEN_GFX_WA + def_bool n + prompt "Workaround broken graphics drivers (going away soon)" + depends on DMAR + ---help--- + Current Graphics drivers tend to use physical address + for DMA and avoid using DMA APIs. Setting this config + option permits the IOMMU driver to set a unity map for + all the OS-visible memory. Hence the driver can continue + to use physical addresses for DMA, at least until this + option is removed in the 2.6.32 kernel. + config DMAR_FLOPPY_WA def_bool y depends on DMAR diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c index d660be49236..49e0c18833e 100644 --- a/arch/x86/boot/video-bios.c +++ b/arch/x86/boot/video-bios.c @@ -37,14 +37,13 @@ static int set_bios_mode(u8 mode) ireg.al = mode; /* AH=0x00 Set Video Mode */ intcall(0x10, &ireg, NULL); - ireg.ah = 0x0f; /* Get Current Video Mode */ intcall(0x10, &ireg, &oreg); do_restore = 1; /* Assume video contents were lost */ /* Not all BIOSes are clean with the top bit */ - new_mode = ireg.al & 0x7f; + new_mode = oreg.al & 0x7f; if (new_mode == mode) return 0; /* Mode change OK */ diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index c700147d6ff..275dd177f19 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -45,7 +45,7 @@ static int vesa_probe(void) ireg.di = (size_t)&vginfo; intcall(0x10, &ireg, &oreg); - if (ireg.ax != 0x004f || + if (oreg.ax != 0x004f || vginfo.signature != VESA_MAGIC || vginfo.version < 0x0102) return 0; /* Not present */ @@ -70,7 +70,7 @@ static int vesa_probe(void) ireg.di = (size_t)&vminfo; intcall(0x10, &ireg, &oreg); - if (ireg.ax != 0x004f) + if (oreg.ax != 0x004f) continue; if ((vminfo.mode_attr & 0x15) == 0x05) { diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index 2503d4e64c2..dc5a667ff79 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -19,7 +19,10 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} /** * atomic_set - set atomic variable @@ -28,7 +31,10 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) (((v)->counter) = (i)) +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} /** * atomic_add - add integer to atomic variable @@ -200,8 +206,15 @@ static inline int atomic_sub_return(int i, atomic_t *v) return atomic_add_return(-i, v); } -#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline int atomic_xchg(atomic_t *v, int new) +{ + return xchg(&v->counter, new); +} /** * atomic_add_unless - add unless the number is already a given value @@ -250,45 +263,12 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) /* An 64bit atomic type */ typedef struct { - unsigned long long counter; + u64 __aligned(8) counter; } atomic64_t; #define ATOMIC64_INIT(val) { (val) } -/** - * atomic64_read - read atomic64 variable - * @ptr: pointer of type atomic64_t - * - * Atomically reads the value of @v. - * Doesn't imply a read memory barrier. - */ -#define __atomic64_read(ptr) ((ptr)->counter) - -static inline unsigned long long -cmpxchg8b(unsigned long long *ptr, unsigned long long old, unsigned long long new) -{ - asm volatile( - - LOCK_PREFIX "cmpxchg8b (%[ptr])\n" - - : "=A" (old) - - : [ptr] "D" (ptr), - "A" (old), - "b" (ll_low(new)), - "c" (ll_high(new)) - - : "memory"); - - return old; -} - -static inline unsigned long long -atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val, - unsigned long long new_val) -{ - return cmpxchg8b(&ptr->counter, old_val, new_val); -} +extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); /** * atomic64_xchg - xchg atomic64 variable @@ -298,18 +278,7 @@ atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val, * Atomically xchgs the value of @ptr to @new_val and returns * the old value. */ - -static inline unsigned long long -atomic64_xchg(atomic64_t *ptr, unsigned long long new_val) -{ - unsigned long long old_val; - - do { - old_val = atomic_read(ptr); - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); - - return old_val; -} +extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); /** * atomic64_set - set atomic64 variable @@ -318,10 +287,7 @@ atomic64_xchg(atomic64_t *ptr, unsigned long long new_val) * * Atomically sets the value of @ptr to @new_val. */ -static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val) -{ - atomic64_xchg(ptr, new_val); -} +extern void atomic64_set(atomic64_t *ptr, u64 new_val); /** * atomic64_read - read atomic64 variable @@ -329,17 +295,30 @@ static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val) * * Atomically reads the value of @ptr and returns it. */ -static inline unsigned long long atomic64_read(atomic64_t *ptr) +static inline u64 atomic64_read(atomic64_t *ptr) { - unsigned long long curr_val; - - do { - curr_val = __atomic64_read(ptr); - } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val); - - return curr_val; + u64 res; + + /* + * Note, we inline this atomic64_t primitive because + * it only clobbers EAX/EDX and leaves the others + * untouched. We also (somewhat subtly) rely on the + * fact that cmpxchg8b returns the current 64-bit value + * of the memory location we are touching: + */ + asm volatile( + "mov %%ebx, %%eax\n\t" + "mov %%ecx, %%edx\n\t" + LOCK_PREFIX "cmpxchg8b %1\n" + : "=&A" (res) + : "m" (*ptr) + ); + + return res; } +extern u64 atomic64_read(atomic64_t *ptr); + /** * atomic64_add_return - add and return * @delta: integer value to add @@ -347,34 +326,14 @@ static inline unsigned long long atomic64_read(atomic64_t *ptr) * * Atomically adds @delta to @ptr and returns @delta + *@ptr */ -static inline unsigned long long -atomic64_add_return(unsigned long long delta, atomic64_t *ptr) -{ - unsigned long long old_val, new_val; - - do { - old_val = atomic_read(ptr); - new_val = old_val + delta; - - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); - - return new_val; -} - -static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr) -{ - return atomic64_add_return(-delta, ptr); -} +extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); -static inline long atomic64_inc_return(atomic64_t *ptr) -{ - return atomic64_add_return(1, ptr); -} - -static inline long atomic64_dec_return(atomic64_t *ptr) -{ - return atomic64_sub_return(1, ptr); -} +/* + * Other variants with different arithmetic operators: + */ +extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); +extern u64 atomic64_inc_return(atomic64_t *ptr); +extern u64 atomic64_dec_return(atomic64_t *ptr); /** * atomic64_add - add integer to atomic64 variable @@ -383,10 +342,7 @@ static inline long atomic64_dec_return(atomic64_t *ptr) * * Atomically adds @delta to @ptr. */ -static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr) -{ - atomic64_add_return(delta, ptr); -} +extern void atomic64_add(u64 delta, atomic64_t *ptr); /** * atomic64_sub - subtract the atomic64 variable @@ -395,10 +351,7 @@ static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr) * * Atomically subtracts @delta from @ptr. */ -static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr) -{ - atomic64_add(-delta, ptr); -} +extern void atomic64_sub(u64 delta, atomic64_t *ptr); /** * atomic64_sub_and_test - subtract value from variable and test result @@ -409,13 +362,7 @@ static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr) * true if the result is zero, or false for all * other cases. */ -static inline int -atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr) -{ - unsigned long long old_val = atomic64_sub_return(delta, ptr); - - return old_val == 0; -} +extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); /** * atomic64_inc - increment atomic64 variable @@ -423,10 +370,7 @@ atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr) * * Atomically increments @ptr by 1. */ -static inline void atomic64_inc(atomic64_t *ptr) -{ - atomic64_add(1, ptr); -} +extern void atomic64_inc(atomic64_t *ptr); /** * atomic64_dec - decrement atomic64 variable @@ -434,10 +378,7 @@ static inline void atomic64_inc(atomic64_t *ptr) * * Atomically decrements @ptr by 1. */ -static inline void atomic64_dec(atomic64_t *ptr) -{ - atomic64_sub(1, ptr); -} +extern void atomic64_dec(atomic64_t *ptr); /** * atomic64_dec_and_test - decrement and test @@ -447,10 +388,7 @@ static inline void atomic64_dec(atomic64_t *ptr) * returns true if the result is 0, or false for all other * cases. */ -static inline int atomic64_dec_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(1, ptr); -} +extern int atomic64_dec_and_test(atomic64_t *ptr); /** * atomic64_inc_and_test - increment and test @@ -460,10 +398,7 @@ static inline int atomic64_dec_and_test(atomic64_t *ptr) * and returns true if the result is zero, or false for all * other cases. */ -static inline int atomic64_inc_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(-1, ptr); -} +extern int atomic64_inc_and_test(atomic64_t *ptr); /** * atomic64_add_negative - add and test if negative @@ -474,13 +409,7 @@ static inline int atomic64_inc_and_test(atomic64_t *ptr) * if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int -atomic64_add_negative(unsigned long long delta, atomic64_t *ptr) -{ - long long old_val = atomic64_add_return(delta, ptr); - - return old_val < 0; -} +extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); #include <asm-generic/atomic-long.h> #endif /* _ASM_X86_ATOMIC_32_H */ diff --git a/arch/x86/include/asm/atomic_64.h b/arch/x86/include/asm/atomic_64.h index 0d636022000..d605dc268e7 100644 --- a/arch/x86/include/asm/atomic_64.h +++ b/arch/x86/include/asm/atomic_64.h @@ -18,7 +18,10 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} /** * atomic_set - set atomic variable @@ -27,7 +30,10 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) (((v)->counter) = (i)) +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} /** * atomic_add - add integer to atomic variable @@ -192,7 +198,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) * Atomically reads the value of @v. * Doesn't imply a read memory barrier. */ -#define atomic64_read(v) ((v)->counter) +static inline long atomic64_read(const atomic64_t *v) +{ + return v->counter; +} /** * atomic64_set - set atomic64 variable @@ -201,7 +210,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) * * Atomically sets the value of @v to @i. */ -#define atomic64_set(v, i) (((v)->counter) = (i)) +static inline void atomic64_set(atomic64_t *v, long i) +{ + v->counter = i; +} /** * atomic64_add - add integer to atomic64 variable @@ -355,11 +367,25 @@ static inline long atomic64_sub_return(long i, atomic64_t *v) #define atomic64_inc_return(v) (atomic64_add_return(1, (v))) #define atomic64_dec_return(v) (atomic64_sub_return(1, (v))) -#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) +static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline long atomic64_xchg(atomic64_t *v, long new) +{ + return xchg(&v->counter, new); +} -#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) +static inline long atomic_cmpxchg(atomic_t *v, int old, int new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline long atomic_xchg(atomic_t *v, int new) +{ + return xchg(&v->counter, new); +} /** * atomic_add_unless - add unless the number is a given value diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 2d81af3974a..7b2d71df39a 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -111,12 +111,9 @@ enum fixed_addresses { #ifdef CONFIG_PARAVIRT FIX_PARAVIRT_BOOTMAP, #endif - FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */ - FIX_TEXT_POKE1, + FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ + FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ __end_of_permanent_fixed_addresses, -#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT - FIX_OHCI1394_BASE, -#endif /* * 256 temporary boot-time mappings, used by early_ioremap(), * before ioremap() is functional. @@ -129,6 +126,9 @@ enum fixed_addresses { FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - (__end_of_permanent_fixed_addresses & 255), FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, +#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT + FIX_OHCI1394_BASE, +#endif #ifdef CONFIG_X86_32 FIX_WP_TEST, #endif diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1692fb5050e..6be7fc254b5 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -246,10 +246,6 @@ #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) -/* Intel Model 6 */ -#define MSR_P6_EVNTSEL0 0x00000186 -#define MSR_P6_EVNTSEL1 0x00000187 - /* P4/Xeon+ specific */ #define MSR_IA32_MCG_EAX 0x00000180 #define MSR_IA32_MCG_EBX 0x00000181 diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index c9726440993..c86e5ed4af5 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h @@ -72,7 +72,6 @@ void lapic_watchdog_stop(void); int lapic_watchdog_init(unsigned nmi_hz); int lapic_wd_event(unsigned nmi_hz); unsigned lapic_adjust_nmi_hz(unsigned hz); -int lapic_watchdog_ok(void); void disable_lapic_nmi_watchdog(void); void enable_lapic_nmi_watchdog(void); void stop_nmi(void); diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index b7e5db87639..4e77853321d 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -302,4 +302,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) #define _raw_read_relax(lock) cpu_relax() #define _raw_write_relax(lock) cpu_relax() +/* The {read|write|spin}_lock() on x86 are full memory barriers. */ +static inline void smp_mb__after_lock(void) { } +#define ARCH_HAS_SMP_MB_AFTER_LOCK + #endif /* _ASM_X86_SPINLOCK_H */ diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index f517944b2b1..cf86a5e7381 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -3,6 +3,8 @@ extern int kstack_depth_to_print; +int x86_is_stack_id(int id, char *name); + /* Generic stack tracer with callbacks */ struct stacktrace_ops { diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index b0783520988..fad7d40b75f 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -49,7 +49,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 6c327b852e2..430d5b24af7 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -26,6 +26,8 @@ CFLAGS_tsc.o := $(nostackp) CFLAGS_paravirt.o := $(nostackp) GCOV_PROFILE_vsyscall_64.o := n GCOV_PROFILE_hpet.o := n +GCOV_PROFILE_tsc.o := n +GCOV_PROFILE_paravirt.o := n obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 9372f0406ad..6c99f503780 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1192,7 +1192,7 @@ out: return 0; } -struct notifier_block device_nb = { +static struct notifier_block device_nb = { .notifier_call = device_change_notifier, }; @@ -1763,7 +1763,7 @@ static void *alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) - return 0; + return NULL; paddr = virt_to_phys(virt_addr); diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 10b2accd12e..c1b17e97252 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -472,6 +472,8 @@ static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) if (iommu->evt_buf == NULL) return NULL; + iommu->evt_buf_size = EVT_BUFFER_SIZE; + return iommu->evt_buf; } @@ -691,6 +693,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; devid_to = e->ext >> 8; + set_dev_entry_from_acpi(iommu, devid , e->flags, 0); set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); amd_iommu_alias_table[devid] = devid_to; break; @@ -749,11 +752,13 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; for (dev_i = devid_start; dev_i <= devid; ++dev_i) { - if (alias) + if (alias) { amd_iommu_alias_table[dev_i] = devid_to; - set_dev_entry_from_acpi(iommu, - amd_iommu_alias_table[dev_i], - flags, ext_flags); + set_dev_entry_from_acpi(iommu, + devid_to, flags, ext_flags); + } + set_dev_entry_from_acpi(iommu, dev_i, + flags, ext_flags); } break; default: diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 8c7c042ecad..0a1c2830ec6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -140,7 +140,6 @@ int x2apic_mode; #ifdef CONFIG_X86_X2APIC /* x2apic enabled before OS handover */ static int x2apic_preenabled; -static int disable_x2apic; static __init int setup_nox2apic(char *str) { if (x2apic_enabled()) { @@ -149,7 +148,6 @@ static __init int setup_nox2apic(char *str) return 0; } - disable_x2apic = 1; setup_clear_cpu_cap(X86_FEATURE_X2APIC); return 0; } diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4d0216fcb36..90b5e6efa93 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1716,25 +1716,19 @@ __apicdebuginit(void) print_IO_APIC(void) return; } -__apicdebuginit(void) print_APIC_bitfield(int base) +__apicdebuginit(void) print_APIC_field(int base) { - unsigned int v; - int i, j; + int i; if (apic_verbosity == APIC_QUIET) return; - printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); - for (i = 0; i < 8; i++) { - v = apic_read(base + i*0x10); - for (j = 0; j < 32; j++) { - if (v & (1<<j)) - printk("1"); - else - printk("0"); - } - printk("\n"); - } + printk(KERN_DEBUG); + + for (i = 0; i < 8; i++) + printk(KERN_CONT "%08x", apic_read(base + i*0x10)); + + printk(KERN_CONT "\n"); } __apicdebuginit(void) print_local_APIC(void *dummy) @@ -1745,7 +1739,7 @@ __apicdebuginit(void) print_local_APIC(void *dummy) if (apic_verbosity == APIC_QUIET) return; - printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", + printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, read_apic_id()); @@ -1786,11 +1780,11 @@ __apicdebuginit(void) print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC SPIV: %08x\n", v); printk(KERN_DEBUG "... APIC ISR field:\n"); - print_APIC_bitfield(APIC_ISR); + print_APIC_field(APIC_ISR); printk(KERN_DEBUG "... APIC TMR field:\n"); - print_APIC_bitfield(APIC_TMR); + print_APIC_field(APIC_TMR); printk(KERN_DEBUG "... APIC IRR field:\n"); - print_APIC_bitfield(APIC_IRR); + print_APIC_field(APIC_IRR); if (APIC_INTEGRATED(ver)) { /* !82489DX */ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 81cbe64ed6b..2a50ef89100 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -299,7 +299,7 @@ static int transition_pstate(struct powernow_k8_data *data, u32 pstate) static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid) { - if (core_voltage_pre_transition(data, reqvid)) + if (core_voltage_pre_transition(data, reqvid, reqfid)) return 1; if (core_frequency_transition(data, reqfid)) @@ -327,17 +327,20 @@ static int transition_fid_vid(struct powernow_k8_data *data, /* Phase 1 - core voltage transition ... setup voltage */ static int core_voltage_pre_transition(struct powernow_k8_data *data, - u32 reqvid) + u32 reqvid, u32 reqfid) { u32 rvosteps = data->rvo; u32 savefid = data->currfid; - u32 maxvid, lo; + u32 maxvid, lo, rvomult = 1; dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, " "reqvid 0x%x, rvo 0x%x\n", smp_processor_id(), data->currfid, data->currvid, reqvid, data->rvo); + if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP)) + rvomult = 2; + rvosteps *= rvomult; rdmsr(MSR_FIDVID_STATUS, lo, maxvid); maxvid = 0x1f & (maxvid >> 16); dprintk("ph1 maxvid=0x%x\n", maxvid); @@ -351,7 +354,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, return 1; } - while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { + while ((rvosteps > 0) && + ((rvomult * data->rvo + data->currvid) > reqvid)) { if (data->currvid == maxvid) { rvosteps = 0; } else { @@ -384,13 +388,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) u32 vcoreqfid, vcocurrfid, vcofiddiff; u32 fid_interval, savevid = data->currvid; - if ((reqfid < HI_FID_TABLE_BOTTOM) && - (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk(KERN_ERR PFX "ph2: illegal lo-lo transition " - "0x%x 0x%x\n", reqfid, data->currfid); - return 1; - } - if (data->currfid == reqfid) { printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", data->currfid); @@ -407,6 +404,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid : vcoreqfid - vcocurrfid; + if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP)) + vcofiddiff = 0; + while (vcofiddiff > 2) { (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); @@ -1081,14 +1081,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, return 0; } - if ((fid < HI_FID_TABLE_BOTTOM) && - (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk(KERN_ERR PFX - "ignoring illegal change in lo freq table-%x to 0x%x\n", - data->currfid, fid); - return 1; - } - dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n", smp_processor_id(), fid, vid); freqs.old = find_khz_freq_from_fid(data->currfid); @@ -1267,7 +1259,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) { static const char ACPI_PSS_BIOS_BUG_MSG[] = KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n" - KERN_ERR FW_BUG PFX "Try again with latest BIOS.\n"; + FW_BUG PFX "Try again with latest BIOS.\n"; struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; int rc; diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index c9c1190b5e1..02ce824073c 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -215,7 +215,8 @@ struct pst_s { #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg) -static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid); +static int core_voltage_pre_transition(struct powernow_k8_data *data, + u32 reqvid, u32 regfid); static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid); static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index af425b83202..484c1e5f658 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -194,14 +194,14 @@ static void print_mce(struct mce *m) m->cs, m->ip); if (m->cs == __KERNEL_CS) print_symbol("{%s}", m->ip); - printk("\n"); + printk(KERN_CONT "\n"); } printk(KERN_EMERG "TSC %llx ", m->tsc); if (m->addr) - printk("ADDR %llx ", m->addr); + printk(KERN_CONT "ADDR %llx ", m->addr); if (m->misc) - printk("MISC %llx ", m->misc); - printk("\n"); + printk(KERN_CONT "MISC %llx ", m->misc); + printk(KERN_CONT "\n"); printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid); @@ -209,13 +209,13 @@ static void print_mce(struct mce *m) static void print_mce_head(void) { - printk(KERN_EMERG "\n" KERN_EMERG "HARDWARE ERROR\n"); + printk(KERN_EMERG "\nHARDWARE ERROR\n"); } static void print_mce_tail(void) { printk(KERN_EMERG "This is not a software problem!\n" - KERN_EMERG "Run through mcelog --ascii to decode and contact your hardware vendor\n"); + "Run through mcelog --ascii to decode and contact your hardware vendor\n"); } #define PANIC_TIMEOUT 5 /* 5 seconds */ diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index d4cf4ce19aa..36c3dc7b899 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -1561,6 +1561,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip) static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry); static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry); +static DEFINE_PER_CPU(int, in_nmi_frame); static void @@ -1576,7 +1577,9 @@ static void backtrace_warning(void *data, char *msg) static int backtrace_stack(void *data, char *name) { - /* Process all stacks: */ + per_cpu(in_nmi_frame, smp_processor_id()) = + x86_is_stack_id(NMI_STACK, name); + return 0; } @@ -1584,6 +1587,9 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) { struct perf_callchain_entry *entry = data; + if (per_cpu(in_nmi_frame, smp_processor_id())) + return; + if (reliable) callchain_store(entry, addr); } diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 5c481f6205b..e60ed740d2b 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -803,8 +803,3 @@ int __kprobes lapic_wd_event(unsigned nmi_hz) wd_ops->rearm(wd, nmi_hz); return 1; } - -int lapic_watchdog_ok(void) -{ - return wd_ops != NULL; -} diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index d593cd1f58d..bca5fba91c9 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -19,6 +19,12 @@ #include "dumpstack.h" +/* Just a stub for now */ +int x86_is_stack_id(int id, char *name) +{ + return 0; +} + void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data) diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index d35db5993fd..54b0a327676 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -19,10 +19,8 @@ #include "dumpstack.h" -static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, - unsigned *usedp, char **idp) -{ - static char ids[][8] = { + +static char x86_stack_ids[][8] = { [DEBUG_STACK - 1] = "#DB", [NMI_STACK - 1] = "NMI", [DOUBLEFAULT_STACK - 1] = "#DF", @@ -33,6 +31,15 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; + +int x86_is_stack_id(int id, char *name) +{ + return x86_stack_ids[id - 1] == name; +} + +static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, + unsigned *usedp, char **idp) +{ unsigned k; /* @@ -61,7 +68,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, if (*usedp & (1U << k)) break; *usedp |= 1U << k; - *idp = ids[k]; + *idp = x86_stack_ids[k]; return (unsigned long *)end; } /* @@ -81,12 +88,13 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, do { ++j; end -= EXCEPTION_STKSZ; - ids[j][4] = '1' + (j - N_EXCEPTION_STACKS); + x86_stack_ids[j][4] = '1' + + (j - N_EXCEPTION_STACKS); } while (stack < end - EXCEPTION_STKSZ); if (*usedp & (1U << j)) break; *usedp |= 1U << j; - *idp = ids[j]; + *idp = x86_stack_ids[j]; return (unsigned long *)end; } #endif diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index c4ca89d9aaf..5cb5725b2ba 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -627,10 +627,9 @@ __init void e820_setup_gap(void) #ifdef CONFIG_X86_64 if (!found) { gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024; - printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit " - "address range\n" - KERN_ERR "PCI: Unassigned devices with 32bit resource " - "registers may break!\n"); + printk(KERN_ERR + "PCI: Warning: Cannot find a gap in the 32bit address range\n" + "PCI: Unassigned devices with 32bit resource registers may break!\n"); } #endif diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index a78ecad0c90..c664d515f61 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -200,7 +200,7 @@ static void kvm_leave_lazy_mmu(void) state->mode = paravirt_get_lazy_mode(); } -static void paravirt_ops_setup(void) +static void __init paravirt_ops_setup(void) { pv_info.name = "KVM"; pv_info.paravirt_enabled = 1; diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index cfd9f906389..d2e56b8f48e 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -675,7 +675,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) nommu: /* Should not happen anymore */ printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n" - KERN_WARNING "falling back to iommu=soft.\n"); + "falling back to iommu=soft.\n"); return -1; } diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index f9d35632666..07c31899c9c 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,6 +10,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o ifeq ($(CONFIG_X86_32),y) + obj-y += atomic64_32.o lib-y += checksum_32.o lib-y += strstr_32.o lib-y += semaphore_32.o string_32.o diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c new file mode 100644 index 00000000000..824fa0be55a --- /dev/null +++ b/arch/x86/lib/atomic64_32.c @@ -0,0 +1,230 @@ +#include <linux/compiler.h> +#include <linux/module.h> +#include <linux/types.h> + +#include <asm/processor.h> +#include <asm/cmpxchg.h> +#include <asm/atomic.h> + +static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) +{ + u32 low = new; + u32 high = new >> 32; + + asm volatile( + LOCK_PREFIX "cmpxchg8b %1\n" + : "+A" (old), "+m" (*ptr) + : "b" (low), "c" (high) + ); + return old; +} + +u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val) +{ + return cmpxchg8b(&ptr->counter, old_val, new_val); +} +EXPORT_SYMBOL(atomic64_cmpxchg); + +/** + * atomic64_xchg - xchg atomic64 variable + * @ptr: pointer to type atomic64_t + * @new_val: value to assign + * + * Atomically xchgs the value of @ptr to @new_val and returns + * the old value. + */ +u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) +{ + /* + * Try first with a (possibly incorrect) assumption about + * what we have there. We'll do two loops most likely, + * but we'll get an ownership MESI transaction straight away + * instead of a read transaction followed by a + * flush-for-ownership transaction: + */ + u64 old_val, real_val = 0; + + do { + old_val = real_val; + + real_val = atomic64_cmpxchg(ptr, old_val, new_val); + + } while (real_val != old_val); + + return old_val; +} +EXPORT_SYMBOL(atomic64_xchg); + +/** + * atomic64_set - set atomic64 variable + * @ptr: pointer to type atomic64_t + * @new_val: value to assign + * + * Atomically sets the value of @ptr to @new_val. + */ +void atomic64_set(atomic64_t *ptr, u64 new_val) +{ + atomic64_xchg(ptr, new_val); +} +EXPORT_SYMBOL(atomic64_set); + +/** +EXPORT_SYMBOL(atomic64_read); + * atomic64_add_return - add and return + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr and returns @delta + *@ptr + */ +noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr) +{ + /* + * Try first with a (possibly incorrect) assumption about + * what we have there. We'll do two loops most likely, + * but we'll get an ownership MESI transaction straight away + * instead of a read transaction followed by a + * flush-for-ownership transaction: + */ + u64 old_val, new_val, real_val = 0; + + do { + old_val = real_val; + new_val = old_val + delta; + + real_val = atomic64_cmpxchg(ptr, old_val, new_val); + + } while (real_val != old_val); + + return new_val; +} +EXPORT_SYMBOL(atomic64_add_return); + +u64 atomic64_sub_return(u64 delta, atomic64_t *ptr) +{ + return atomic64_add_return(-delta, ptr); +} +EXPORT_SYMBOL(atomic64_sub_return); + +u64 atomic64_inc_return(atomic64_t *ptr) +{ + return atomic64_add_return(1, ptr); +} +EXPORT_SYMBOL(atomic64_inc_return); + +u64 atomic64_dec_return(atomic64_t *ptr) +{ + return atomic64_sub_return(1, ptr); +} +EXPORT_SYMBOL(atomic64_dec_return); + +/** + * atomic64_add - add integer to atomic64 variable + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr. + */ +void atomic64_add(u64 delta, atomic64_t *ptr) +{ + atomic64_add_return(delta, ptr); +} +EXPORT_SYMBOL(atomic64_add); + +/** + * atomic64_sub - subtract the atomic64 variable + * @delta: integer value to subtract + * @ptr: pointer to type atomic64_t + * + * Atomically subtracts @delta from @ptr. + */ +void atomic64_sub(u64 delta, atomic64_t *ptr) +{ + atomic64_add(-delta, ptr); +} +EXPORT_SYMBOL(atomic64_sub); + +/** + * atomic64_sub_and_test - subtract value from variable and test result + * @delta: integer value to subtract + * @ptr: pointer to type atomic64_t + * + * Atomically subtracts @delta from @ptr and returns + * true if the result is zero, or false for all + * other cases. + */ +int atomic64_sub_and_test(u64 delta, atomic64_t *ptr) +{ + u64 new_val = atomic64_sub_return(delta, ptr); + + return new_val == 0; +} +EXPORT_SYMBOL(atomic64_sub_and_test); + +/** + * atomic64_inc - increment atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically increments @ptr by 1. + */ +void atomic64_inc(atomic64_t *ptr) +{ + atomic64_add(1, ptr); +} +EXPORT_SYMBOL(atomic64_inc); + +/** + * atomic64_dec - decrement atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically decrements @ptr by 1. + */ +void atomic64_dec(atomic64_t *ptr) +{ + atomic64_sub(1, ptr); +} +EXPORT_SYMBOL(atomic64_dec); + +/** + * atomic64_dec_and_test - decrement and test + * @ptr: pointer to type atomic64_t + * + * Atomically decrements @ptr by 1 and + * returns true if the result is 0, or false for all other + * cases. + */ +int atomic64_dec_and_test(atomic64_t *ptr) +{ + return atomic64_sub_and_test(1, ptr); +} +EXPORT_SYMBOL(atomic64_dec_and_test); + +/** + * atomic64_inc_and_test - increment and test + * @ptr: pointer to type atomic64_t + * + * Atomically increments @ptr by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +int atomic64_inc_and_test(atomic64_t *ptr) +{ + return atomic64_sub_and_test(-1, ptr); +} +EXPORT_SYMBOL(atomic64_inc_and_test); + +/** + * atomic64_add_negative - add and test if negative + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. + */ +int atomic64_add_negative(u64 delta, atomic64_t *ptr) +{ + s64 new_val = atomic64_add_return(delta, ptr); + + return new_val < 0; +} +EXPORT_SYMBOL(atomic64_add_negative); diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index 9a10a78bb4a..ebeafcce04a 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -5,15 +5,14 @@ * Zero a page. * rdi page */ - ALIGN -clear_page_c: +ENTRY(clear_page_c) CFI_STARTPROC movl $4096/8,%ecx xorl %eax,%eax rep stosq ret CFI_ENDPROC -ENDPROC(clear_page) +ENDPROC(clear_page_c) ENTRY(clear_page) CFI_STARTPROC diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index f118c110af3..6ba0f7bb85e 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -75,6 +75,7 @@ ENTRY(copy_to_user) jae bad_to_user ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string CFI_ENDPROC +ENDPROC(copy_to_user) /* Standard copy_from_user with segment limit checking */ ENTRY(copy_from_user) diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 7c8ca91bb9e..1f118d462ac 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -751,7 +751,7 @@ survive: if (retval == -ENOMEM && is_global_init(current)) { up_read(¤t->mm->mmap_sem); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto survive; } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 78a5fff857b..85307cc6e45 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -426,10 +426,11 @@ static noinline int vmalloc_fault(unsigned long address) } static const char errata93_warning[] = -KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n" -KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n" -KERN_ERR "******* Please consider a BIOS update.\n" -KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"; +KERN_ERR +"******* Your BIOS seems to not contain a fix for K8 errata #93\n" +"******* Working around it, but it may cause SEGVs or burn power.\n" +"******* Please consider a BIOS update.\n" +"******* Disabling USB legacy in the BIOS may also help.\n"; /* * No vm86 mode in 64-bit mode: diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 47ce9a2ce5e..0607119cef9 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -12,6 +12,7 @@ #include <asm/system.h> #include <asm/tlbflush.h> #include <asm/tlb.h> +#include <asm/proto.h> DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index b177652251a..6176fe8f29e 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -598,8 +598,15 @@ void __init paging_init(void) sparse_memory_present_with_active_regions(MAX_NUMNODES); sparse_init(); - /* clear the default setting with node 0 */ - nodes_clear(node_states[N_NORMAL_MEMORY]); + + /* + * clear the default setting with node 0 + * note: don't use nodes_clear here, that is really clearing when + * numa support is not compiled in, and later node_set_state + * will not set it back. + */ + node_clear_state(0, N_NORMAL_MEMORY); + free_area_init_nodes(max_zone_pfns); } diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b07dd8d0b32..89b9a5cd63d 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -390,7 +390,7 @@ static int __init p4_init(char **cpu_type) static int force_arch_perfmon; static int force_cpu_type(const char *str, struct kernel_param *kp) { - if (!strcmp(str, "archperfmon")) { + if (!strcmp(str, "arch_perfmon")) { force_arch_perfmon = 1; printk(KERN_INFO "oprofile: forcing architectural perfmon\n"); } diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index b26626dc517..1014eb4bfc3 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -68,6 +68,10 @@ setup_resource(struct acpi_resource *acpi_res, void *data) unsigned long flags; struct resource *root; int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; + u64 start, end; + + if (bus_has_transparent_bridge(info->bus)) + max_root_bus_resources -= 3; status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) @@ -84,25 +88,24 @@ setup_resource(struct acpi_resource *acpi_res, void *data) } else return AE_OK; - res = &info->res[info->res_num]; - res->name = info->name; - res->flags = flags; - res->start = addr.minimum + addr.translation_offset; - res->end = res->start + addr.address_length - 1; - res->child = NULL; - - if (bus_has_transparent_bridge(info->bus)) - max_root_bus_resources -= 3; + start = addr.minimum + addr.translation_offset; + end = start + addr.address_length - 1; if (info->res_num >= max_root_bus_resources) { printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx " "from %s for %s due to _CRS returning more than " - "%d resource descriptors\n", (unsigned long) res->start, - (unsigned long) res->end, root->name, info->name, + "%d resource descriptors\n", (unsigned long) start, + (unsigned long) end, root->name, info->name, max_root_bus_resources); - info->res_num++; return AE_OK; } + res = &info->res[info->res_num]; + res->name = info->name; + res->flags = flags; + res->start = start; + res->end = end; + res->child = NULL; + if (insert_resource(root, res)) { printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " "from %s for %s\n", (unsigned long) res->start, @@ -115,23 +118,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) } static void -adjust_transparent_bridge_resources(struct pci_bus *bus) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - int i; - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) { - for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) - dev->subordinate->resource[i] = - dev->bus->resource[i - 3]; - } - } -} - -static void get_current_resources(struct acpi_device *device, int busnum, int domain, struct pci_bus *bus) { @@ -158,8 +144,6 @@ get_current_resources(struct acpi_device *device, int busnum, info.res_num = 0; acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, &info); - if (info.res_num) - adjust_transparent_bridge_resources(bus); return; @@ -222,8 +206,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do */ memcpy(bus->sysdata, sd, sizeof(*sd)); kfree(sd); - } else - bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); + } else { + bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); + if (bus) { + if (pci_probe & PCI_USE__CRS) + get_current_resources(device, busnum, domain, + bus); + bus->subordinate = pci_scan_child_bus(bus); + } + } if (!bus) kfree(sd); @@ -238,8 +229,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do #endif } - if (bus && (pci_probe & PCI_USE__CRS)) - get_current_resources(device, busnum, domain, bus); return bus; } diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index f893d6a6e80..3ffa10df20b 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -100,8 +100,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) int j; struct pci_root_info *info; - /* don't go for it if _CRS is used */ - if (pci_probe & PCI_USE__CRS) + /* don't go for it if _CRS is used already */ + if (b->resource[0] != &ioport_resource || + b->resource[1] != &iomem_resource) return; /* if only one root bus, don't need to anything */ @@ -116,6 +117,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) if (i == pci_root_num) return; + printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", + b->number); + info = &pci_root_info[i]; for (j = 0; j < info->res_num; j++) { struct resource *res; diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile index de2abbd0754..a6a198c3362 100644 --- a/arch/x86/power/Makefile +++ b/arch/x86/power/Makefile @@ -1,7 +1,7 @@ # __restore_processor_state() restores %gs after S3 resume and so should not # itself be stack-protected nostackp := $(call cc-option, -fno-stack-protector) -CFLAGS_cpu_$(BITS).o := $(nostackp) +CFLAGS_cpu.o := $(nostackp) obj-$(CONFIG_PM_SLEEP) += cpu.o obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index 0f4fe1faf9b..13165641cc5 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h @@ -80,8 +80,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -92,7 +90,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index ba9ab934978..e64efac3b9d 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -354,10 +354,10 @@ void show_regs(struct pt_regs * regs) for (i = 0; i < 16; i++) { if ((i % 8) == 0) - printk ("\n" KERN_INFO "a%02d: ", i); - printk("%08lx ", regs->areg[i]); + printk(KERN_INFO "a%02d:", i); + printk(KERN_CONT " %08lx", regs->areg[i]); } - printk("\n"); + printk(KERN_CONT "\n"); printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n", regs->pc, regs->ps, regs->depc, regs->excvaddr); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 87276eb83f7..fd7080ed793 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2311,7 +2311,7 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) goto queue_fail; cfqq = cic_to_cfqq(cic, is_sync); - if (!cfqq) { + if (!cfqq || cfqq == &cfqd->oom_cfqq) { cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask); cic_set_cfqq(cic, cfqq, is_sync); } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index f0e0ce0a607..e5b10017a50 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -680,3 +680,4 @@ int __init blk_scsi_ioctl_init(void) blk_set_cmd_filter_defaults(&blk_default_cmd_filter); return 0; } +fs_initcall(blk_scsi_ioctl_init); diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 3d763fdf99b..24665067301 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -207,6 +207,16 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) void __iomem *tmp; int i, ret; + device_initialize(&dev->dev); + + /* + * Copy from device_add + */ + if (dev->dev.init_name) { + dev_set_name(&dev->dev, "%s", dev->dev.init_name); + dev->dev.init_name = NULL; + } + dev->dev.release = amba_device_release; dev->dev.bus = &amba_bustype; dev->dev.dma_mask = &dev->dma_mask; @@ -240,7 +250,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) goto err_release; } - ret = device_register(&dev->dev); + ret = device_add(&dev->dev); if (ret) goto err_release; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ddeb819c8f8..fc466531260 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -357,7 +357,7 @@ static void fw_dev_release(struct device *dev) kfree(fw_priv->pages); kfree(fw_priv->fw_id); kfree(fw_priv); - put_device(dev); + kfree(dev); module_put(THIS_MODULE); } @@ -408,13 +408,11 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, if (retval) { dev_err(device, "%s: device_register failed\n", __func__); put_device(f_dev); - goto error_kfree_fw_id; + return retval; } *dev_p = f_dev; return 0; -error_kfree_fw_id: - kfree(fw_priv->fw_id); error_kfree: kfree(f_dev); kfree(fw_priv); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index fae72545898..58a3e572f2c 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -762,6 +762,7 @@ static int dpm_prepare(pm_message_t state) dev->power.status = DPM_ON; if (error == -EAGAIN) { put_device(dev); + error = 0; continue; } printk(KERN_ERR "PM: Failed to prepare device %s " diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 9c6e5b0fe89..2f07b7c99a9 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1645,7 +1645,7 @@ static int __init fd_probe_drives(void) { int drive,drives,nomem; - printk(KERN_INFO "FD: probing units\n" KERN_INFO "found "); + printk(KERN_INFO "FD: probing units\nfound "); drives=0; nomem=0; for(drive=0;drive<FD_MAX_UNITS;drive++) { diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 83650e00632..99a506f619b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1372,8 +1372,10 @@ try_next_bio: wakeup = (pd->write_congestion_on > 0 && pd->bio_queue_size <= pd->write_congestion_off); spin_unlock(&pd->lock); - if (wakeup) - clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE); + if (wakeup) { + clear_bdi_congested(&pd->disk->queue->backing_dev_info, + BLK_RW_ASYNC); + } pkt->sleep_time = max(PACKET_WAIT_TIME, 1); pkt_set_state(pkt, PACKET_WAITING_STATE); @@ -2592,10 +2594,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) spin_lock(&pd->lock); if (pd->write_congestion_on > 0 && pd->bio_queue_size >= pd->write_congestion_on) { - set_bdi_congested(&q->backing_dev_info, WRITE); + set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC); do { spin_unlock(&pd->lock); - congestion_wait(WRITE, HZ); + congestion_wait(BLK_RW_ASYNC, HZ); spin_lock(&pd->lock); } while(pd->bio_queue_size > pd->write_congestion_off); } diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index f08491a3a81..b20abe102a2 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -390,9 +390,10 @@ static inline void ace_dump_mem(void *base, int len) static void ace_dump_regs(struct ace_device *ace) { - dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" - KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n" - KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", + dev_info(ace->dev, + " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" + " status:%.8x mpu_lba:%.8x busmode:%4x\n" + " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", ace_in32(ace, ACE_CTRL), ace_in(ace, ACE_SECCNTCMD), ace_in(ace, ACE_VERSION), diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5dcbe603eca..91b53eb1c05 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -305,10 +305,11 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) == BIOS_CNTL_LOCK_ENABLE_MASK) { static __initdata /*const*/ char warning[] = - KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" - KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" - KERN_WARNING PFX "you are certain that your system has a functional\n" - KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; + KERN_WARNING +PFX "Firmware space is locked read-only. If you can't or\n" +PFX "don't want to disable this in firmware setup, and if\n" +PFX "you are certain that your system has a functional\n" +PFX "RNG, try using the 'no_fwh_detect' option.\n"; if (no_fwh_detect) return -ENODEV; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 4159292e35c..621d1184673 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1478,10 +1478,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, status = inw(base + 0x4); if (status != 0) { dev_warn(&pdev->dev, "Card%d rejected load header:\n" - KERN_WARNING "Address:0x%x\n" - KERN_WARNING "Count:0x%x\n" - KERN_WARNING "Status:0x%x\n", - index + 1, frame->addr, frame->count, status); + "Address:0x%x\n" + "Count:0x%x\n" + "Status:0x%x\n", + index + 1, frame->addr, frame->count, status); goto errrelfw; } outsw(base, frame->data, word_count); @@ -1526,10 +1526,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, status = inw(base + 0x4); if (status != 0) { dev_warn(&pdev->dev, "Card%d rejected verify header:\n" - KERN_WARNING "Address:0x%x\n" - KERN_WARNING "Count:0x%x\n" - KERN_WARNING "Status: 0x%x\n", - index + 1, frame->addr, frame->count, status); + "Address:0x%x\n" + "Count:0x%x\n" + "Status: 0x%x\n", + index + 1, frame->addr, frame->count, status); goto errrelfw; } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index daebe1ba43d..9d1b4f548f6 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -75,114 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp) */ static void pty_unthrottle(struct tty_struct *tty) { - struct tty_struct *o_tty = tty->link; - - if (!o_tty) - return; - - tty_wakeup(o_tty); + tty_wakeup(tty->link); set_bit(TTY_THROTTLED, &tty->flags); } -/* - * WSH 05/24/97: modified to - * (1) use space in tty->flip instead of a shared temp buffer - * The flip buffers aren't being used for a pty, so there's lots - * of space available. The buffer is protected by a per-pty - * semaphore that should almost never come under contention. - * (2) avoid redundant copying for cases where count >> receive_room - * N.B. Calls from user space may now return an error code instead of - * a count. +/** + * pty_space - report space left for writing + * @to: tty we are writing into * - * FIXME: Our pty_write method is called with our ldisc lock held but - * not our partners. We can't just wait on the other one blindly without - * risking deadlocks. At some point when everything has settled down we need - * to look into making pty_write at least able to sleep over an ldisc change. + * The tty buffers allow 64K but we sneak a peak and clip at 8K this + * allows a lot of overspill room for echo and other fun messes to + * be handled properly + */ + +static int pty_space(struct tty_struct *to) +{ + int n = 8192 - to->buf.memory_used; + if (n < 0) + return 0; + return n; +} + +/** + * pty_write - write to a pty + * @tty: the tty we write from + * @buf: kernel buffer of data + * @count: bytes to write * - * The return on no ldisc is a bit counter intuitive but the logic works - * like this. During an ldisc change the other end will flush its buffers. We - * thus return the full length which is identical to the case where we had - * proper locking and happened to queue the bytes just before the flush during - * the ldisc change. + * Our "hardware" write method. Data is coming from the ldisc which + * may be in a non sleeping state. We simply throw this at the other + * end of the link as if we were an IRQ handler receiving stuff for + * the other side of the pty/tty pair. */ + static int pty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - struct tty_ldisc *ld; - int c = count; + int c; - if (!to || tty->stopped) + if (tty->stopped) return 0; - ld = tty_ldisc_ref(to); - - if (ld) { - c = to->receive_room; - if (c > count) - c = count; - ld->ops->receive_buf(to, buf, NULL, c); - tty_ldisc_deref(ld); + + /* This isn't locked but our 8K is quite sloppy so no + big deal */ + + c = pty_space(to); + if (c > count) + c = count; + if (c > 0) { + /* Stuff the data into the input queue of the other end */ + c = tty_insert_flip_string(to, buf, c); + /* And shovel */ + tty_flip_buffer_push(to); + tty_wakeup(tty); } return c; } +/** + * pty_write_room - write space + * @tty: tty we are writing from + * + * Report how many bytes the ldisc can send into the queue for + * the other device. + */ + static int pty_write_room(struct tty_struct *tty) { - struct tty_struct *to = tty->link; - - if (!to || tty->stopped) - return 0; - - return to->receive_room; + return pty_space(tty->link); } -/* - * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior - * The chars_in_buffer() value is used by the ldisc select() function - * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). - * The pty driver chars_in_buffer() Master/Slave must behave differently: - * - * The Master side needs to allow typed-ahead commands to accumulate - * while being canonicalized, so we report "our buffer" as empty until - * some threshold is reached, and then report the count. (Any count > - * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock - * the count returned must be 0 if no canonical data is available to be - * read. (The N_TTY ldisc.chars_in_buffer now knows this.) +/** + * pty_chars_in_buffer - characters currently in our tx queue + * @tty: our tty * - * The Slave side passes all characters in raw mode to the Master side's - * buffer where they can be read immediately, so in this case we can - * return the true count in the buffer. + * Report how much we have in the transmit queue. As everything is + * instantly at the other end this is easy to implement. */ + static int pty_chars_in_buffer(struct tty_struct *tty) { - struct tty_struct *to = tty->link; - struct tty_ldisc *ld; - int count = 0; - - /* We should get the line discipline lock for "tty->link" */ - if (!to) - return 0; - /* We cannot take a sleeping reference here without deadlocking with - an ldisc change - but it doesn't really matter */ - ld = tty_ldisc_ref(to); - if (ld == NULL) - return 0; - - /* The ldisc must report 0 if no characters available to be read */ - if (ld->ops->chars_in_buffer) - count = ld->ops->chars_in_buffer(to); - - tty_ldisc_deref(ld); - - if (tty->driver->subtype == PTY_TYPE_SLAVE) - return count; - - /* Master side driver ... if the other side's read buffer is less than - * half full, return 0 to allow writers to proceed; otherwise return - * the count. This leaves a comfortable margin to avoid overflow, - * and still allows half a buffer's worth of typed-ahead commands. - */ - return (count < N_TTY_BUF_SIZE/2) ? 0 : count; + return 0; } /* Set the lock flag on a pty */ @@ -202,20 +176,10 @@ static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; unsigned long flags; - struct tty_ldisc *ld; if (!to) return; - ld = tty_ldisc_ref(to); - - /* The other end is changing discipline */ - if (!ld) - return; - - if (ld->ops->flush_buffer) - to->ldisc->ops->flush_buffer(to); - tty_ldisc_deref(ld); - + /* tty_buffer_flush(to); FIXME */ if (to->packet) { spin_lock_irqsave(&tty->ctrl_lock, flags); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6e2ec0b1894..b90eda8b344 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = { * cpufreq_add_dev - add a CPU device * * Adds the cpufreq interface for a CPU device. + * + * The Oracle says: try running cpufreq registration/unregistration concurrently + * with with cpu hotplugging and all hell will break loose. Tried to clean this + * mess up, but more thorough testing is needed. - Mathieu */ static int cpufreq_add_dev(struct sys_device *sys_dev) { @@ -772,9 +776,6 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) struct sys_device *cpu_sys_dev; unsigned long flags; unsigned int j; -#ifdef CONFIG_SMP - struct cpufreq_policy *managed_policy; -#endif if (cpu_is_offline(cpu)) return 0; @@ -804,15 +805,12 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) goto nomem_out; } if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) { - kfree(policy); ret = -ENOMEM; - goto nomem_out; + goto err_free_policy; } if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { - free_cpumask_var(policy->cpus); - kfree(policy); ret = -ENOMEM; - goto nomem_out; + goto err_free_cpumask; } policy->cpu = cpu; @@ -820,7 +818,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) /* Initially set CPU itself as the policy_cpu */ per_cpu(policy_cpu, cpu) = cpu; - lock_policy_rwsem_write(cpu); + ret = (lock_policy_rwsem_write(cpu) < 0); + WARN_ON(ret); init_completion(&policy->kobj_unregister); INIT_WORK(&policy->update, handle_update); @@ -833,7 +832,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = cpufreq_driver->init(policy); if (ret) { dprintk("initialization failed\n"); - goto err_out; + goto err_unlock_policy; } policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; @@ -852,21 +851,29 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) #endif for_each_cpu(j, policy->cpus) { + struct cpufreq_policy *managed_policy; + if (cpu == j) continue; /* Check for existing affected CPUs. * They may not be aware of it due to CPU Hotplug. */ - managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */ + managed_policy = cpufreq_cpu_get(j); if (unlikely(managed_policy)) { /* Set proper policy_cpu */ unlock_policy_rwsem_write(cpu); per_cpu(policy_cpu, cpu) = managed_policy->cpu; - if (lock_policy_rwsem_write(cpu) < 0) - goto err_out_driver_exit; + if (lock_policy_rwsem_write(cpu) < 0) { + /* Should not go through policy unlock path */ + if (cpufreq_driver->exit) + cpufreq_driver->exit(policy); + ret = -EBUSY; + cpufreq_cpu_put(managed_policy); + goto err_free_cpumask; + } spin_lock_irqsave(&cpufreq_driver_lock, flags); cpumask_copy(managed_policy->cpus, policy->cpus); @@ -877,12 +884,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = sysfs_create_link(&sys_dev->kobj, &managed_policy->kobj, "cpufreq"); - if (ret) - goto err_out_driver_exit; - - cpufreq_debug_enable_ratelimit(); - ret = 0; - goto err_out_driver_exit; /* call driver->exit() */ + if (!ret) + cpufreq_cpu_put(managed_policy); + /* + * Success. We only needed to be added to the mask. + * Call driver->exit() because only the cpu parent of + * the kobj needed to call init(). + */ + goto out_driver_exit; /* call driver->exit() */ } } #endif @@ -892,25 +901,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, "cpufreq"); if (ret) - goto err_out_driver_exit; + goto out_driver_exit; /* set up files for this cpu device */ drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; drv_attr++; } if (cpufreq_driver->get) { ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; } if (cpufreq_driver->target) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; } spin_lock_irqsave(&cpufreq_driver_lock, flags); @@ -922,18 +931,22 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) /* symlink affected CPUs */ for_each_cpu(j, policy->cpus) { + struct cpufreq_policy *managed_policy; + if (j == cpu) continue; if (!cpu_online(j)) continue; dprintk("CPU %u already managed, adding link\n", j); - cpufreq_cpu_get(cpu); + managed_policy = cpufreq_cpu_get(cpu); cpu_sys_dev = get_cpu_sysdev(j); ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, "cpufreq"); - if (ret) + if (ret) { + cpufreq_cpu_put(managed_policy); goto err_out_unregister; + } } policy->governor = NULL; /* to assure that the starting sequence is @@ -965,17 +978,20 @@ err_out_unregister: per_cpu(cpufreq_cpu_data, j) = NULL; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +err_out_kobj_put: kobject_put(&policy->kobj); wait_for_completion(&policy->kobj_unregister); -err_out_driver_exit: +out_driver_exit: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); -err_out: +err_unlock_policy: unlock_policy_rwsem_write(cpu); +err_free_cpumask: + free_cpumask_var(policy->cpus); +err_free_policy: kfree(policy); - nomem_out: module_put(cpufreq_driver->owner); module_out: @@ -1070,8 +1086,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) spin_unlock_irqrestore(&cpufreq_driver_lock, flags); #endif - unlock_policy_rwsem_write(cpu); - if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); @@ -1088,6 +1102,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) if (cpufreq_driver->exit) cpufreq_driver->exit(data); + unlock_policy_rwsem_write(cpu); + free_cpumask_var(data->related_cpus); free_cpumask_var(data->cpus); kfree(data); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 7fc58af748b..57490502b21 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -63,22 +63,20 @@ struct cpu_dbs_info_s { unsigned int down_skip; unsigned int requested_freq; int cpu; - unsigned int enable:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ /* - * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug - * lock and dbs_mutex. cpu_hotplug lock should always be held before - * dbs_mutex. If any function that can potentially take cpu_hotplug lock - * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then - * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock - * is recursive for the same process. -Venki - * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it - * would deadlock with cancel_delayed_work_sync(), which is needed for proper - * raceless workqueue teardown. + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on + * different CPUs. It protects dbs_enable in governor start/stop. */ static DEFINE_MUTEX(dbs_mutex); @@ -143,9 +141,6 @@ dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, struct cpufreq_policy *policy; - if (!this_dbs_info->enable) - return 0; - policy = this_dbs_info->cur_policy; /* @@ -488,18 +483,12 @@ static void do_dbs_timer(struct work_struct *work) delay -= jiffies % delay; - if (lock_policy_rwsem_write(cpu) < 0) - return; - - if (!dbs_info->enable) { - unlock_policy_rwsem_write(cpu); - return; - } + mutex_lock(&dbs_info->timer_mutex); dbs_check_cpu(dbs_info); queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_info->timer_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -508,7 +497,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - dbs_info->enable = 1; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work, delay); @@ -516,7 +504,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { - dbs_info->enable = 0; cancel_delayed_work_sync(&dbs_info->work); } @@ -535,9 +522,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; - if (this_dbs_info->enable) /* Already enabled */ - break; - mutex_lock(&dbs_mutex); rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); @@ -561,6 +545,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->down_skip = 0; this_dbs_info->requested_freq = policy->cur; + mutex_init(&this_dbs_info->timer_mutex); dbs_enable++; /* * Start the timerschedule work, when this governor @@ -590,17 +575,19 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, &dbs_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); } - dbs_timer_init(this_dbs_info); - mutex_unlock(&dbs_mutex); + dbs_timer_init(this_dbs_info); + break; case CPUFREQ_GOV_STOP: - mutex_lock(&dbs_mutex); dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); dbs_enable--; + mutex_destroy(&this_dbs_info->timer_mutex); /* * Stop the timerschedule work, when this governor @@ -616,7 +603,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: - mutex_lock(&dbs_mutex); + mutex_lock(&this_dbs_info->timer_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, @@ -625,7 +612,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, __cpufreq_driver_target( this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); - mutex_unlock(&dbs_mutex); + mutex_unlock(&this_dbs_info->timer_mutex); break; } diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 1911d172935..d6ba14276bb 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -70,23 +70,21 @@ struct cpu_dbs_info_s { unsigned int freq_lo_jiffies; unsigned int freq_hi_jiffies; int cpu; - unsigned int enable:1, - sample_type:1; + unsigned int sample_type:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ /* - * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug - * lock and dbs_mutex. cpu_hotplug lock should always be held before - * dbs_mutex. If any function that can potentially take cpu_hotplug lock - * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then - * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock - * is recursive for the same process. -Venki - * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it - * would deadlock with cancel_delayed_work_sync(), which is needed for proper - * raceless workqueue teardown. + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on + * different CPUs. It protects dbs_enable in governor start/stop. */ static DEFINE_MUTEX(dbs_mutex); @@ -192,13 +190,18 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy, return freq_hi; } +static void ondemand_powersave_bias_init_cpu(int cpu) +{ + struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + static void ondemand_powersave_bias_init(void) { int i; for_each_online_cpu(i) { - struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i); - dbs_info->freq_table = cpufreq_frequency_get_table(i); - dbs_info->freq_lo = 0; + ondemand_powersave_bias_init_cpu(i); } } @@ -240,12 +243,10 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; mutex_lock(&dbs_mutex); - if (ret != 1) { - mutex_unlock(&dbs_mutex); - return -EINVAL; - } dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); mutex_unlock(&dbs_mutex); @@ -259,13 +260,12 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, int ret; ret = sscanf(buf, "%u", &input); - mutex_lock(&dbs_mutex); if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || input < MIN_FREQUENCY_UP_THRESHOLD) { - mutex_unlock(&dbs_mutex); return -EINVAL; } + mutex_lock(&dbs_mutex); dbs_tuners_ins.up_threshold = input; mutex_unlock(&dbs_mutex); @@ -363,9 +363,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) struct cpufreq_policy *policy; unsigned int j; - if (!this_dbs_info->enable) - return; - this_dbs_info->freq_lo = 0; policy = this_dbs_info->cur_policy; @@ -493,14 +490,7 @@ static void do_dbs_timer(struct work_struct *work) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - - if (lock_policy_rwsem_write(cpu) < 0) - return; - - if (!dbs_info->enable) { - unlock_policy_rwsem_write(cpu); - return; - } + mutex_lock(&dbs_info->timer_mutex); /* Common NORMAL_SAMPLE setup */ dbs_info->sample_type = DBS_NORMAL_SAMPLE; @@ -517,7 +507,7 @@ static void do_dbs_timer(struct work_struct *work) dbs_info->freq_lo, CPUFREQ_RELATION_H); } queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_info->timer_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -526,8 +516,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - dbs_info->enable = 1; - ondemand_powersave_bias_init(); dbs_info->sample_type = DBS_NORMAL_SAMPLE; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work, @@ -536,7 +524,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { - dbs_info->enable = 0; cancel_delayed_work_sync(&dbs_info->work); } @@ -555,19 +542,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; - if (this_dbs_info->enable) /* Already enabled */ - break; - mutex_lock(&dbs_mutex); - dbs_enable++; rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); if (rc) { - dbs_enable--; mutex_unlock(&dbs_mutex); return rc; } + dbs_enable++; for_each_cpu(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); @@ -581,6 +564,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, } } this_dbs_info->cpu = cpu; + ondemand_powersave_bias_init_cpu(cpu); + mutex_init(&this_dbs_info->timer_mutex); /* * Start the timerschedule work, when this governor * is used for first time @@ -598,29 +583,31 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, max(min_sampling_rate, latency * LATENCY_MULTIPLIER); } - dbs_timer_init(this_dbs_info); - mutex_unlock(&dbs_mutex); + + dbs_timer_init(this_dbs_info); break; case CPUFREQ_GOV_STOP: - mutex_lock(&dbs_mutex); dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); + mutex_destroy(&this_dbs_info->timer_mutex); dbs_enable--; mutex_unlock(&dbs_mutex); break; case CPUFREQ_GOV_LIMITS: - mutex_lock(&dbs_mutex); + mutex_lock(&this_dbs_info->timer_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); - mutex_unlock(&dbs_mutex); + mutex_unlock(&this_dbs_info->timer_mutex); break; } return 0; diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81b..f74edae5cb4 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) { int channel, bandwidth = 0; - fw_iso_resource_manage(card, generation, 1ULL << 31, - &channel, &bandwidth, true); + fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, + &bandwidth, true, card->bm_transaction_data); if (channel == 31) { card->broadcast_channel_allocated = true; device_for_each_child(card->device, (void *)(long)generation, @@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) bool do_reset = false; bool root_device_is_running; bool root_device_is_cmc; - __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); @@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) goto pick_me; } - lock_data[0] = cpu_to_be32(0x3f); - lock_data[1] = cpu_to_be32(local_id); + card->bm_transaction_data[0] = cpu_to_be32(0x3f); + card->bm_transaction_data[1] = cpu_to_be32(local_id); spin_unlock_irqrestore(&card->lock, flags); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - lock_data, sizeof(lock_data)); + card->bm_transaction_data, + sizeof(card->bm_transaction_data)); if (rcode == RCODE_GENERATION) /* Another bus reset, BM work has been rescheduled. */ goto out; if (rcode == RCODE_COMPLETE && - lock_data[0] != cpu_to_be32(0x3f)) { + card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { /* Somebody else is BM. Only act as IRM. */ if (local_id == irm_id) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0..ced186d7e9a 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -125,6 +125,7 @@ struct iso_resource { int generation; u64 channels; s32 bandwidth; + __be32 transaction_data[2]; struct iso_resource_event *e_alloc, *e_dealloc; }; @@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) r->channels, &channel, &bandwidth, todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC || - todo == ISO_RES_ALLOC_ONCE); + todo == ISO_RES_ALLOC_ONCE, + r->transaction_data); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38..110e731f557 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); */ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, - int bandwidth, bool allocate) + int bandwidth, bool allocate, __be32 data[2]) { - __be32 data[2]; int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; /* @@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, } static int manage_channel(struct fw_card *card, int irm_id, int generation, - u32 channels_mask, u64 offset, bool allocate) + u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) { - __be32 data[2], c, all, old; + __be32 c, all, old; int i, retry = 5; old = all = allocate ? cpu_to_be32(~0) : 0; @@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, } static void deallocate_channel(struct fw_card *card, int irm_id, - int generation, int channel) + int generation, int channel, __be32 buffer[2]) { u32 mask; u64 offset; @@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; - manage_channel(card, irm_id, generation, mask, offset, false); + manage_channel(card, irm_id, generation, mask, offset, false, buffer); } /** @@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, */ void fw_iso_resource_manage(struct fw_card *card, int generation, u64 channels_mask, int *channel, int *bandwidth, - bool allocate) + bool allocate, __be32 buffer[2]) { u32 channels_hi = channels_mask; /* channels 31...0 */ u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ @@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (channels_hi) c = manage_channel(card, irm_id, generation, channels_hi, - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, + allocate, buffer); if (channels_lo && c < 0) { c = manage_channel(card, irm_id, generation, channels_lo, - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, + allocate, buffer); if (c >= 0) c += 32; } @@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (*bandwidth == 0) return; - ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, + allocate, buffer); if (ret < 0) *bandwidth = 0; if (allocate && ret < 0 && c >= 0) { - deallocate_channel(card, irm_id, generation, c); + deallocate_channel(card, irm_id, generation, c, buffer); *channel = ret; } } diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e..6052816be35 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); void fw_iso_resource_manage(struct fw_card *card, int generation, - u64 channels_mask, int *channel, int *bandwidth, bool allocate); + u64 channels_mask, int *channel, int *bandwidth, + bool allocate, __be32 buffer[2]); /* -topology */ diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 24c45635376..8d51568ee14 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -201,6 +201,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ /* + * There is no transport protocol limit to the CDB length, but we implement + * a fixed length only. 16 bytes is enough for disks larger than 2 TB. + */ +#define SBP2_MAX_CDB_SIZE 16 + +/* * The default maximum s/g segment size of a FireWire controller is * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to * be quadlet-aligned, we set the length limit to 0xffff & ~3. @@ -312,7 +318,7 @@ struct sbp2_command_orb { struct sbp2_pointer next; struct sbp2_pointer data_descriptor; __be32 misc; - u8 command_block[12]; + u8 command_block[SBP2_MAX_CDB_SIZE]; } request; struct scsi_cmnd *cmd; scsi_done_fn_t done; @@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) if (fw_device_enable_phys_dma(device) < 0) goto fail_shost_put; + shost->max_cmd_len = SBP2_MAX_CDB_SIZE; + if (scsi_add_host(shost, &unit->device) < 0) goto fail_shost_put; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index e4476743f20..b1bc6e277d2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) { volatile struct iic_regs __iomem *iic = dev->vaddr; printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); - printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" - KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" - KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" - KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", + printk(KERN_DEBUG + " cntl = 0x%02x, mdcntl = 0x%02x\n" + " sts = 0x%02x, extsts = 0x%02x\n" + " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" + " xtcntlss = 0x%02x, directcntl = 0x%02x\n", in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), in_8(&iic->xtcntlss), in_8(&iic->directcntl)); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d5f3c77bead..db96138fefc 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -466,14 +466,10 @@ void do_ide_request(struct request_queue *q) if (!ide_lock_port(hwif)) { ide_hwif_t *prev_port; + + WARN_ON_ONCE(hwif->rq); repeat: prev_port = hwif->host->cur_port; - - if (drive->dev_flags & IDE_DFLAG_BLOCKED) - rq = hwif->rq; - else - WARN_ON_ONCE(hwif->rq); - if (drive->dev_flags & IDE_DFLAG_SLEEPING && time_after(drive->sleep, jiffies)) { ide_unlock_port(hwif); @@ -500,29 +496,43 @@ repeat: hwif->cur_dev = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - if (rq == NULL) { - spin_unlock_irq(&hwif->lock); - spin_lock_irq(q->queue_lock); - /* - * we know that the queue isn't empty, but this can - * happen if ->prep_rq_fn() decides to kill a request - */ + spin_unlock_irq(&hwif->lock); + spin_lock_irq(q->queue_lock); + /* + * we know that the queue isn't empty, but this can happen + * if the q->prep_rq_fn() decides to kill a request + */ + if (!rq) rq = blk_fetch_request(drive->queue); - spin_unlock_irq(q->queue_lock); - spin_lock_irq(&hwif->lock); - if (rq == NULL) { - ide_unlock_port(hwif); - goto out; - } + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwif->lock); + + if (!rq) { + ide_unlock_port(hwif); + goto out; } /* * Sanity: don't accept a request that isn't a PM request - * if we are currently power managed. + * if we are currently power managed. This is very important as + * blk_stop_queue() doesn't prevent the blk_fetch_request() + * above to return us whatever is in the queue. Since we call + * ide_do_request() ourselves, we end up taking requests while + * the queue is blocked... + * + * We let requests forced at head of queue with ide-preempt + * though. I hope that doesn't happen too much, hopefully not + * unless the subdriver triggers such a thing in its own PM + * state machine. */ - BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) && - blk_pm_request(rq) == 0); + if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && + blk_pm_request(rq) == 0 && + (rq->cmd_flags & REQ_PREEMPT) == 0) { + /* there should be no pending command at this point */ + ide_unlock_port(hwif); + goto plug_device; + } hwif->rq = rq; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 83b734aec92..52b25f8b111 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) } shost->hostdata[0] = (unsigned long)lu; + shost->max_cmd_len = SBP2_MAX_CDB_SIZE; if (!scsi_add_host(shost, &ud->device)) { lu->shost = shost; diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index c5036f1cc5b..64a3a66a8a3 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -25,6 +25,12 @@ #define SBP2_DEVICE_NAME "sbp2" /* + * There is no transport protocol limit to the CDB length, but we implement + * a fixed length only. 16 bytes is enough for disks larger than 2 TB. + */ +#define SBP2_MAX_CDB_SIZE 16 + +/* * SBP-2 specific definitions */ @@ -51,7 +57,7 @@ struct sbp2_command_orb { u32 data_descriptor_hi; u32 data_descriptor_lo; u32 misc; - u8 cdb[12]; + u8 cdb[SBP2_MAX_CDB_SIZE]; } __attribute__((packed)); #define SBP2_LOGIN_REQUEST 0x0 diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9d8f796c674..a6b989a9dc0 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD if INPUT_KEYBOARD +config KEYBOARD_AAED2000 + tristate "AAED-2000 keyboard" + depends on MACH_AAED2000 + select INPUT_POLLDEV + default y + help + Say Y here to enable the keyboard on the Agilent AAED-2000 + development board. + + To compile this driver as a module, choose M here: the + module will be called aaed2000_kbd. + +config KEYBOARD_AMIGA + tristate "Amiga keyboard" + depends on AMIGA + help + Say Y here if you are running Linux on any AMIGA and have a keyboard + attached. + + To compile this driver as a module, choose M here: the + module will be called amikbd. + +config ATARI_KBD_CORE + bool + +config KEYBOARD_ATARI + tristate "Atari keyboard" + depends on ATARI + select ATARI_KBD_CORE + help + Say Y here if you are running Linux on any Atari and have a keyboard + attached. + + To compile this driver as a module, choose M here: the + module will be called atakbd. + config KEYBOARD_ATKBD tristate "AT keyboard" if EMBEDDED || !X86 default y @@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES right-hand column will be interpreted as the key shown in the left-hand column. -config KEYBOARD_SUNKBD - tristate "Sun Type 4 and Type 5 keyboard" - select SERIO - help - Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, - connected either to the Sun keyboard connector or to an serial - (RS-232) port via a simple adapter. - - To compile this driver as a module, choose M here: the - module will be called sunkbd. - -config KEYBOARD_LKKBD - tristate "DECstation/VAXstation LK201/LK401 keyboard" - select SERIO - help - Say Y here if you want to use a LK201 or LK401 style serial - keyboard. This keyboard is also useable on PCs if you attach - it with the inputattach program. The connector pinout is - described within lkkbd.c. - - To compile this driver as a module, choose M here: the - module will be called lkkbd. - -config KEYBOARD_LOCOMO - tristate "LoCoMo Keyboard Support" - depends on SHARP_LOCOMO && INPUT_KEYBOARD - help - Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA - - To compile this driver as a module, choose M here: the - module will be called locomokbd. - -config KEYBOARD_XTKBD - tristate "XT keyboard" - select SERIO - help - Say Y here if you want to use the old IBM PC/XT keyboard (or - compatible) on your system. This is only possible with a - parallel port keyboard adapter, you cannot connect it to the - keyboard port on a PC that runs Linux. - - To compile this driver as a module, choose M here: the - module will be called xtkbd. - -config KEYBOARD_NEWTON - tristate "Newton keyboard" - select SERIO - help - Say Y here if you have a Newton keyboard on a serial port. - - To compile this driver as a module, choose M here: the - module will be called newtonkbd. - -config KEYBOARD_STOWAWAY - tristate "Stowaway keyboard" - select SERIO +config KEYBOARD_BFIN + tristate "Blackfin BF54x keypad support" + depends on (BF54x && !BF544) help - Say Y here if you have a Stowaway keyboard on a serial port. - Stowaway compatible keyboards like Dicota Input-PDA keyboard - are also supported by this driver. + Say Y here if you want to use the BF54x keypad. To compile this driver as a module, choose M here: the - module will be called stowaway. + module will be called bf54x-keys. config KEYBOARD_CORGI tristate "Corgi keyboard" @@ -143,61 +124,50 @@ config KEYBOARD_CORGI To compile this driver as a module, choose M here: the module will be called corgikbd. -config KEYBOARD_SPITZ - tristate "Spitz keyboard" - depends on PXA_SHARPSL - default y +config KEYBOARD_LKKBD + tristate "DECstation/VAXstation LK201/LK401 keyboard" + select SERIO help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. + Say Y here if you want to use a LK201 or LK401 style serial + keyboard. This keyboard is also useable on PCs if you attach + it with the inputattach program. The connector pinout is + described within lkkbd.c. To compile this driver as a module, choose M here: the - module will be called spitzkbd. + module will be called lkkbd. -config KEYBOARD_TOSA - tristate "Tosa keyboard" - depends on MACH_TOSA - default y +config KEYBOARD_EP93XX + tristate "EP93xx Matrix Keypad support" + depends on ARCH_EP93XX help - Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) + Say Y here to enable the matrix keypad on the Cirrus EP93XX. To compile this driver as a module, choose M here: the - module will be called tosakbd. + module will be called ep93xx_keypad. -config KEYBOARD_TOSA_USE_EXT_KEYCODES - bool "Tosa keyboard: use extended keycodes" - depends on KEYBOARD_TOSA - default n +config KEYBOARD_GPIO + tristate "GPIO Buttons" + depends on GENERIC_GPIO help - Say Y here to enable the tosa keyboard driver to generate extended - (>= 127) keycodes. Be aware, that they can't be correctly interpreted - by either console keyboard driver or by Kdrive keybd driver. - - Say Y only if you know, what you are doing! + This driver implements support for buttons connected + to GPIO pins of various CPUs (and some other chips). -config KEYBOARD_AMIGA - tristate "Amiga keyboard" - depends on AMIGA - help - Say Y here if you are running Linux on any AMIGA and have a keyboard - attached. + Say Y here if your device has buttons connected + directly to such GPIO pins. Your board-specific + setup logic must also provide a platform device, + with configuration data saying which GPIOs are used. To compile this driver as a module, choose M here: the - module will be called amikbd. + module will be called gpio_keys. -config ATARI_KBD_CORE - bool - -config KEYBOARD_ATARI - tristate "Atari keyboard" - depends on ATARI - select ATARI_KBD_CORE +config KEYBOARD_MATRIX + tristate "GPIO driven matrix keypad support" + depends on GENERIC_GPIO help - Say Y here if you are running Linux on any Atari and have a keyboard - attached. + Enable support for GPIO driven matrix keypad. To compile this driver as a module, choose M here: the - module will be called atakbd. + module will be called matrix_keypad. config KEYBOARD_HIL_OLD tristate "HP HIL keyboard support (simple driver)" @@ -261,20 +231,39 @@ config KEYBOARD_LM8323 To compile this driver as a module, choose M here: the module will be called lm8323. -config KEYBOARD_OMAP - tristate "TI OMAP keypad support" - depends on (ARCH_OMAP1 || ARCH_OMAP2) +config KEYBOARD_LOCOMO + tristate "LoCoMo Keyboard Support" + depends on SHARP_LOCOMO help - Say Y here if you want to use the OMAP keypad. + Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA To compile this driver as a module, choose M here: the - module will be called omap-keypad. + module will be called locomokbd. + +config KEYBOARD_MAPLE + tristate "Maple bus keyboard" + depends on SH_DREAMCAST && MAPLE + help + Say Y here if you have a Dreamcast console running Linux and have + a keyboard attached to its Maple bus. + + To compile this driver as a module, choose M here: the + module will be called maple_keyb. + +config KEYBOARD_NEWTON + tristate "Newton keyboard" + select SERIO + help + Say Y here if you have a Newton keyboard on a serial port. + + To compile this driver as a module, choose M here: the + module will be called newtonkbd. config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" depends on PXA27x || PXA3xx help - Enable support for PXA27x/PXA3xx keypad controller + Enable support for PXA27x/PXA3xx keypad controller. To compile this driver as a module, choose M here: the module will be called pxa27x_keypad. @@ -288,51 +277,38 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_AAED2000 - tristate "AAED-2000 keyboard" - depends on MACH_AAED2000 - select INPUT_POLLDEV +config KEYBOARD_SPITZ + tristate "Spitz keyboard" + depends on PXA_SHARPSL default y help - Say Y here to enable the keyboard on the Agilent AAED-2000 - development board. - - To compile this driver as a module, choose M here: the - module will be called aaed2000_kbd. - -config KEYBOARD_GPIO - tristate "GPIO Buttons" - depends on GENERIC_GPIO - help - This driver implements support for buttons connected - to GPIO pins of various CPUs (and some other chips). - - Say Y here if your device has buttons connected - directly to such GPIO pins. Your board-specific - setup logic must also provide a platform device, - with configuration data saying which GPIOs are used. + Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, + SL-C3000 and Sl-C3100 series of PDAs. To compile this driver as a module, choose M here: the - module will be called gpio-keys. + module will be called spitzkbd. -config KEYBOARD_MAPLE - tristate "Maple bus keyboard" - depends on SH_DREAMCAST && MAPLE +config KEYBOARD_STOWAWAY + tristate "Stowaway keyboard" + select SERIO help - Say Y here if you have a Dreamcast console running Linux and have - a keyboard attached to its Maple bus. + Say Y here if you have a Stowaway keyboard on a serial port. + Stowaway compatible keyboards like Dicota Input-PDA keyboard + are also supported by this driver. To compile this driver as a module, choose M here: the - module will be called maple_keyb. + module will be called stowaway. -config KEYBOARD_BFIN - tristate "Blackfin BF54x keypad support" - depends on (BF54x && !BF544) +config KEYBOARD_SUNKBD + tristate "Sun Type 4 and Type 5 keyboard" + select SERIO help - Say Y here if you want to use the BF54x keypad. + Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, + connected either to the Sun keyboard connector or to an serial + (RS-232) port via a simple adapter. To compile this driver as a module, choose M here: the - module will be called bf54x-keys. + module will be called sunkbd. config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" @@ -344,13 +320,45 @@ config KEYBOARD_SH_KEYSC To compile this driver as a module, choose M here: the module will be called sh_keysc. -config KEYBOARD_EP93XX - tristate "EP93xx Matrix Keypad support" - depends on ARCH_EP93XX +config KEYBOARD_OMAP + tristate "TI OMAP keypad support" + depends on (ARCH_OMAP1 || ARCH_OMAP2) help - Say Y here to enable the matrix keypad on the Cirrus EP93XX. + Say Y here if you want to use the OMAP keypad. To compile this driver as a module, choose M here: the - module will be called ep93xx_keypad. + module will be called omap-keypad. + +config KEYBOARD_TOSA + tristate "Tosa keyboard" + depends on MACH_TOSA + default y + help + Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) + + To compile this driver as a module, choose M here: the + module will be called tosakbd. + +config KEYBOARD_TOSA_USE_EXT_KEYCODES + bool "Tosa keyboard: use extended keycodes" + depends on KEYBOARD_TOSA + help + Say Y here to enable the tosa keyboard driver to generate extended + (>= 127) keycodes. Be aware, that they can't be correctly interpreted + by either console keyboard driver or by Kdrive keybd driver. + + Say Y only if you know, what you are doing! + +config KEYBOARD_XTKBD + tristate "XT keyboard" + select SERIO + help + Say Y here if you want to use the old IBM PC/XT keyboard (or + compatible) on your system. This is only possible with a + parallel port keyboard adapter, you cannot connect it to the + keyboard port on a PC that runs Linux. + + To compile this driver as a module, choose M here: the + module will be called xtkbd. endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 156b647a259..b5b5eae9724 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -4,29 +4,30 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o -obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o -obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o -obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o +obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o -obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o -obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o -obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o +obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o -obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o -obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o +obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o +obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o +obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o +obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o +obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o +obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o +obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o +obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o -obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o -obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o -obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o -obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o -obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o -obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o +obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o +obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2157cd7de00..efed0c9e242 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -29,7 +29,8 @@ struct gpio_button_data { struct gpio_keys_button *button; struct input_dev *input; - struct delayed_work work; + struct timer_list timer; + struct work_struct work; }; struct gpio_keys_drvdata { @@ -40,7 +41,7 @@ struct gpio_keys_drvdata { static void gpio_keys_report_event(struct work_struct *work) { struct gpio_button_data *bdata = - container_of(work, struct gpio_button_data, work.work); + container_of(work, struct gpio_button_data, work); struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; @@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work) input_sync(input); } +static void gpio_keys_timer(unsigned long _data) +{ + struct gpio_button_data *data = (struct gpio_button_data *)_data; + + schedule_work(&data->work); +} + static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; - unsigned long delay; BUG_ON(irq != gpio_to_irq(button->gpio)); - delay = button->debounce_interval ? - msecs_to_jiffies(button->debounce_interval) : 0; - schedule_delayed_work(&bdata->work, delay); + if (button->debounce_interval) + mod_timer(&bdata->timer, + jiffies + msecs_to_jiffies(button->debounce_interval)); + else + schedule_work(&bdata->work); return IRQ_HANDLED; } @@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) bdata->input = input; bdata->button = button; - INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); + setup_timer(&bdata->timer, + gpio_keys_timer, (unsigned long)bdata); + INIT_WORK(&bdata->work, gpio_keys_report_event); error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); if (error < 0) { @@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); - cancel_delayed_work_sync(&ddata->data[i].work); + if (pdata->buttons[i].debounce_interval) + del_timer_sync(&ddata->data[i].timer); + cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } @@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); free_irq(irq, &ddata->data[i]); - cancel_delayed_work_sync(&ddata->data[i].work); + if (pdata->buttons[i].debounce_interval) + del_timer_sync(&ddata->data[i].timer); + cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c new file mode 100644 index 00000000000..e9b2e7cb05b --- /dev/null +++ b/drivers/input/keyboard/matrix_keypad.c @@ -0,0 +1,453 @@ +/* + * GPIO driven matrix keyboard driver + * + * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com> + * + * Based on corgikbd.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/input/matrix_keypad.h> + +struct matrix_keypad { + const struct matrix_keypad_platform_data *pdata; + struct input_dev *input_dev; + unsigned short *keycodes; + + uint32_t last_key_state[MATRIX_MAX_COLS]; + struct delayed_work work; + bool scan_pending; + bool stopped; + spinlock_t lock; +}; + +/* + * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause + * minmal side effect when scanning other columns, here it is configured to + * be input, and it should work on most platforms. + */ +static void __activate_col(const struct matrix_keypad_platform_data *pdata, + int col, bool on) +{ + bool level_on = !pdata->active_low; + + if (on) { + gpio_direction_output(pdata->col_gpios[col], level_on); + } else { + gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); + gpio_direction_input(pdata->col_gpios[col]); + } +} + +static void activate_col(const struct matrix_keypad_platform_data *pdata, + int col, bool on) +{ + __activate_col(pdata, col, on); + + if (on && pdata->col_scan_delay_us) + udelay(pdata->col_scan_delay_us); +} + +static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, + bool on) +{ + int col; + + for (col = 0; col < pdata->num_col_gpios; col++) + __activate_col(pdata, col, on); +} + +static bool row_asserted(const struct matrix_keypad_platform_data *pdata, + int row) +{ + return gpio_get_value_cansleep(pdata->row_gpios[row]) ? + !pdata->active_low : pdata->active_low; +} + +static void enable_row_irqs(struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + for (i = 0; i < pdata->num_row_gpios; i++) + enable_irq(gpio_to_irq(pdata->row_gpios[i])); +} + +static void disable_row_irqs(struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + for (i = 0; i < pdata->num_row_gpios; i++) + disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); +} + +/* + * This gets the keys from keyboard and reports it to input subsystem + */ +static void matrix_keypad_scan(struct work_struct *work) +{ + struct matrix_keypad *keypad = + container_of(work, struct matrix_keypad, work.work); + struct input_dev *input_dev = keypad->input_dev; + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + uint32_t new_state[MATRIX_MAX_COLS]; + int row, col, code; + + /* de-activate all columns for scanning */ + activate_all_cols(pdata, false); + + memset(new_state, 0, sizeof(new_state)); + + /* assert each column and read the row status out */ + for (col = 0; col < pdata->num_col_gpios; col++) { + + activate_col(pdata, col, true); + + for (row = 0; row < pdata->num_row_gpios; row++) + new_state[col] |= + row_asserted(pdata, row) ? (1 << row) : 0; + + activate_col(pdata, col, false); + } + + for (col = 0; col < pdata->num_col_gpios; col++) { + uint32_t bits_changed; + + bits_changed = keypad->last_key_state[col] ^ new_state[col]; + if (bits_changed == 0) + continue; + + for (row = 0; row < pdata->num_row_gpios; row++) { + if ((bits_changed & (1 << row)) == 0) + continue; + + code = (row << 4) + col; + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, + keypad->keycodes[code], + new_state[col] & (1 << row)); + } + } + input_sync(input_dev); + + memcpy(keypad->last_key_state, new_state, sizeof(new_state)); + + activate_all_cols(pdata, true); + + /* Enable IRQs again */ + spin_lock_irq(&keypad->lock); + keypad->scan_pending = false; + enable_row_irqs(keypad); + spin_unlock_irq(&keypad->lock); +} + +static irqreturn_t matrix_keypad_interrupt(int irq, void *id) +{ + struct matrix_keypad *keypad = id; + unsigned long flags; + + spin_lock_irqsave(&keypad->lock, flags); + + /* + * See if another IRQ beaten us to it and scheduled the + * scan already. In that case we should not try to + * disable IRQs again. + */ + if (unlikely(keypad->scan_pending || keypad->stopped)) + goto out; + + disable_row_irqs(keypad); + keypad->scan_pending = true; + schedule_delayed_work(&keypad->work, + msecs_to_jiffies(keypad->pdata->debounce_ms)); + +out: + spin_unlock_irqrestore(&keypad->lock, flags); + return IRQ_HANDLED; +} + +static int matrix_keypad_start(struct input_dev *dev) +{ + struct matrix_keypad *keypad = input_get_drvdata(dev); + + keypad->stopped = false; + mb(); + + /* + * Schedule an immediate key scan to capture current key state; + * columns will be activated and IRQs be enabled after the scan. + */ + schedule_delayed_work(&keypad->work, 0); + + return 0; +} + +static void matrix_keypad_stop(struct input_dev *dev) +{ + struct matrix_keypad *keypad = input_get_drvdata(dev); + + keypad->stopped = true; + mb(); + flush_work(&keypad->work.work); + /* + * matrix_keypad_scan() will leave IRQs enabled; + * we should disable them now. + */ + disable_row_irqs(keypad); +} + +#ifdef CONFIG_PM +static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + matrix_keypad_stop(keypad->input_dev); + + if (device_may_wakeup(&pdev->dev)) + for (i = 0; i < pdata->num_row_gpios; i++) + enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + + return 0; +} + +static int matrix_keypad_resume(struct platform_device *pdev) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + if (device_may_wakeup(&pdev->dev)) + for (i = 0; i < pdata->num_row_gpios; i++) + disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + + matrix_keypad_start(keypad->input_dev); + + return 0; +} +#else +#define matrix_keypad_suspend NULL +#define matrix_keypad_resume NULL +#endif + +static int __devinit init_matrix_gpio(struct platform_device *pdev, + struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i, err = -EINVAL; + + /* initialized strobe lines as outputs, activated */ + for (i = 0; i < pdata->num_col_gpios; i++) { + err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for COL%d\n", + pdata->col_gpios[i], i); + goto err_free_cols; + } + + gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); + } + + for (i = 0; i < pdata->num_row_gpios; i++) { + err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for ROW%d\n", + pdata->row_gpios[i], i); + goto err_free_rows; + } + + gpio_direction_input(pdata->row_gpios[i]); + } + + for (i = 0; i < pdata->num_row_gpios; i++) { + err = request_irq(gpio_to_irq(pdata->row_gpios[i]), + matrix_keypad_interrupt, + IRQF_DISABLED | + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "matrix-keypad", keypad); + if (err) { + dev_err(&pdev->dev, + "Unable to acquire interrupt for GPIO line %i\n", + pdata->row_gpios[i]); + goto err_free_irqs; + } + } + + /* initialized as disabled - enabled by input->open */ + disable_row_irqs(keypad); + return 0; + +err_free_irqs: + while (--i >= 0) + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); + i = pdata->num_row_gpios; +err_free_rows: + while (--i >= 0) + gpio_free(pdata->row_gpios[i]); + i = pdata->num_col_gpios; +err_free_cols: + while (--i >= 0) + gpio_free(pdata->col_gpios[i]); + + return err; +} + +static int __devinit matrix_keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keypad_platform_data *pdata; + const struct matrix_keymap_data *keymap_data; + struct matrix_keypad *keypad; + struct input_dev *input_dev; + unsigned short *keycodes; + int i; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + keymap_data = pdata->keymap_data; + if (!keymap_data) { + dev_err(&pdev->dev, "no keymap data defined\n"); + return -EINVAL; + } + + if (!keymap_data->max_keymap_size) { + dev_err(&pdev->dev, "invalid keymap data supplied\n"); + return -EINVAL; + } + + keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); + keycodes = kzalloc(keymap_data->max_keymap_size * + sizeof(keypad->keycodes), + GFP_KERNEL); + input_dev = input_allocate_device(); + if (!keypad || !keycodes || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } + + keypad->input_dev = input_dev; + keypad->pdata = pdata; + keypad->keycodes = keycodes; + keypad->stopped = true; + INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); + spin_lock_init(&keypad->lock); + + input_dev->name = pdev->name; + input_dev->id.bustype = BUS_HOST; + input_dev->dev.parent = &pdev->dev; + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_dev->open = matrix_keypad_start; + input_dev->close = matrix_keypad_stop; + + input_dev->keycode = keycodes; + input_dev->keycodesize = sizeof(*keycodes); + input_dev->keycodemax = keymap_data->max_keymap_size; + + for (i = 0; i < keymap_data->keymap_size; i++) { + unsigned int key = keymap_data->keymap[i]; + unsigned int row = KEY_ROW(key); + unsigned int col = KEY_COL(key); + unsigned short code = KEY_VAL(key); + + keycodes[(row << 4) + col] = code; + __set_bit(code, input_dev->keybit); + } + __clear_bit(KEY_RESERVED, input_dev->keybit); + + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, keypad); + + err = init_matrix_gpio(pdev, keypad); + if (err) + goto err_free_mem; + + err = input_register_device(keypad->input_dev); + if (err) + goto err_free_mem; + + device_init_wakeup(&pdev->dev, pdata->wakeup); + platform_set_drvdata(pdev, keypad); + + return 0; + +err_free_mem: + input_free_device(input_dev); + kfree(keycodes); + kfree(keypad); + return err; +} + +static int __devexit matrix_keypad_remove(struct platform_device *pdev) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + device_init_wakeup(&pdev->dev, 0); + + for (i = 0; i < pdata->num_row_gpios; i++) { + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); + gpio_free(pdata->row_gpios[i]); + } + + for (i = 0; i < pdata->num_col_gpios; i++) + gpio_free(pdata->col_gpios[i]); + + input_unregister_device(keypad->input_dev); + platform_set_drvdata(pdev, NULL); + kfree(keypad->keycodes); + kfree(keypad); + + return 0; +} + +static struct platform_driver matrix_keypad_driver = { + .probe = matrix_keypad_probe, + .remove = __devexit_p(matrix_keypad_remove), + .suspend = matrix_keypad_suspend, + .resume = matrix_keypad_resume, + .driver = { + .name = "matrix-keypad", + .owner = THIS_MODULE, + }, +}; + +static int __init matrix_keypad_init(void) +{ + return platform_driver_register(&matrix_keypad_driver); +} + +static void __exit matrix_keypad_exit(void) +{ + platform_driver_unregister(&matrix_keypad_driver); +} + +module_init(matrix_keypad_init); +module_exit(matrix_keypad_exit); + +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); +MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:matrix-keypad"); diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 5e5eb88d8d1..7b6ce178f1b 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) input_sync(input); } -static int __init gpio_mouse_probe(struct platform_device *pdev) +static int __devinit gpio_mouse_probe(struct platform_device *pdev) { struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; struct input_polled_dev *input_poll; @@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) return 0; } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:gpio_mouse"); - static struct platform_driver gpio_mouse_device_driver = { + .probe = gpio_mouse_probe, .remove = __devexit_p(gpio_mouse_remove), .driver = { .name = "gpio_mouse", @@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = { static int __init gpio_mouse_init(void) { - return platform_driver_probe(&gpio_mouse_device_driver, - gpio_mouse_probe); + return platform_driver_register(&gpio_mouse_device_driver); } module_init(gpio_mouse_init); @@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit); MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ + diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index fb8a3cd3ffd..924e8ed7f2c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -392,6 +392,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), }, }, + { + .ident = "Acer Aspire One 150", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), + }, + }, + { + .ident = "Advent 4211", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), + DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), + }, + }, + { + .ident = "Medion Akoya Mini E1210", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), + }, + }, + { + .ident = "Mivvy M310", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), + DMI_MATCH(DMI_PRODUCT_NAME, "N10"), + }, + }, { } }; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f919bf57293..582245c497e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -934,10 +934,11 @@ static bool i8042_suspended; static int i8042_suspend(struct platform_device *dev, pm_message_t state) { - if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { + if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) i8042_controller_reset(); - i8042_suspended = true; - } + + i8042_suspended = state.event == PM_EVENT_SUSPEND || + state.event == PM_EVENT_FREEZE; return 0; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index fb17573f8f2..d66f4944f2a 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state) { struct serio *serio = to_serio_port(dev); - if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { + if (!serio->suspended && state.event == PM_EVENT_SUSPEND) serio_cleanup(serio); - serio->suspended = true; - } + + serio->suspended = state.event == PM_EVENT_SUSPEND || + state.event == PM_EVENT_FREEZE; return 0; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 38bf86384ae..c896d6a21b7 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_TOUCH, 0); wacom_report_abs(wcombo, ABS_WHEEL, 0); + if (wacom->features->type >= INTUOS3S) + wacom_report_abs(wcombo, ABS_Z, 0); } wacom_report_key(wcombo, wacom->tool[idx], 0); wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ @@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = { { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, + { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, @@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index ec5169604a6..2d91049571a 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -294,32 +294,33 @@ struct reply_t gigaset_tab_cid[] = {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ + {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, {RSP_OK, 607,607, -1, 608,-1}, - //{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, - {RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}}, - {RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}}, {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, - /* dialing */ - {RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */ - - /* connection established */ - {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 - {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 - - {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout + /* optional dialing responses */ + {EV_BC_OPEN, 650,650, -1, 651,-1}, + {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, + {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, + + /* connect */ + {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, + {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP}}, + {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, + {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP}}, + {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, /* remote hangup */ - {RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, - {RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, + {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, + {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, /* hangup */ @@ -358,7 +359,8 @@ struct reply_t gigaset_tab_cid[] = {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, - {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, + {EV_BC_OPEN, 750,750, -1, 751,-1}, + {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, /* B channel closed (general case) */ {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME @@ -876,12 +878,6 @@ static void bchannel_down(struct bc_state *bcs) static void bchannel_up(struct bc_state *bcs) { - if (!(bcs->chstate & CHS_D_UP)) { - dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__); - bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); - } - if (bcs->chstate & CHS_B_UP) { dev_notice(bcs->cs->dev, "%s: B channel already up\n", __func__); diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index db3a1e4cd48..bed38fcc432 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -174,12 +174,6 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) pr_err("invalid size %d\n", size); return -EINVAL; } - src = iwb->read; - if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD || - (read < src && limit >= src))) { - pr_err("isoc write buffer frame reservation violated\n"); - return -EFAULT; - } #endif if (read < write) { diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 9933eb861c7..529e2ba505c 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -776,7 +776,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) * But don't wait if split was due to the io size restriction */ if (unlikely(out_of_pages)) - congestion_wait(WRITE, HZ/100); + congestion_wait(BLK_RW_ASYNC, HZ/100); /* * With async crypto it is unsafe to share the crypto context diff --git a/drivers/md/md.c b/drivers/md/md.c index 0f4a70c43ff..d4351ff0849 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1756,9 +1756,10 @@ static void print_sb_1(struct mdp_superblock_1 *sb) __u8 *uuid; uuid = sb->set_uuid; - printk(KERN_INFO "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" - ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" - KERN_INFO "md: Name: \"%s\" CT:%llu\n", + printk(KERN_INFO + "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" + ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" + "md: Name: \"%s\" CT:%llu\n", le32_to_cpu(sb->major_version), le32_to_cpu(sb->feature_map), uuid[0], uuid[1], uuid[2], uuid[3], @@ -1770,12 +1771,13 @@ static void print_sb_1(struct mdp_superblock_1 *sb) & MD_SUPERBLOCK_1_TIME_SEC_MASK); uuid = sb->device_uuid; - printk(KERN_INFO "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" + printk(KERN_INFO + "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" " RO:%llu\n" - KERN_INFO "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" - ":%02x%02x%02x%02x%02x%02x\n" - KERN_INFO "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" - KERN_INFO "md: (MaxDev:%u) \n", + "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" + ":%02x%02x%02x%02x%02x%02x\n" + "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" + "md: (MaxDev:%u) \n", le32_to_cpu(sb->level), (unsigned long long)le64_to_cpu(sb->size), le32_to_cpu(sb->raid_disks), diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index b6da9c3873f..aa20ce8cc66 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -1096,8 +1096,19 @@ static int xc2028_set_params(struct dvb_frontend *fe, } /* All S-code tables need a 200kHz shift */ - if (priv->ctrl.demod) + if (priv->ctrl.demod) { demod = priv->ctrl.demod + 200; + /* + * The DTV7 S-code table needs a 700 kHz shift. + * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this + * + * DTV7 is only used in Australia. Germany or Italy may also + * use this firmware after initialization, but a tune to a UHF + * channel should then cause DTV78 to be used. + */ + if (type & DTV7) + demod += 500; + } return generic_set_freq(fe, p->frequency, T_DIGITAL_TV, type, 0, demod); diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 68eb4493f99..d8d4214fd65 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,5 +1,6 @@ config TTPCI_EEPROM tristate + depends on I2C default n config DVB_AV7110 diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 640421ceb24..46d21632961 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1200,7 +1200,7 @@ static int si470x_fops_release(struct file *file) video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); - goto done; + goto unlock; } /* stop rds reception */ @@ -1213,9 +1213,8 @@ static int si470x_fops_release(struct file *file) retval = si470x_stop(radio); usb_autopm_put_interface(radio->intf); } - +unlock: mutex_unlock(&radio->disconnect_lock); - done: return retval; } diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 061e147f6f2..84b6fc15519 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -312,6 +312,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_MT9V011 + tristate "Micron mt9v011 sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This is a Video4Linux2 sensor-level driver for the Micron + mt0v011 1.3 Mpixel camera. It currently only works with the + em28xx driver. + config VIDEO_TCM825X tristate "TCM825x camera sensor support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7fb3add1b38..9f2e3214a48 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index c92a25036f0..36f2d76006f 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { static const struct cx18_card cx18_card_mpc718 = { .type = CX18_CARD_YUAN_MPC718, - .name = "Yuan MPC718", - .comment = "Analog video capture works; some audio line in may not.\n", + .name = "Yuan MPC718 MiniPCI DVB-T/Analog", + .comment = "Experimenters needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = { { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, - { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, - { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, - { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, }, - .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 }, .tuners = { /* XC3028 tuner */ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, + /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, .ddr = { - /* Probably Samsung K4D263238G-VC33 memory */ - .chip_config = 0x003, - .refresh = 0x30c, - .timing1 = 0x23230b73, - .timing2 = 0x08, + /* Hynix HY5DU283222B DDR RAM */ + .chip_config = 0x303, + .refresh = 0x3bd, + .timing1 = 0x36320966, + .timing2 = 0x1f, .tune_lane = 0, .initial_emrs = 2, }, + .gpio_init.initial_value = 0x1, + .gpio_init.direction = 0x3, + /* FIXME - these GPIO's are just guesses */ + .gpio_audio_input = { .mask = 0x3, + .tuner = 0x1, + .linein = 0x3, + .radio = 0x1 }, .xceive_pin = 0, .pci_list = cx18_pci_mpc718, .i2c = &cx18_i2c_std, diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623ef..51a0c33b25b 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -30,6 +30,10 @@ #include "s5h1409.h" #include "mxl5005s.h" #include "zl10353.h" + +#include <linux/firmware.h> +#include "mt352.h" +#include "mt352_priv.h" #include "tuner-xc2028.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define CX18_CLOCK_ENABLE2 0xc71024 #define CX18_DMUX_CLK_MASK 0x0080 +/* + * CX18_CARD_HVR_1600_ESMT + * CX18_CARD_HVR_1600_SAMSUNG + */ + static struct mxl5005s_config hauppauge_hvr1600_tuner = { .i2c_address = 0xC6 >> 1, .if_freq = IF_FREQ_5380000HZ, @@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +/* + * CX18_CARD_LEADTEK_DVR3100H + */ /* Information/confirmation of proper config values provided by Terry Wu */ static struct zl10353_config leadtek_dvr3100h_demod = { .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ @@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; +/* + * CX18_CARD_YUAN_MPC718 + */ +/* + * Due to + * + * 1. an absence of information on how to prgram the MT352 + * 2. the Linux mt352 module pushing MT352 initialzation off onto us here + * + * We have to use an init sequence that *you* must extract from the Windows + * driver (yuanrap.sys) and which we load as a firmware. + * + * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual + * with chip programming details, then I can remove this annoyance. + */ +static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, + const struct firmware **fw) +{ + struct cx18 *cx = stream->cx; + const char *fn = "dvb-cx18-mpc718-mt352.fw"; + int ret; + + ret = request_firmware(fw, fn, &cx->pci_dev->dev); + if (ret) + CX18_ERR("Unable to open firmware file %s\n", fn); + else { + size_t sz = (*fw)->size; + if (sz < 2 || sz > 64 || (sz % 2) != 0) { + CX18_ERR("Firmware %s has a bad size: %lu bytes\n", + fn, (unsigned long) sz); + ret = -EILSEQ; + release_firmware(*fw); + *fw = NULL; + } + } + + if (ret) { + CX18_ERR("The MPC718 board variant with the MT352 DVB-T" + "demodualtor will not work without it\n"); + CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " + "mpc718' if you need the firmware\n"); + } + return ret; +} + +static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) +{ + struct cx18_dvb *dvb = container_of(fe->dvb, + struct cx18_dvb, dvb_adapter); + struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); + const struct firmware *fw = NULL; + int ret; + int i; + u8 buf[3]; + + ret = yuan_mpc718_mt352_reqfw(stream, &fw); + if (ret) + return ret; + + /* Loop through all the register-value pairs in the firmware file */ + for (i = 0; i < fw->size; i += 2) { + buf[0] = fw->data[i]; + /* Intercept a few registers we want to set ourselves */ + switch (buf[0]) { + case TRL_NOMINAL_RATE_0: + /* Set our custom OFDM bandwidth in the case below */ + break; + case TRL_NOMINAL_RATE_1: + /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ + /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ + /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ + buf[1] = 0x72; + buf[2] = 0x49; + mt352_write(fe, buf, 3); + break; + case INPUT_FREQ_0: + /* Set our custom IF in the case below */ + break; + case INPUT_FREQ_1: + /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ + buf[1] = 0x31; + buf[2] = 0xc0; + mt352_write(fe, buf, 3); + break; + default: + /* Pass through the register-value pair from the fw */ + buf[1] = fw->data[i+1]; + mt352_write(fe, buf, 2); + break; + } + } + + buf[0] = (u8) TUNER_GO; + buf[1] = 0x01; /* Go */ + mt352_write(fe, buf, 2); + release_firmware(fw); + return 0; +} + +static struct mt352_config yuan_mpc718_mt352_demod = { + .demod_address = 0x1e >> 1, + .adc_clock = 20480, /* 20.480 MHz */ + .if2 = 4560, /* 4.560 MHz */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .demod_init = yuan_mpc718_mt352_init, +}; + +static struct zl10353_config yuan_mpc718_zl10353_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ +}; + static int dvb_register(struct cx18_stream *stream); /* Kernel DVB framework calls this when the feed needs to start. @@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) break; case CX18_CARD_LEADTEK_DVR3100H: + case CX18_CARD_YUAN_MPC718: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; + case CX18_CARD_YUAN_MPC718: + /* + * TODO + * Apparently, these cards also could instead have a + * DiBcom demod supported by one of the db7000 drivers + */ + dvb->fe = dvb_attach(mt352_attach, + &yuan_mpc718_mt352_demod, + &cx->i2c_adap[1]); + if (dvb->fe == NULL) + dvb->fe = dvb_attach(zl10353_attach, + &yuan_mpc718_zl10353_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 48a975134ac..86ac529e62b 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -463,6 +463,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = { .if_khz = 5380, }; +static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1275: + switch (param->u.vsb.modulation) { + case VSB_8: + cx23885_gpio_clear(dev, GPIO_5); + break; + case QAM_64: + case QAM_256: + default: + cx23885_gpio_set(dev, GPIO_5); + break; + } + break; + } + return (port->set_frontend_save) ? + port->set_frontend_save(fe, param) : -ENODEV; +} + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -502,6 +526,12 @@ static int dvb_register(struct cx23885_tsport *port) 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } + + /* FIXME: temporary hack */ + /* define bridge override to set_frontend */ + port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; + fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; + break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 1a2ac518a3f..214a55e943b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -288,6 +288,10 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; + + /* FIXME: temporary hack */ + int (*set_frontend_save) (struct dvb_frontend *, + struct dvb_frontend_parameters *); }; struct cx23885_dev { diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 16a5af30e9d..6524b493e03 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -8,6 +8,8 @@ config VIDEO_EM28XX select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO + ---help--- This is a video4linux driver for Empia 28xx based TV cards. diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c43fdb9bc88..ebd24a25fb8 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -58,6 +58,8 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); +#define MT9V011_VERSION 0x8243 + /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; @@ -191,6 +193,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, { -1, -1, -1, -1}, }; + +static struct em28xx_reg_seq silvercrest_reg_seq[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, + { -1, -1, -1, -1}, +}; + /* * Board definitions */ @@ -438,6 +447,18 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2820_BOARD_SILVERCREST_WEBCAM] = { + .name = "Silvercrest Webcam 1.3mpix", + .tuner_type = TUNER_ABSENT, + .is_27xx = 1, + .decoder = EM28XX_MT9V011, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = silvercrest_reg_seq, + } }, + }, [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -826,7 +847,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, - .dvb_gpio = default_analog, + .dvb_gpio = default_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1639,6 +1660,11 @@ static unsigned short tvp5150_addrs[] = { I2C_CLIENT_END }; +static unsigned short mt9v011_addrs[] = { + 0xba >> 1, + I2C_CLIENT_END +}; + static unsigned short msp3400_addrs[] = { 0x80 >> 1, 0x88 >> 1, @@ -1678,6 +1704,46 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } +/* HINT method: webcam I2C chips + * + * This method work for webcams with Micron sensors + */ +static int em28xx_hint_sensor(struct em28xx *dev) +{ + int rc; + char *sensor_name; + unsigned char cmd; + __be16 version_be; + u16 version; + + if (dev->model != EM2820_BOARD_UNKNOWN) + return 0; + + dev->i2c_client.addr = 0xba >> 1; + cmd = 0; + i2c_master_send(&dev->i2c_client, &cmd, 1); + rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); + if (rc != 2) + return -EINVAL; + + version = be16_to_cpu(version_be); + + switch (version) { + case MT9V011_VERSION: + dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; + sensor_name = "mt9v011"; + break; + default: + printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); + return -EINVAL; + } + + em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", + sensor_name, em28xx_boards[dev->model].name); + + return 0; +} + /* Since em28xx_pre_card_setup() requires a proper dev->model, * this won't work for boards with generic PCI IDs */ @@ -1706,7 +1772,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820\n"); + if (dev->board.is_27xx) + em28xx_info("chip is em2710\n"); + else + em28xx_info("chip ID is em2820\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); @@ -2158,6 +2227,10 @@ void em28xx_card_setup(struct em28xx *dev) before probing the i2c bus. */ em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; + case EM2820_BOARD_SILVERCREST_WEBCAM: + /* FIXME: need to document the registers bellow */ + em28xx_write_reg(dev, 0x0d, 0x42); + em28xx_write_reg(dev, 0x13, 0x08); } if (dev->board.has_snapshot_button) @@ -2189,6 +2262,10 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvp5150", "tvp5150", tvp5150_addrs); + if (dev->board.decoder == EM28XX_MT9V011) + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9v011", "mt9v011", mt9v011_addrs); + if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvaudio", "tvaudio", dev->board.tvaudio_addr); @@ -2333,6 +2410,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } + em28xx_hint_sensor(dev); + /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); @@ -2573,6 +2652,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { em28xx_devused &= ~(1<<dev->devno); + mutex_unlock(&dev->lock); kfree(dev); goto err; } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c8d7ce8fbd3..079ab4d563a 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -648,17 +648,28 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_set_outfmt(struct em28xx *dev) { int ret; + int vinmode, vinctl, outfmt; + + outfmt = dev->format->reg; + + if (dev->board.is_27xx) { + vinmode = 0x0d; + vinctl = 0x00; + } else { + vinmode = 0x10; + vinctl = 0x11; + } ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - dev->format->reg | 0x20, 0x3f); + outfmt | 0x20, 0xff); if (ret < 0) - return ret; + return ret; - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); if (ret < 0) return ret; - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -695,13 +706,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->board.is_em2800) + + if (dev->board.is_27xx) { + /* FIXME: Don't use the scaler yet */ + mode = 0; + } else if (dev->board.is_em2800) { mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); - else { + } else { u8 buf[2]; + buf[0] = h; buf[1] = h >> 8; em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); + buf[0] = v; buf[1] = v >> 8; em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); @@ -720,8 +737,11 @@ int em28xx_resolution_set(struct em28xx *dev) height = norm_maxh(dev) >> 1; em28xx_set_outfmt(dev); + + em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index e7b47c8da8f..3da97c32b8f 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -243,6 +243,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, + .parallel_ts = 1, + .if2 = 45600, +}; + #ifdef EM28XX_DRX397XD_SUPPORT /* [TODO] djh - not sure yet what the device config needs to contain */ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { @@ -433,7 +441,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_KWORLD_DVB_310U: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, @@ -444,6 +451,25 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2880_BOARD_TERRATEC_HYBRID_XS: + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_terratec_xs_zl10353_xc3028, + &dev->i2c_adap); + if (dvb->frontend == NULL) { + /* This board could have either a zl10353 or a mt352. + If the chip id isn't for zl10353, try mt352 */ + + /* FIXME: make support for mt352 work */ + printk(KERN_ERR "version of this board with mt352 not " + "currently supported\n"); + result = -EINVAL; + goto out_free; + } + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->frontend = dvb_attach(s5h1409_attach, diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2c86fcf089f..27e33a287df 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -483,7 +483,7 @@ static char *i2c_devs[128] = { [0xa0 >> 1] = "eeprom", [0xb0 >> 1] = "tda9874", [0xb8 >> 1] = "tvp5150a", - [0xba >> 1] = "tvp5150a", + [0xba >> 1] = "webcam sensor or tvp5150a", [0xc0 >> 1] = "tuner (analog)", [0xc2 >> 1] = "tuner (analog)", [0xc4 >> 1] = "tuner (analog)", diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8fe1beecfff..14316c91217 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct em28xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", + .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, + }, { + .name = "16 bpp RGB 565, LE", + .fourcc = V4L2_PIX_FMT_RGB565, + .depth = 16, + .reg = EM28XX_OUTFMT_RGB_16_656, + }, { + .name = "8 bpp Bayer BGBG..GRGR", + .fourcc = V4L2_PIX_FMT_SBGGR8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, + }, { + .name = "8 bpp Bayer GRGR..BGBG", + .fourcc = V4L2_PIX_FMT_SGRBG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GRGR, + }, { + .name = "8 bpp Bayer GBGB..RGRG", + .fourcc = V4L2_PIX_FMT_SGBRG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, + }, { + .name = "12 bpp YUV411", + .fourcc = V4L2_PIX_FMT_YUV411P, + .depth = 12, + .reg = EM28XX_OUTFMT_YUV411, }, }; @@ -701,7 +726,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_em2800) { + if (dev->board.is_27xx) { + /* FIXME: This is the only supported fmt */ + width = 640; + height = 480; + } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; @@ -733,13 +762,40 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, + unsigned width, unsigned height) +{ + struct em28xx_fmt *fmt; + + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) { + width = 640; + height = 480; + } + + fmt = format_by_fourcc(fourcc); + if (!fmt) + return -EINVAL; + + dev->format = fmt; + dev->width = width; + dev->height = height; + + /* set new image size */ + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + em28xx_set_alternate(dev); + em28xx_resolution_set(dev); + + return 0; +} + static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; - struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -749,12 +805,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, vidioc_try_fmt_vid_cap(file, priv, f); - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - rc = -EINVAL; - goto out; - } - if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -767,16 +817,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - /* set new image size */ - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - dev->format = fmt; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - rc = 0; + rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, + f->fmt.pix.width, f->fmt.pix.height); out: mutex_unlock(&dev->lock); @@ -1616,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) filp->private_data = fh; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->hscale = 0; - dev->vscale = 0; - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_alternate(dev); em28xx_resolution_set(dev); @@ -1962,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* set default norm */ dev->norm = em28xx_video_template.current_norm; - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; dev->ctl_input = 0; /* Analog specific initialization */ dev->format = &format[0]; + em28xx_set_video_format(dev, format[0].fourcc, + norm_maxw(dev), norm_maxh(dev)); + video_mux(dev, dev->ctl_input); /* Audio defaults */ diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 813ce45c2f9..d90fef46376 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -107,6 +107,7 @@ #define EM2860_BOARD_TERRATEC_AV350 68 #define EM2882_BOARD_KWORLD_ATSC_315U 69 #define EM2882_BOARD_EVGA_INDTUBE 70 +#define EM2820_BOARD_SILVERCREST_WEBCAM 71 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -360,6 +361,7 @@ enum em28xx_decoder { EM28XX_NODECODER, EM28XX_TVP5150, EM28XX_SAA711X, + EM28XX_MT9V011, }; enum em28xx_adecoder { @@ -388,6 +390,7 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; + unsigned int is_27xx:1; unsigned int valid:1; unsigned char xclk, i2c_speed; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 9df7137fe67..992ce530f13 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -36,10 +36,6 @@ #define STV_ISOC_ENDPOINT_ADDR 0x81 -#ifndef V4L2_PIX_FMT_SGRBG8 -#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') -#endif - #define STV_REG23 0x0423 /* Control registers of the STV0600 ASIC */ diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c new file mode 100644 index 00000000000..1fe8fc9183a --- /dev/null +++ b/drivers/media/video/mt9v011.c @@ -0,0 +1,431 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#include <linux/i2c.h> +#include <linux/videodev2.h> +#include <linux/delay.h> +#include <media/v4l2-device.h> +#include "mt9v011.h" +#include <media/v4l2-i2c-drv.h> +#include <media/v4l2-chip-ident.h> + +MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_LICENSE("GPL"); + + +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-2)"); + +/* supported controls */ +static struct v4l2_queryctrl mt9v011_qctrl[] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = (1 << 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, +}; + +struct mt9v011 { + struct v4l2_subdev sd; + unsigned width, height; + + u16 global_gain, red_bal, blue_bal; +}; + +static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mt9v011, sd); +} + +static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + __be16 buffer; + int rc, val; + + rc = i2c_master_send(c, &addr, 1); + if (rc != 1) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 1)\n", rc); + + msleep(10); + + rc = i2c_master_recv(c, (char *)&buffer, 2); + if (rc != 2) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 2)\n", rc); + + val = be16_to_cpu(buffer); + + v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); + + return val; +} + +static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, + u16 value) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned char buffer[3]; + int rc; + + buffer[0] = addr; + buffer[1] = value >> 8; + buffer[2] = value & 0xff; + + v4l2_dbg(2, debug, sd, + "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); + rc = i2c_master_send(c, buffer, 3); + if (rc != 3) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 3)\n", rc); +} + + +struct i2c_reg_value { + unsigned char reg; + u16 value; +}; + +/* + * Values used at the original driver + * Some values are marked as Reserved at the datasheet + */ +static const struct i2c_reg_value mt9v011_init_default[] = { + { R0D_MT9V011_RESET, 0x0001 }, + { R0D_MT9V011_RESET, 0x0000 }, + + { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, + { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, + + { R0A_MT9V011_CLK_SPEED, 0x0000 }, + { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, + { R20_MT9V011_READ_MODE, 0x1000 }, + + { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ +}; + +static void set_balance(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + u16 green1_gain, green2_gain, blue_gain, red_gain; + + green1_gain = core->global_gain; + green2_gain = core->global_gain; + + blue_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + red_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain); + mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green1_gain); + mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); + mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); +} + +static void set_res(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned vstart, hstart; + + /* + * The mt9v011 doesn't have scaling. So, in order to select the desired + * resolution, we're cropping at the middle of the sensor. + * hblank and vblank should be adjusted, in order to warrant that + * we'll preserve the line timings for 30 fps, no matter what resolution + * is selected. + * NOTE: datasheet says that width (and height) should be filled with + * width-1. However, this doesn't work, since one pixel per line will + * be missing. + */ + + hstart = 14 + (640 - core->width) / 2; + mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); + mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); + mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); + + vstart = 8 + (640 - core->height) / 2; + mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); + mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); + mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); +}; + +static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) + mt9v011_write(sd, mt9v011_init_default[i].reg, + mt9v011_init_default[i].value); + + set_balance(sd); + set_res(sd); + + return 0; +}; + +static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + + v4l2_dbg(1, debug, sd, "g_ctrl called\n"); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + ctrl->value = core->global_gain; + return 0; + case V4L2_CID_RED_BALANCE: + ctrl->value = core->red_bal; + return 0; + case V4L2_CID_BLUE_BALANCE: + ctrl->value = core->blue_bal; + return 0; + } + return -EINVAL; +} + +static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + u8 i, n; + n = ARRAY_SIZE(mt9v011_qctrl); + + for (i = 0; i < n; i++) { + if (ctrl->id != mt9v011_qctrl[i].id) + continue; + if (ctrl->value < mt9v011_qctrl[i].minimum || + ctrl->value > mt9v011_qctrl[i].maximum) + return -ERANGE; + v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", + ctrl->id, ctrl->value); + break; + } + + switch (ctrl->id) { + case V4L2_CID_GAIN: + core->global_gain = ctrl->value; + break; + case V4L2_CID_RED_BALANCE: + core->red_bal = ctrl->value; + break; + case V4L2_CID_BLUE_BALANCE: + core->blue_bal = ctrl->value; + break; + default: + return -EINVAL; + } + + set_balance(sd); + + return 0; +} + +static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) +{ + if (fmt->index > 0) + return -EINVAL; + + fmt->flags = 0; + strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); + fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; + + return 0; +} + +static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) + return -EINVAL; + + v4l_bound_align_image(&pix->width, 48, 639, 1, + &pix->height, 32, 480, 1, 0); + + return 0; +} + +static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + struct mt9v011 *core = to_mt9v011(sd); + int rc; + + rc = mt9v011_try_fmt(sd, fmt); + if (rc < 0) + return -EINVAL; + + core->width = pix->width; + core->height = pix->height; + + set_res(sd); + + return 0; +} + + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v011_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + reg->val = mt9v011_read(sd, reg->reg & 0xff); + reg->size = 2; + + return 0; +} + +static int mt9v011_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); + + return 0; +} +#endif + +static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, + MT9V011_VERSION); +} + +static const struct v4l2_subdev_core_ops mt9v011_core_ops = { + .g_ctrl = mt9v011_g_ctrl, + .s_ctrl = mt9v011_s_ctrl, + .reset = mt9v011_reset, + .g_chip_ident = mt9v011_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v011_g_register, + .s_register = mt9v011_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops mt9v011_video_ops = { + .enum_fmt = mt9v011_enum_fmt, + .try_fmt = mt9v011_try_fmt, + .s_fmt = mt9v011_s_fmt, +}; + +static const struct v4l2_subdev_ops mt9v011_ops = { + .core = &mt9v011_core_ops, + .video = &mt9v011_video_ops, +}; + + +/**************************************************************************** + I2C Client & Driver + ****************************************************************************/ + +static int mt9v011_probe(struct i2c_client *c, + const struct i2c_device_id *id) +{ + u16 version; + struct mt9v011 *core; + struct v4l2_subdev *sd; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(c->adapter, + I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -EIO; + + core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); + if (!core) + return -ENOMEM; + + sd = &core->sd; + v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); + + /* Check if the sensor is really a MT9V011 */ + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + if (version != MT9V011_VERSION) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + version); + kfree(core); + return -EINVAL; + } + + core->global_gain = 0x0024; + core->width = 640; + core->height = 480; + + v4l_info(c, "chip found @ 0x%02x (%s)\n", + c->addr << 1, c->adapter->name); + + return 0; +} + +static int mt9v011_remove(struct i2c_client *c) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(c); + + v4l2_dbg(1, debug, sd, + "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", + c->addr << 1); + + v4l2_device_unregister_subdev(sd); + kfree(to_mt9v011(sd)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct i2c_device_id mt9v011_id[] = { + { "mt9v011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9v011_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "mt9v011", + .probe = mt9v011_probe, + .remove = mt9v011_remove, + .id_table = mt9v011_id, +}; diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h new file mode 100644 index 00000000000..9e443ee3055 --- /dev/null +++ b/drivers/media/video/mt9v011.h @@ -0,0 +1,35 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#ifndef MT9V011_H_ +#define MT9V011_H_ + +#define R00_MT9V011_CHIP_VERSION 0x00 +#define R01_MT9V011_ROWSTART 0x01 +#define R02_MT9V011_COLSTART 0x02 +#define R03_MT9V011_HEIGHT 0x03 +#define R04_MT9V011_WIDTH 0x04 +#define R05_MT9V011_HBLANK 0x05 +#define R06_MT9V011_VBLANK 0x06 +#define R07_MT9V011_OUT_CTRL 0x07 +#define R09_MT9V011_SHUTTER_WIDTH 0x09 +#define R0A_MT9V011_CLK_SPEED 0x0a +#define R0B_MT9V011_RESTART 0x0b +#define R0C_MT9V011_SHUTTER_DELAY 0x0c +#define R0D_MT9V011_RESET 0x0d +#define R1E_MT9V011_DIGITAL_ZOOM 0x1e +#define R20_MT9V011_READ_MODE 0x20 +#define R2B_MT9V011_GREEN_1_GAIN 0x2b +#define R2C_MT9V011_BLUE_GAIN 0x2c +#define R2D_MT9V011_RED_GAIN 0x2d +#define R2E_MT9V011_GREEN_2_GAIN 0x2e +#define R35_MT9V011_GLOBAL_GAIN 0x35 +#define RF1_MT9V011_CHIP_ENABLE 0xf1 + +#define MT9V011_VERSION 0x8243 + +#endif diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 16f595d4337..9f5ae816785 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -237,11 +237,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return -ENOMEM; icd->num_user_formats = fmts; - fmts = 0; dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); /* Second pass - actually fill data formats */ + fmts = 0; for (i = 0; i < icd->num_formats; i++) if (!ici->ops->get_formats) { icd->user_formats[i].host_fmt = icd->formats + i; @@ -877,8 +877,11 @@ static int soc_camera_probe(struct device *dev) (unsigned short)~0; ret = soc_camera_init_user_formats(icd); - if (ret < 0) + if (ret < 0) { + if (icd->ops->remove) + icd->ops->remove(icd); goto eiufmt; + } icd->height = DEFAULT_HEIGHT; icd->width = DEFAULT_WIDTH; @@ -902,8 +905,10 @@ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + mutex_lock(&icd->video_lock); if (icd->ops->remove) icd->ops->remove(icd); + mutex_unlock(&icd->video_lock); soc_camera_free_user_formats(icd); @@ -1145,6 +1150,7 @@ evidallocd: } EXPORT_SYMBOL(soc_camera_video_start); +/* Called from client .remove() methods with .video_lock held */ void soc_camera_video_stop(struct soc_camera_device *icd) { struct video_device *vdev = icd->vdev; @@ -1154,10 +1160,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd) if (!icd->dev.parent || !vdev) return; - mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&icd->video_lock); } EXPORT_SYMBOL(soc_camera_video_stop); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cd726685846..7705fc6baf0 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -343,6 +343,53 @@ static struct bar_std bars[] = { #define TO_U(r, g, b) \ (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) +/* precalculate color bar values to speed up rendering */ +static void precalculate_bars(struct vivi_fh *fh) +{ + struct vivi_dev *dev = fh->dev; + unsigned char r, g, b; + int k, is_yuv; + + fh->input = dev->input; + + for (k = 0; k < 8; k++) { + r = bars[fh->input].bar[k][0]; + g = bars[fh->input].bar[k][1]; + b = bars[fh->input].bar[k][2]; + is_yuv = 0; + + switch (fh->fmt->fourcc) { + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + is_yuv = 1; + break; + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + r >>= 3; + g >>= 2; + b >>= 3; + break; + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_RGB555X: + r >>= 3; + g >>= 3; + b >>= 3; + break; + } + + if (is_yuv) { + fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ + fh->bars[k][1] = TO_U(r, g, b); /* Cb */ + fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + } else { + fh->bars[k][0] = r; + fh->bars[k][1] = g; + fh->bars[k][2] = b; + } + } + +} + #define TSTAMP_MIN_Y 24 #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) #define TSTAMP_INPUT_X 10 @@ -755,6 +802,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.height = fh->height; buf->vb.field = field; + precalculate_bars(fh); + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) @@ -893,53 +942,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -/* precalculate color bar values to speed up rendering */ -static void precalculate_bars(struct vivi_fh *fh) -{ - struct vivi_dev *dev = fh->dev; - unsigned char r, g, b; - int k, is_yuv; - - fh->input = dev->input; - - for (k = 0; k < 8; k++) { - r = bars[fh->input].bar[k][0]; - g = bars[fh->input].bar[k][1]; - b = bars[fh->input].bar[k][2]; - is_yuv = 0; - - switch (fh->fmt->fourcc) { - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - is_yuv = 1; - break; - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - r >>= 3; - g >>= 2; - b >>= 3; - break; - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - r >>= 3; - g >>= 3; - b >>= 3; - break; - } - - if (is_yuv) { - fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ - fh->bars[k][1] = TO_U(r, g, b); /* Cb */ - fh->bars[k][2] = TO_V(r, g, b); /* Cr */ - } else { - fh->bars[k][0] = r; - fh->bars[k][1] = g; - fh->bars[k][2] = b; - } - } - -} - /*FIXME: This seems to be generic enough to be at videodev2 */ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) @@ -965,8 +967,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vb_vidq.field = f->fmt.pix.field; fh->type = f->type; - precalculate_bars(fh); - ret = 0; out: mutex_unlock(&q->vb_lock); @@ -1357,6 +1357,7 @@ static int __init vivi_create_instance(int inst) goto unreg_dev; *vfd = vivi_template; + vfd->debug = debug; ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); if (ret < 0) diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 7ac12cb0be4..5b6e58a3ba4 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -32,8 +32,7 @@ * This driver was tested with firmware revision A4. */ -#if defined(CONFIG_KEYBOARD_DM355EVM) \ - || defined(CONFIG_KEYBOARD_DM355EVM_MODULE) +#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE) #define msp_has_keyboard() true #else #define msp_has_keyboard() false diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 8d1c60a3f0d..5d778ec8cdb 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -235,7 +235,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg) skb->ip_summed = CHECKSUM_UNNECESSARY; dev_dbg(xpnet, "passing skb to network layer\n" - KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " + "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " "skb->end=0x%p skb->len=%d\n", (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); @@ -399,7 +399,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg, msg->buf_pa = xp_pa((void *)start_addr); dev_dbg(xpnet, "sending XPC message to %d:%d\n" - KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, " + "msg->buf_pa=0x%lx, msg->size=%u, " "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n", dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size, msg->leadin_ignore, msg->tailout_ignore); diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 85a18175730..08787f5a22a 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -569,16 +569,8 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) #ifdef DEBUG_DRIVER /* dump the packet */ - { - int i; - - for (i = 0; i < 64; i++) { - if ((i % 16) == 0) - printk("\n" KERN_DEBUG); - printk ("%2.2x ", skb->data [i]); - } - printk("\n"); - } + print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE, + 16, 1, skb->data, 64, true); #endif entry = lp->tx_new & lp->tx_ring_mod_mask; ib->btx_ring [entry].length = (-skblen) | 0xf000; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index d6d4ab3b430..7d227cdab9f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -158,15 +158,12 @@ module_exit(arcnet_exit); void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) { - int i; + char hdr[32]; - printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); - for (i = 0; i < skb->len; i++) { - if (i % 16 == 0) - printk("\n" KERN_DEBUG "[%04X] ", i); - printk("%02X ", ((u_char *) skb->data)[i]); - } - printk("\n"); + /* dump the packet */ + snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc); + print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, + 16, 1, skb->data, skb->len, true); } EXPORT_SYMBOL(arcnet_dump_skb); @@ -184,6 +181,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, int i, length; unsigned long flags = 0; static uint8_t buf[512]; + char hdr[32]; /* hw.copy_from_card expects IRQ context so take the IRQ lock to keep it single threaded */ @@ -197,14 +195,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, /* if the offset[0] byte is nonzero, this is a 256-byte packet */ length = (buf[2] ? 256 : 512); - printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); - for (i = 0; i < length; i++) { - if (i % 16 == 0) - printk("\n" KERN_DEBUG "[%04X] ", i); - printk("%02X ", buf[i]); - } - printk("\n"); - + /* dump the packet */ + snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc); + print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, + 16, 1, buf, length, true); } #else diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index b02e805c1db..29c33c709c6 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -55,6 +55,10 @@ #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 +/********* ISR0 Register offset **********/ +#define CEV_ISR0_OFFSET 0xC18 +#define CEV_ISR_SIZE 4 + /********* Event Q door bell *************/ #define DB_EQ_OFFSET DB_CQ_OFFSET #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 308eb09ca56..c43f6a11929 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1274,15 +1274,17 @@ static irqreturn_t be_intx(int irq, void *dev) { struct be_adapter *adapter = dev; struct be_ctrl_info *ctrl = &adapter->ctrl; - int rx, tx; + int isr; - tx = event_handle(ctrl, &adapter->tx_eq); - rx = event_handle(ctrl, &adapter->rx_eq); + isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + + ctrl->pci_func * CEV_ISR_SIZE); + if (!isr) + return IRQ_NONE; - if (rx || tx) - return IRQ_HANDLED; - else - return IRQ_NONE; + event_handle(ctrl, &adapter->tx_eq); + event_handle(ctrl, &adapter->rx_eq); + + return IRQ_HANDLED; } static irqreturn_t be_msix_rx(int irq, void *dev) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 9578a3dfac0..206144f2470 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -428,10 +428,11 @@ bmac_init_phy(struct net_device *dev) printk(KERN_DEBUG "phy registers:"); for (addr = 0; addr < 32; ++addr) { if ((addr & 7) == 0) - printk("\n" KERN_DEBUG); - printk(" %.4x", bmac_mif_read(dev, addr)); + printk(KERN_DEBUG); + printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); } - printk("\n"); + printk(KERN_CONT "\n"); + if (bp->is_bmac_plus) { unsigned int capable, ctrl; diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 8678457849f..85a737c5c23 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -902,6 +902,8 @@ struct bnx2x { u16 rx_quick_cons_trip; u16 rx_ticks_int; u16 rx_ticks; +/* Maximal coalescing timeout in us */ +#define BNX2X_MAX_COALESCE_TOUT (0xf0*12) u32 lin_cnt; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 951714a7f90..c36a5f33739 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -484,8 +484,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp) mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); mark = ((mark + 0x3) & ~0x3); - printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark); + printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark); + printk(KERN_ERR PFX); for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + @@ -500,7 +501,7 @@ static void bnx2x_fw_dump(struct bnx2x *bp) data[8] = 0x0; printk(KERN_CONT "%s", (char *)data); } - printk("\n" KERN_ERR PFX "end of fw dump\n"); + printk(KERN_ERR PFX "end of fw dump\n"); } static void bnx2x_panic_dump(struct bnx2x *bp) @@ -4434,7 +4435,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR16(bp, BAR_USTRORM_INTMEM + USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - bp->rx_ticks ? 0 : 1); + (bp->rx_ticks/12) ? 0 : 1); /* HC_INDEX_C_ETH_TX_CQ_CONS */ REG_WR8(bp, BAR_CSTRORM_INTMEM + @@ -4444,7 +4445,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - bp->tx_ticks ? 0 : 1); + (bp->tx_ticks/12) ? 0 : 1); } } @@ -7354,7 +7355,7 @@ static void bnx2x_reset_task(struct work_struct *work) #ifdef BNX2X_STOP_ON_ERROR BNX2X_ERR("reset task called but STOP_ON_ERROR defined" " so reset not done to allow debug dump,\n" - KERN_ERR " you will need to reboot when done\n"); + " you will need to reboot when done\n"); return; #endif @@ -9069,12 +9070,12 @@ static int bnx2x_set_coalesce(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); bp->rx_ticks = (u16) coal->rx_coalesce_usecs; - if (bp->rx_ticks > 3000) - bp->rx_ticks = 3000; + if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT; bp->tx_ticks = (u16) coal->tx_coalesce_usecs; - if (bp->tx_ticks > 0x3000) - bp->tx_ticks = 0x3000; + if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT; if (netif_running(dev)) bnx2x_update_coalesce(bp); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 538dda4422d..fb5df5c6203 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -642,8 +642,7 @@ static int setup_sge_qsets(struct adapter *adap) struct port_info *pi = netdev_priv(dev); pi->qs = &adap->sge.qs[pi->first_qset]; - for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; - ++j, ++qset_idx) { + for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); err = t3_sge_alloc_qset(adap, qset_idx, 1, (adap->flags & USING_MSIX) ? qset_idx + 1 : diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2df8fb0af70..12fd446f989 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1820,11 +1820,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; + if (!is_valid_ether_addr(sa->sa_data)) + return -EINVAL; + /* Store mac addr in priv and rx channel and set it in EMAC hw */ memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + + /* If the interface is down - rxch is NULL. */ + /* MAC address is configured only after the interface is enabled. */ + if (netif_running(ndev)) { + memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + } if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 895d72143ee..4b6a219fece 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -268,8 +268,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_INFO "tx_coalesce:\t%d packets\n", tx_coalesce); if (np->coalesce) - printk(KERN_INFO "rx_coalesce:\t%d packets\n" - KERN_INFO "rx_timeout: \t%d ns\n", + printk(KERN_INFO + "rx_coalesce:\t%d packets\n" + "rx_timeout: \t%d ns\n", np->rx_coalesce, np->rx_timeout*640); if (np->vlan) printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); @@ -1522,9 +1523,9 @@ mii_get_media (struct net_device *dev) printk (KERN_INFO "Operating at 10 Mbps, "); } if (bmcr & MII_BMCR_DUPLEX_MODE) { - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } } if (np->tx_flow) @@ -1614,9 +1615,9 @@ mii_set_media (struct net_device *dev) } if (np->full_duplex) { bmcr |= MII_BMCR_DUPLEX_MODE; - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } #if 0 /* Set 1000BaseT Master/Slave setting */ @@ -1669,9 +1670,9 @@ mii_get_media_pcs (struct net_device *dev) __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR); printk (KERN_INFO "Operating at 1000 Mbps, "); if (bmcr & MII_BMCR_DUPLEX_MODE) { - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } } if (np->tx_flow) diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 8890c97e112..c0f185beb8b 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -238,6 +238,7 @@ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ +#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ /* Constants used to interpret the masked PCI-X bus speed. */ @@ -575,6 +576,8 @@ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ +#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ + /* NVM Control */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 163c1c0cfee..fd44d9f9076 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -215,6 +215,7 @@ enum e1e_registers { E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ + E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ E1000_HICR = 0x08F00, /* Host Interface Control */ }; @@ -302,6 +303,9 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ +#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 +#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E +#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 9e23f50fb9c..d56c7473144 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -338,6 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + union ich8_hws_flash_status hsfsts; u32 gfpreg; u32 sector_base_addr; u32 sector_end_addr; @@ -374,6 +375,20 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); + /* + * Make sure the flash bank size does not overwrite the 4k + * sector ranges. We may have 64k allotted to us but we only care + * about the first 2 4k sectors. Therefore, if we have anything less + * than 64k set in the HSFSTS register, we will reduce the bank size + * down to 4k and let the rest remain unused. If berasesz == 3, then + * we are working in 64k mode. Otherwise we are not. + */ + if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) { + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.berasesz != 3) + nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS; + } + nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; /* Clear shadow ram */ @@ -446,6 +461,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) return 0; } +/** + * e1000_check_for_copper_link_ich8lan - Check for link (Copper) + * @hw: pointer to the HW structure + * + * Checks to see of the link status of the hardware has changed. If a + * change in link status has been detected, then we read the PHY registers + * to get the current speed/duplex if link exists. + **/ +static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + bool link; + + /* + * We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. + */ + if (!mac->get_link_status) { + ret_val = 0; + goto out; + } + + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_ENABLE); + if (ret_val) + goto out; + } + + /* + * First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) + goto out; /* No link detected */ + + mac->get_link_status = false; + + if (hw->phy.type == e1000_phy_82578) { + ret_val = e1000_link_stall_workaround_hv(hw); + if (ret_val) + goto out; + } + + /* + * Check if there was DownShift, must be checked + * immediately after link-up + */ + e1000e_check_downshift(hw); + + /* + * If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ + if (!mac->autoneg) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + /* + * Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ + e1000e_config_collision_dist(hw); + + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000e_config_fc_after_link_up(hw); + if (ret_val) + hw_dbg(hw, "Error configuring flow control\n"); + +out: + return ret_val; +} + static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; @@ -694,6 +798,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) } /** + * e1000_lan_init_done_ich8lan - Check for PHY config completion + * @hw: pointer to the HW structure + * + * Check the appropriate indication the MAC has finished configuring the + * PHY after a software reset. + **/ +static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) +{ + u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; + + /* Wait for basic configuration completes before proceeding */ + do { + data = er32(STATUS); + data &= E1000_STATUS_LAN_INIT_DONE; + udelay(100); + } while ((!data) && --loop); + + /* + * If basic configuration is incomplete before the above loop + * count reaches 0, loading the configuration from NVM will + * leave the PHY in a bad state possibly resulting in no link. + */ + if (loop == 0) + hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); + + /* Clear the Init Done bit for the next init event */ + data = er32(STATUS); + data &= ~E1000_STATUS_LAN_INIT_DONE; + ew32(STATUS, data); +} + +/** * e1000_phy_hw_reset_ich8lan - Performs a PHY reset * @hw: pointer to the HW structure * @@ -707,13 +843,15 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) u32 i; u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val; - u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; u16 word_addr, reg_data, reg_addr, phy_page = 0; ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) return ret_val; + /* Allow time for h/w to get to a quiescent state after reset */ + mdelay(10); + if (hw->mac.type == e1000_pchlan) { ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) @@ -741,26 +879,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) if (!(data & sw_cfg_mask)) return 0; - /* Wait for basic configuration completes before proceeding*/ - do { - data = er32(STATUS); - data &= E1000_STATUS_LAN_INIT_DONE; - udelay(100); - } while ((!data) && --loop); - - /* - * If basic configuration is incomplete before the above loop - * count reaches 0, loading the configuration from NVM will - * leave the PHY in a bad state possibly resulting in no link. - */ - if (loop == 0) { - hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); - } - - /* Clear the Init Done bit for the next init event */ - data = er32(STATUS); - data &= ~E1000_STATUS_LAN_INIT_DONE; - ew32(STATUS, data); + /* Wait for basic configuration completes before proceeding */ + e1000_lan_init_done_ich8lan(hw); /* * Make sure HW does not configure LCD from PHY @@ -961,12 +1081,14 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * Call gig speed drop workaround on LPLU before accessing * any PHY registers */ - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3)) + if (hw->mac.type == e1000_ich8lan) e1000e_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ @@ -979,6 +1101,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most @@ -1038,6 +1163,10 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (!active) { phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + + if (phy->type != e1000_phy_igp_3) + return 0; + /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most @@ -1073,12 +1202,14 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * Call gig speed drop workaround on LPLU before accessing * any PHY registers */ - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3)) + if (hw->mac.type == e1000_ich8lan) e1000e_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ @@ -1905,7 +2036,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) break; case 1: sector_size = ICH_FLASH_SEG_SIZE_4K; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; + iteration = 1; break; case 2: if (hw->mac.type == e1000_ich9lan) { @@ -1917,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) break; case 3: sector_size = ICH_FLASH_SEG_SIZE_64K; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; + iteration = 1; break; default: return -E1000_ERR_NVM; @@ -2143,6 +2274,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl = er32(CTRL); if (!e1000_check_reset_block(hw)) { + /* Clear PHY Reset Asserted bit */ + if (hw->mac.type >= e1000_pchlan) { + u32 status = er32(STATUS); + ew32(STATUS, status & ~E1000_STATUS_PHYRA); + } + /* * PHY HW reset requires MAC CORE reset at the same * time to make sure the interface between MAC and the @@ -2156,23 +2293,34 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(CTRL, (ctrl | E1000_CTRL_RST)); msleep(20); - if (!ret_val) { - /* release the swflag because it is not reset by - * hardware reset - */ + if (!ret_val) e1000_release_swflag_ich8lan(hw); - } - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) { - /* - * When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - hw_dbg(hw, "Auto Read Done did not complete\n"); + if (ctrl & E1000_CTRL_PHY_RST) + ret_val = hw->phy.ops.get_cfg_done(hw); + + if (hw->mac.type >= e1000_ich10lan) { + e1000_lan_init_done_ich8lan(hw); + } else { + ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) { + /* + * When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + hw_dbg(hw, "Auto Read Done did not complete\n"); + } } + /* + * For PCH, this write will make sure that any noise + * will be detected as a CRC error and be dropped rather than show up + * as a bad packet to the DMA engine. + */ + if (hw->mac.type == e1000_pchlan) + ew32(CRC_OFFSET, 0x65656565); + ew32(IMC, 0xffffffff); icr = er32(ICR); @@ -2222,6 +2370,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + /* + * The 82578 Rx buffer will stall if wakeup is enabled in host and + * the ME. Reading the BM_WUC register will clear the host wakeup bit. + * Reset the phy after disabling host wakeup to reset the Rx buffer. + */ + if (hw->phy.type == e1000_phy_82578) { + hw->phy.ops.read_phy_reg(hw, BM_WUC, &i); + ret_val = e1000_phy_hw_reset_ich8lan(hw); + if (ret_val) + return ret_val; + } + /* Setup link and flow control */ ret_val = e1000_setup_link_ich8lan(hw); @@ -2254,16 +2414,6 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) ew32(CTRL_EXT, ctrl_ext); /* - * The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Reading the BM_WUC register will clear the host wakeup bit. - * Reset the phy after disabling host wakeup to reset the Rx buffer. - */ - if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_WUC, &i); - e1000e_phy_hw_reset_generic(hw); - } - - /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there @@ -2485,6 +2635,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, if (ret_val) return ret_val; + if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_DISABLE); + if (ret_val) + return ret_val; + } + if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { @@ -2850,6 +3008,16 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) { u32 bank = 0; + if (hw->mac.type >= e1000_pchlan) { + u32 status = er32(STATUS); + + if (status & E1000_STATUS_PHYRA) + ew32(STATUS, status & ~E1000_STATUS_PHYRA); + else + hw_dbg(hw, + "PHY Reset Asserted not set - needs delay\n"); + } + e1000e_get_cfg_done(hw); /* If EEPROM is not marked present, init the IGP 3 PHY manually */ @@ -2921,7 +3089,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) static struct e1000_mac_operations ich8_mac_ops = { .id_led_init = e1000e_id_led_init, .check_mng_mode = e1000_check_mng_mode_ich8lan, - .check_for_link = e1000e_check_for_copper_link, + .check_for_link = e1000_check_for_copper_link_ich8lan, /* cleanup_led dependent on mac type */ .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, .get_bus_info = e1000_get_bus_info_ich8lan, diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index be6d9e99037..99ba2b8a2a0 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) mac->get_link_status = 0; - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1000_link_stall_workaround_hv(hw); - if (ret_val) - return ret_val; - } - /* * Check if there was DownShift, must be checked * immediately after link-up diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index e23459cf3d0..994401fd066 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1531,7 +1531,12 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, */ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); if (ret_val) - break; + /* + * If the first read fails, another entity may have + * ownership of the resources, wait and try again to + * see if they have relinquished the resources yet. + */ + udelay(usec_interval); ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); if (ret_val) break; @@ -2737,6 +2742,11 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) if (hw->phy.type != e1000_phy_82578) goto out; + /* Do not apply workaround if in PHY loopback bit 14 set */ + hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data); + if (data & PHY_CONTROL_LB) + goto out; + /* check if link is up and at 1Gbps */ ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); if (ret_val) diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index b60e27dfcfa..88d7ebf3122 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -338,8 +338,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, #ifndef MODULE static int printed_version; if (!printed_version++) - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk(KERN_INFO "%s%s", version, version2); #endif card_idx++; @@ -1600,7 +1599,7 @@ static int __init epic_init (void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk (KERN_INFO "%s" KERN_INFO "%s", + printk (KERN_INFO "%s%s", version, version2); #endif diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 891be28a7d4..48385c42ab5 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1209,17 +1209,20 @@ static void fealnx_tx_timeout(struct net_device *dev) unsigned long flags; int i; - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, ioread32(ioaddr + ISR)); + printk(KERN_WARNING + "%s: Transmit timed out, status %8.8x, resetting...\n", + dev->name, ioread32(ioaddr + ISR)); { printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int) np->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); + printk(KERN_CONT " %8.8x", + (unsigned int) np->rx_ring[i].status); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", np->tx_ring[i].status); - printk("\n"); + printk(KERN_CONT " %4.4x", np->tx_ring[i].status); + printk(KERN_CONT "\n"); } spin_lock_irqsave(&np->lock, flags); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 30b7dd67133..cc47f3f057c 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -46,12 +46,12 @@ #else -#define FEC_ECNTRL; 0x000 /* Ethernet control reg */ -#define FEC_IEVENT; 0x004 /* Interrupt even reg */ -#define FEC_IMASK; 0x008 /* Interrupt mask reg */ -#define FEC_IVEC; 0x00c /* Interrupt vec status reg */ -#define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ -#define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ +#define FEC_ECNTRL 0x000 /* Ethernet control reg */ +#define FEC_IEVENT 0x004 /* Interrupt even reg */ +#define FEC_IMASK 0x008 /* Interrupt mask reg */ +#define FEC_IVEC 0x00c /* Interrupt vec status reg */ +#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ #define FEC_MII_DATA 0x040 /* MII manage frame reg */ #define FEC_MII_SPEED 0x044 /* MII speed control reg */ #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 1094d292630..3b4e0766c7b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3514,11 +3514,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - napi_schedule(&np->napi); - - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); + if (napi_schedule_prep(&np->napi)) { + /* + * Disable further irq's (msix not enabled with napi) + */ + writel(0, base + NvRegIrqMask); + __napi_schedule(&np->napi); + } #else do @@ -3615,12 +3617,13 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - napi_schedule(&np->napi); - - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); - + if (napi_schedule_prep(&np->napi)) { + /* + * Disable further irq's (msix not enabled with napi) + */ + writel(0, base + NvRegIrqMask); + __napi_schedule(&np->napi); + } #else do { diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 9d5b62cb30f..d62378cbc14 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -173,8 +173,8 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static const char version[] __devinitconst = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" -KERN_INFO " Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" -KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; +" Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" +" Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; /* IP_MF appears to be only defined in <netinet/ip.h>, however, @@ -1080,11 +1080,14 @@ static void hamachi_tx_timeout(struct net_device *dev) { printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length)); - printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); + printk(KERN_CONT " %8.8x", + le32_to_cpu(hmp->rx_ring[i].status_n_length)); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length)); - printk("\n"); + printk(KERN_CONT " %4.4x", + le32_to_cpu(hmp->tx_ring[i].status_n_length)); + printk(KERN_CONT "\n"); } /* Reinit the hardware and make sure the Rx and Tx processes @@ -1753,13 +1756,13 @@ static int hamachi_close(struct net_device *dev) #ifdef __i386__ if (hamachi_debug > 2) { - printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", + printk(KERN_DEBUG " Tx ring at %8.8x:\n", (int)hmp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %c #%d desc. %8.8x %8.8x.\n", + printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n", readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ', i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)hmp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n", @@ -1770,7 +1773,7 @@ static int hamachi_close(struct net_device *dev) u16 *addr = (u16 *) hmp->rx_skbuff[i]->data; int j; - + printk(KERN_DEBUG "Addr: "); for (j = 0; j < 0x50; j++) printk(" %4.4x", addr[j]); printk("\n"); diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 5e4b7afd068..352703255bb 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -68,7 +68,7 @@ static const char paranoia_str[] = KERN_ERR static const char bc_drvname[] = "baycom_epp"; static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 2e6fc4dc74b..5f5af9a606f 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -102,7 +102,7 @@ static const char bc_drvname[] = "baycom_par"; static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index b6a816e60c0..aa4488e871b 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c @@ -91,7 +91,7 @@ static const char bc_drvname[] = "baycom_ser_fdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c index 3bcc57acbe6..88c59359602 100644 --- a/drivers/net/hamradio/baycom_ser_hdx.c +++ b/drivers/net/hamradio/baycom_ser_hdx.c @@ -79,7 +79,7 @@ static const char bc_drvname[] = "baycom_ser_hdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index efd9be21488..ac28dd5a4fd 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -190,6 +190,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) phy->ops.write_reg = igb_write_phy_reg_igp; } + /* set lan id */ + hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> + E1000_STATUS_FUNC_SHIFT; + /* Set phy->phy_addr and phy->id. */ ret_val = igb_get_phy_id_82575(hw); if (ret_val) diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index d56890f5c9d..7c5978ad929 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -138,6 +138,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->hw.fc.requested_mode = ixgbe_fc_none; } adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + } adapter->flags |= IXGBE_FLAG_DCB_ENABLED; ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) @@ -154,6 +158,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->dcb_cfg.pfc_mode_enable = false; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) netdev->netdev_ops->ndo_open(netdev); diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0f7b6a3a2e6..2a978008fd6 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1830,7 +1830,6 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, break; default: wol->supported = 0; - retval = 0; } return retval; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5588ef493a3..e3442f47f93 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2697,19 +2697,23 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* * For hot-pluggable SFP+ devices, a new SFP+ module may have - * arrived before interrupts were enabled. We need to kick off - * the SFP+ module setup first, then try to bring up link. + * arrived before interrupts were enabled but after probe. Such + * devices wouldn't have their type identified yet. We need to + * kick off the SFP+ module setup first, then try to bring up link. * If we're not hot-pluggable SFP+, we just need to configure link * and bring it up. */ - err = hw->phy.ops.identify(hw); - if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize because " - "an unsupported SFP+ module type was detected.\n" - "Reload the driver after installing a supported " - "module.\n"); - ixgbe_down(adapter); - return err; + if (hw->phy.type == ixgbe_phy_unknown) { + err = hw->phy.ops.identify(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { + /* + * Take the device down and schedule the sfp tasklet + * which will unregister_netdev and log it. + */ + ixgbe_down(adapter); + schedule_work(&adapter->sfp_config_module_task); + return err; + } } if (ixgbe_is_sfp(hw)) { @@ -3126,7 +3130,11 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) #endif if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); - ixgbe_set_rss_queues(adapter); + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) + ixgbe_set_fdir_queues(adapter); + else + ixgbe_set_rss_queues(adapter); } /* adding FCoE rx rings to the end */ f->mask = adapter->num_rx_queues; @@ -3384,7 +3392,12 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) } #endif /* CONFIG_IXGBE_DCB */ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - ixgbe_cache_ring_rss(adapter); + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) + ixgbe_cache_ring_fdir(adapter); + else + ixgbe_cache_ring_rss(adapter); + fcoe_i = f->mask; } for (i = 0; i < f->indices; i++, fcoe_i++) @@ -3724,7 +3737,7 @@ static void ixgbe_sfp_task(struct work_struct *work) if ((hw->phy.type == ixgbe_phy_nl) && (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { s32 ret = hw->phy.ops.identify_sfp(hw); - if (ret) + if (ret == IXGBE_ERR_SFP_NOT_PRESENT) goto reschedule; ret = hw->phy.ops.reset(hw); if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { @@ -4534,13 +4547,17 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) u32 err; adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; + + /* Time for electrical oscillations to settle down */ + msleep(100); err = hw->phy.ops.identify_sfp(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { dev_err(&adapter->pdev->dev, "failed to initialize because " "an unsupported SFP+ module type was detected.\n" "Reload the driver after installing a supported " "module.\n"); - ixgbe_down(adapter); + unregister_netdev(adapter->netdev); return; } hw->mac.ops.setup_sfp(hw); @@ -5570,12 +5587,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_FCOE_CRC; netdev->features |= NETIF_F_FSO; netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; - DPRINTK(DRV, INFO, "FCoE enabled, " - "disabling Flow Director\n"); - adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; - adapter->flags &= - ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; - adapter->atr_sample_rate = 0; } else { adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; } diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 453e966762f..9ecad17522c 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -60,6 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { + hw->phy.mdio.prtad = phy_addr; if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { ixgbe_get_phy_id(hw); hw->phy.type = @@ -68,6 +69,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) break; } } + /* clear value if nothing found */ + hw->phy.mdio.prtad = 0; } else { status = 0; } diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c9bfe4eea18..78c088331f5 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -130,8 +130,8 @@ static int full_duplex[MAX_UNITS]; static const char version[] __devinitconst = KERN_INFO DRV_NAME " dp8381x driver, version " DRV_VERSION ", " DRV_RELDATE "\n" - KERN_INFO " originally by Donald Becker <becker@scyld.com>\n" - KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; + " originally by Donald Becker <becker@scyld.com>\n" + " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 5c3e242428f..992dbfffdb0 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -321,7 +321,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) } if (ei_debug && version_printed++ == 0) - printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); + printk(KERN_INFO "%s%s", version1, version2); printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr); diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 970cedeb5f3..e1cdba752e0 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -60,7 +60,18 @@ #define _NETXEN_NIC_LINUX_SUBVERSION 30 #define NETXEN_NIC_LINUX_VERSIONID "4.0.30" -#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) +#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) +#define _major(v) (((v) >> 24) & 0xff) +#define _minor(v) (((v) >> 16) & 0xff) +#define _build(v) ((v) & 0xffff) + +/* version in image has weird encoding: + * 7:0 - major + * 15:8 - minor + * 31:16 - build (little endian) + */ +#define NETXEN_DECODE_VERSION(v) \ + NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16)) #define NETXEN_NUM_FLASH_SECTORS (64) #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) @@ -614,6 +625,7 @@ struct netxen_new_user_info { #define NX_P2_MN_ROMIMAGE 0 #define NX_P3_CT_ROMIMAGE 1 #define NX_P3_MN_ROMIMAGE 2 +#define NX_FLASH_ROMIMAGE 3 #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ @@ -1243,7 +1255,7 @@ struct netxen_adapter { u32 resv3; u8 has_link_events; - u8 resv1; + u8 fw_type; u16 tx_context_id; u16 mtu; u16 is_up; @@ -1387,6 +1399,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_load_firmware(struct netxen_adapter *adapter); +int netxen_need_fw_reset(struct netxen_adapter *adapter); void netxen_request_firmware(struct netxen_adapter *adapter); void netxen_release_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 3cc047844af..82410367564 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -853,6 +853,7 @@ enum { #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) +#define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0)) #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 055bb61d6e7..b899bd51fcd 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -684,11 +684,84 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } int +netxen_need_fw_reset(struct netxen_adapter *adapter) +{ + u32 count, old_count; + u32 val, version, major, minor, build; + int i, timeout; + u8 fw_type; + + /* NX2031 firmware doesn't support heartbit */ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 1; + + /* last attempt had failed */ + if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) + return 1; + + old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); + + for (i = 0; i < 10; i++) { + + timeout = msleep_interruptible(200); + if (timeout) { + NXWR32(adapter, CRB_CMDPEG_STATE, + PHAN_INITIALIZE_FAILED); + return -EINTR; + } + + count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); + if (count != old_count) + break; + } + + /* firmware is dead */ + if (count == old_count) + return 1; + + /* check if we have got newer or different file firmware */ + if (adapter->fw) { + + const struct firmware *fw = adapter->fw; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); + version = NETXEN_DECODE_VERSION(val); + + major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); + + if (version > NETXEN_VERSION_CODE(major, minor, build)) + return 1; + + if (version == NETXEN_VERSION_CODE(major, minor, build)) { + + val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); + fw_type = (val & 0x4) ? + NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE; + + if (adapter->fw_type != fw_type) + return 1; + } + } + + return 0; +} + +static char *fw_name[] = { + "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash", +}; + +int netxen_load_firmware(struct netxen_adapter *adapter) { u64 *ptr64; u32 i, flashaddr, size; const struct firmware *fw = adapter->fw; + struct pci_dev *pdev = adapter->pdev; + + dev_info(&pdev->dev, "loading firmware from %s\n", + fw_name[adapter->fw_type]); if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); @@ -756,7 +829,7 @@ static int netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) { __le32 val; - u32 major, minor, build, ver, min_ver, bios; + u32 ver, min_ver, bios; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; @@ -768,21 +841,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) return -EINVAL; val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) min_ver = NETXEN_VERSION_CODE(4, 0, 216); else min_ver = NETXEN_VERSION_CODE(3, 4, 216); - ver = NETXEN_VERSION_CODE(major, minor, build); + ver = NETXEN_DECODE_VERSION(val); - if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { + if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { dev_err(&pdev->dev, "%s: firmware version %d.%d.%d unsupported\n", - fwname, major, minor, build); + fwname, _major(ver), _minor(ver), _build(ver)); return -EINVAL; } @@ -798,22 +868,21 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) if (netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&val)) return -EIO; - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - if (NETXEN_VERSION_CODE(major, minor, build) > ver) + val = NETXEN_DECODE_VERSION(val); + if (val > ver) { + dev_info(&pdev->dev, "%s: firmware is older than flash\n", + fwname); return -EINVAL; + } NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); return 0; } -static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; - void netxen_request_firmware(struct netxen_adapter *adapter) { u32 capability, flashed_ver; - int fw_type; + u8 fw_type; struct pci_dev *pdev = adapter->pdev; int rc = 0; @@ -830,6 +899,8 @@ request_mn: netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&flashed_ver); + flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); + if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); if (capability & NX_PEG_TUNE_MN_PRESENT) { @@ -838,6 +909,10 @@ request_mn: } } + fw_type = NX_FLASH_ROMIMAGE; + adapter->fw = NULL; + goto done; + request_fw: rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); if (rc != 0) { @@ -846,6 +921,7 @@ request_fw: goto request_mn; } + fw_type = NX_FLASH_ROMIMAGE; adapter->fw = NULL; goto done; } @@ -859,16 +935,13 @@ request_fw: goto request_mn; } + fw_type = NX_FLASH_ROMIMAGE; adapter->fw = NULL; goto done; } done: - if (adapter->fw) - dev_info(&pdev->dev, "loading firmware from file %s\n", - fw_name[fw_type]); - else - dev_info(&pdev->dev, "loading firmware from flash\n"); + adapter->fw_type = fw_type; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2919a2d12bf..27539ddf94c 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -718,6 +718,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) if (request_fw) netxen_request_firmware(adapter); + err = netxen_need_fw_reset(adapter); + if (err <= 0) + return err; + if (first_boot != 0x55555555) { NXWR32(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 8c1f6988f39..89f7b2ad523 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -105,7 +105,7 @@ IVc. Errata static char version[] __devinitdata = KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" -KERN_INFO " Support available from http://foo.com/bar/baz.html\n"; +" Support available from http://foo.com/bar/baz.html\n"; /* define to 1 to enable PIO instead of MMIO */ #undef USE_IO_OPS diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index f51944b28cf..06618af1a46 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -298,14 +298,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) strcpy(info->node.dev_name, dev->name); - printk(KERN_INFO "%s: port %#3lx, irq %d,", - dev->name, dev->base_addr, dev->irq); - printk (" mmio %#5lx,", (u_long)ti->mmio); - printk (" sram %#5lx,", (u_long)ti->sram_base << 12); - printk ("\n" KERN_INFO " hwaddr="); - for (i = 0; i < TR_ALEN; i++) - printk("%02X", dev->dev_addr[i]); - printk("\n"); + printk(KERN_INFO + "%s: port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", + dev->name, dev->base_addr, dev->irq, + (u_long)ti->mmio, (u_long)(ti->sram_base << 12), + dev->dev_addr); return 0; cs_failed: diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 02ef63ed1f9..36de91baf23 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1425,15 +1425,12 @@ static void BuildLAF(int *ladrf, int *adr) ladrf[byte] |= (1 << (hashcode & 7)); #ifdef PCMCIA_DEBUG - if (pc_debug > 2) { - printk(KERN_DEBUG " adr ="); - for (i = 0; i < 6; i++) - printk(" %02X", adr[i]); - printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]" - " =", hashcode); - for (i = 0; i < 8; i++) - printk(" %02X", ladrf[i]); - printk("\n"); + if (pc_debug > 2) + printk(KERN_DEBUG " adr =%pM\n", adr); + printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode); + for (i = 0; i < 8; i++) + printk(KERN_CONT " %02X", ladrf[i]); + printk(KERN_CONT "\n"); } #endif } /* BuildLAF */ diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 652a3688836..9ef1c1bfa83 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826), PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 1c35e1d637a..28368157dac 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -485,7 +485,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, &new_ring_dma_addr); if (new_tx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Consistent memory allocation failed.\n", dev->name); return; @@ -496,7 +496,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_dma_addr_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_tx_ring; } @@ -505,7 +505,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_skb_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_lists; } @@ -563,7 +563,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, &new_ring_dma_addr); if (new_rx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Consistent memory allocation failed.\n", dev->name); return; @@ -574,7 +574,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_dma_addr_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_rx_ring; } @@ -583,7 +583,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_skb_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_lists; } @@ -1766,38 +1766,38 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) /* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) { i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i); + printk(KERN_INFO " tx_start_pt(0x%04x):", i); switch (i >> 10) { case 0: - printk(" 20 bytes,"); + printk(KERN_CONT " 20 bytes,"); break; case 1: - printk(" 64 bytes,"); + printk(KERN_CONT " 64 bytes,"); break; case 2: - printk(" 128 bytes,"); + printk(KERN_CONT " 128 bytes,"); break; case 3: - printk("~220 bytes,"); + printk(KERN_CONT "~220 bytes,"); break; } i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(" BCR18(%x):", i & 0xffff); + printk(KERN_CONT " BCR18(%x):", i & 0xffff); if (i & (1 << 5)) - printk("BurstWrEn "); + printk(KERN_CONT "BurstWrEn "); if (i & (1 << 6)) - printk("BurstRdEn "); + printk(KERN_CONT "BurstRdEn "); if (i & (1 << 7)) - printk("DWordIO "); + printk(KERN_CONT "DWordIO "); if (i & (1 << 11)) - printk("NoUFlow "); + printk(KERN_CONT "NoUFlow "); i = a->read_bcr(ioaddr, 25); - printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8); + printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 26); - printk(" SRAM_BND=0x%04x,", i << 8); + printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 27); if (i & (1 << 14)) - printk("LowLatRx"); + printk(KERN_CONT "LowLatRx"); } } @@ -1996,7 +1996,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) &lp->tx_ring_dma_addr); if (lp->tx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; @@ -2008,7 +2008,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) &lp->rx_ring_dma_addr); if (lp->rx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; @@ -2018,7 +2018,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->tx_dma_addr) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2027,7 +2027,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->rx_dma_addr) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2036,7 +2036,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->tx_skbuff) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2045,7 +2045,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->rx_skbuff) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 61755cbd978..eda94fcd406 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -928,13 +928,32 @@ static void phy_state_machine(struct work_struct *work) * Otherwise, it's 0, and we're * still waiting for AN */ if (err > 0) { - phydev->state = PHY_RUNNING; + err = phy_read_status(phydev); + if (err) + break; + + if (phydev->link) { + phydev->state = PHY_RUNNING; + netif_carrier_on(phydev->attached_dev); + } else + phydev->state = PHY_NOLINK; + phydev->adjust_link(phydev->attached_dev); } else { phydev->state = PHY_AN; phydev->link_timeout = PHY_AN_TIMEOUT; } - } else - phydev->state = PHY_RUNNING; + } else { + err = phy_read_status(phydev); + if (err) + break; + + if (phydev->link) { + phydev->state = PHY_RUNNING; + netif_carrier_on(phydev->attached_dev); + } else + phydev->state = PHY_NOLINK; + phydev->adjust_link(phydev->attached_dev); + } break; } diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 156e02e8905..6ed5317ab1c 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1607,6 +1607,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_mb_about_fw(struct ql_adapter *qdev); +void ql_link_on(struct ql_adapter *qdev); +void ql_link_off(struct ql_adapter *qdev); #if 1 #define QL_ALL_DUMP diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 37c99fe7977..eb6a9ee640e 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -59,7 +59,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames); cqicb->flags = FLAGS_LI; - status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { QPRINTK(qdev, IFUP, ERR, @@ -82,7 +82,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames); cqicb->flags = FLAGS_LI; - status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { QPRINTK(qdev, IFUP, ERR, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 90d1f76c0e8..5768af17f16 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -214,6 +214,10 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, return -ENOMEM; } + status = ql_sem_spinlock(qdev, SEM_ICB_MASK); + if (status) + return status; + status = ql_wait_cfg(qdev, bit); if (status) { QPRINTK(qdev, IFUP, ERR, @@ -221,12 +225,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, goto exit; } - status = ql_sem_spinlock(qdev, SEM_ICB_MASK); - if (status) - goto exit; ql_write32(qdev, ICB_L, (u32) map); ql_write32(qdev, ICB_H, (u32) (map >> 32)); - ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ mask = CFG_Q_MASK | (bit << 16); value = bit | (q_id << CFG_Q_SHIFT); @@ -237,6 +237,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, */ status = ql_wait_cfg(qdev, bit); exit: + ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ pci_unmap_single(qdev->pdev, map, size, direction); return status; } @@ -412,6 +413,57 @@ exit: return status; } +/* Set or clear MAC address in hardware. We sometimes + * have to clear it to prevent wrong frame routing + * especially in a bonding environment. + */ +static int ql_set_mac_addr(struct ql_adapter *qdev, int set) +{ + int status; + char zero_mac_addr[ETH_ALEN]; + char *addr; + + if (set) { + addr = &qdev->ndev->dev_addr[0]; + QPRINTK(qdev, IFUP, DEBUG, + "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5]); + } else { + memset(zero_mac_addr, 0, ETH_ALEN); + addr = &zero_mac_addr[0]; + QPRINTK(qdev, IFUP, DEBUG, + "Clearing MAC address on %s\n", + qdev->ndev->name); + } + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; + status = ql_set_mac_addr_reg(qdev, (u8 *) addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + QPRINTK(qdev, IFUP, ERR, "Failed to init mac " + "address.\n"); + return status; +} + +void ql_link_on(struct ql_adapter *qdev) +{ + QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n", + qdev->ndev->name); + netif_carrier_on(qdev->ndev); + ql_set_mac_addr(qdev, 1); +} + +void ql_link_off(struct ql_adapter *qdev) +{ + QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n", + qdev->ndev->name); + netif_carrier_off(qdev->ndev); + ql_set_mac_addr(qdev, 0); +} + /* Get a specific frame routing value from the CAM. * Used for debug and reg dump. */ @@ -1628,7 +1680,7 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; tx_ring_desc = &tx_ring->q[mac_rsp->tid]; ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); - qdev->stats.tx_bytes += tx_ring_desc->map_cnt; + qdev->stats.tx_bytes += (tx_ring_desc->skb)->len; qdev->stats.tx_packets++; dev_kfree_skb(tx_ring_desc->skb); tx_ring_desc->skb = NULL; @@ -1660,13 +1712,13 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, /* Fire up a handler to reset the MPI processor. */ void ql_queue_fw_error(struct ql_adapter *qdev) { - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); } void ql_queue_asic_error(struct ql_adapter *qdev) { - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); ql_disable_interrupts(qdev); /* Clear adapter up bit to signal the recovery * process that it shouldn't kill the reset worker @@ -2104,7 +2156,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) } tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; mac_iocb_ptr = tx_ring_desc->queue_entry; - memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr)); + memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr)); mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; mac_iocb_ptr->tid = tx_ring_desc->index; @@ -2743,7 +2795,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) ql_init_tx_ring(qdev, tx_ring); - err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ, + err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ, (u16) tx_ring->wq_id); if (err) { QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); @@ -3008,7 +3060,7 @@ static int ql_start_rss(struct ql_adapter *qdev) int i; u8 *hash_id = (u8 *) ricb->hash_cq_id; - memset((void *)ricb, 0, sizeof(ricb)); + memset((void *)ricb, 0, sizeof(*ricb)); ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; ricb->flags = @@ -3030,7 +3082,7 @@ static int ql_start_rss(struct ql_adapter *qdev) QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); - status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); + status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); return status; @@ -3039,25 +3091,40 @@ static int ql_start_rss(struct ql_adapter *qdev) return status; } -/* Initialize the frame-to-queue routing. */ -static int ql_route_initialize(struct ql_adapter *qdev) +static int ql_clear_routing_entries(struct ql_adapter *qdev) { - int status = 0; - int i; + int i, status = 0; status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); if (status) return status; - /* Clear all the entries in the routing table. */ for (i = 0; i < 16; i++) { status = ql_set_routing_reg(qdev, i, 0, 0); if (status) { QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for CAM packets.\n"); - goto exit; + "Failed to init routing register for CAM " + "packets.\n"); + break; } } + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); + return status; +} + +/* Initialize the frame-to-queue routing. */ +static int ql_route_initialize(struct ql_adapter *qdev) +{ + int status = 0; + + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return status; + + /* Clear all the entries in the routing table. */ + status = ql_clear_routing_entries(qdev); + if (status) + goto exit; status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); if (status) { @@ -3096,14 +3163,15 @@ exit: int ql_cam_route_initialize(struct ql_adapter *qdev) { - int status; + int status, set; - status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); - if (status) - return status; - status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); - ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + /* If check if the link is up and use to + * determine if we are setting or clearing + * the MAC address in the CAM. + */ + set = ql_read32(qdev, STS); + set &= qdev->port_link_up; + status = ql_set_mac_addr(qdev, set); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); return status; @@ -3210,9 +3278,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev) { u32 value; int status = 0; - unsigned long end_jiffies = jiffies + - max((unsigned long)1, usecs_to_jiffies(30)); + unsigned long end_jiffies; + /* Clear all the entries in the routing table. */ + status = ql_clear_routing_entries(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n"); + return status; + } + + end_jiffies = jiffies + + max((unsigned long)1, usecs_to_jiffies(30)); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); do { @@ -3252,7 +3328,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) int i, status = 0; struct rx_ring *rx_ring; - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); /* Don't kill the reset worker thread if we * are in the process of recovery. @@ -3319,8 +3395,12 @@ static int ql_adapter_up(struct ql_adapter *qdev) } set_bit(QL_ADAPTER_UP, &qdev->flags); ql_alloc_rx_buffers(qdev); - if ((ql_read32(qdev, STS) & qdev->port_init)) - netif_carrier_on(qdev->ndev); + /* If the port is initialized and the + * link is up the turn on the carrier. + */ + if ((ql_read32(qdev, STS) & qdev->port_init) && + (ql_read32(qdev, STS) & qdev->port_link_up)) + ql_link_on(qdev); ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); netif_tx_start_all_queues(qdev->ndev); @@ -3346,11 +3426,6 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev) return -ENOMEM; } status = ql_request_irq(qdev); - if (status) - goto err_irq; - return status; -err_irq: - ql_free_mem_resources(qdev); return status; } @@ -3414,7 +3489,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; - memset((void *)tx_ring, 0, sizeof(tx_ring)); + memset((void *)tx_ring, 0, sizeof(*tx_ring)); tx_ring->qdev = qdev; tx_ring->wq_id = i; tx_ring->wq_len = qdev->tx_ring_size; @@ -3430,7 +3505,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) for (i = 0; i < qdev->rx_ring_count; i++) { rx_ring = &qdev->rx_ring[i]; - memset((void *)rx_ring, 0, sizeof(rx_ring)); + memset((void *)rx_ring, 0, sizeof(*rx_ring)); rx_ring->qdev = qdev; rx_ring->cq_id = i; rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ @@ -3789,7 +3864,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, int pos, err = 0; u16 val16; - memset((void *)qdev, 0, sizeof(qdev)); + memset((void *)qdev, 0, sizeof(*qdev)); err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "PCI device enable failed.\n"); @@ -3976,7 +4051,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, pci_disable_device(pdev); return err; } - netif_carrier_off(ndev); + ql_link_off(qdev); ql_display_dev_info(ndev); cards_found++; return 0; diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 71afbf8b9c5..6685bd97da9 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -238,7 +238,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) &qdev->mpi_port_cfg_work, 0); } - netif_carrier_on(qdev->ndev); + ql_link_on(qdev); } static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) @@ -251,7 +251,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) if (status) QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); } static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) @@ -849,7 +849,7 @@ void ql_mpi_idc_work(struct work_struct *work) case MB_CMD_PORT_RESET: case MB_CMD_SET_PORT_CFG: case MB_CMD_STOP_FW: - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); /* Signal the resulting link up AEN * that the frame routing and mac addr * needs to be set. diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index ed63d23a645..961b5397a53 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include <asm/processor.h> #define DRV_NAME "r6040" -#define DRV_VERSION "0.23" -#define DRV_RELDATE "05May2009" +#define DRV_VERSION "0.24" +#define DRV_RELDATE "08Jul2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ @@ -704,8 +704,11 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) /* Read MISR status and clear */ status = ioread16(ioaddr + MISR); - if (status == 0x0000 || status == 0xffff) + if (status == 0x0000 || status == 0xffff) { + /* Restore RDC MAC interrupt */ + iowrite16(misr, ioaddr + MIER); return IRQ_NONE; + } /* RX interrupt request */ if (status & RX_INTS) { diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b60639bd181..66067f9d91c 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1938,7 +1938,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) if (!res) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); iounmap(pdata->ioaddr); @@ -1976,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = -ENODEV; goto out_0; } - res_size = res->end - res->start + 1; + res_size = resource_size(res); irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { @@ -2104,7 +2104,7 @@ out_unmap_io_3: out_free_netdev_2: free_netdev(dev); out_release_io_1: - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); out_0: return retval; } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 838cce8b8ff..669253c7bd4 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -180,7 +180,7 @@ static int full_duplex[MAX_UNITS] = {0, }; /* These identify the driver base version and may not be removed. */ static const char version[] __devinitconst = KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" -KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; +" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 545f81b34ad..d1521c3875b 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1698,13 +1698,13 @@ static int netdev_close(struct net_device *dev) #ifdef __i386__ if (netif_msg_hw(np)) { - printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", + printk(KERN_DEBUG " Tx ring at %8.8x:\n", (int)(np->tx_ring_dma)); for (i = 0; i < TX_RING_SIZE; i++) - printk(" #%d desc. %4.4x %8.8x %8.8x.\n", + printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n", i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr, np->tx_ring[i].frag[0].length); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)(np->rx_ring_dma)); for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) { printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 0f78f99f9b2..7030bd5e984 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1132,7 +1132,9 @@ static int tsi108_get_mac(struct net_device *dev) } if (!is_valid_ether_addr(dev->dev_addr)) { - printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2); + printk(KERN_ERR + "%s: Invalid MAC address. word1: %08x, word2: %08x\n", + dev->name, word1, word2); return -EINVAL; } @@ -1201,8 +1203,8 @@ static void tsi108_set_rx_mode(struct net_device *dev) __set_bit(hash, &data->mc_hash[0]); } else { printk(KERN_ERR - "%s: got multicast address of length %d " - "instead of 6.\n", dev->name, + "%s: got multicast address of length %d instead of 6.\n", + dev->name, mc->dmi_addrlen); } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 81f054dbb88..ef49744a508 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -944,9 +944,10 @@ static void de_set_media (struct de_private *de) macmode &= ~FullDuplex; if (netif_msg_link(de)) { - printk(KERN_INFO "%s: set link %s\n" - KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" - KERN_INFO "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", + printk(KERN_INFO + "%s: set link %s\n" + "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" + "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", de->dev->name, media_name[media], de->dev->name, dr32(MacMode), dr32(SIAStatus), dr32(CSR13), dr32(CSR14), dr32(CSR15), diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 2abb5d3becc..99a63649f4f 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -570,16 +570,18 @@ static void tulip_tx_timeout(struct net_device *dev) (unsigned int)tp->rx_ring[i].buffer2, buf[0], buf[1], buf[2]); for (j = 0; buf[j] != 0xee && j < 1600; j++) - if (j < 100) printk(" %2.2x", buf[j]); - printk(" j=%d.\n", j); + if (j < 100) + printk(KERN_CONT " %2.2x", buf[j]); + printk(KERN_CONT " j=%d.\n", j); } printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); + printk(KERN_CONT " %8.8x", + (unsigned int)tp->rx_ring[i].status); + printk(KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); - printk("\n"); + printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status); + printk(KERN_CONT "\n"); } #endif diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 842b1a2c40d..0f15773dae5 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -142,7 +142,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static const char version[] __initconst = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker <becker@scyld.com>\n" - KERN_INFO " http://www.scyld.com/network/drivers.html\n"; + " http://www.scyld.com/network/drivers.html\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver"); @@ -939,7 +939,7 @@ static void tx_timeout(struct net_device *dev) printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)np->rx_ring[i].status); - printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); + printk(KERN_DEBUG" Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %8.8x", np->tx_ring[i].status); printk("\n"); @@ -1520,7 +1520,7 @@ static int netdev_close(struct net_device *dev) printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n", i, np->tx_ring[i].length, np->tx_ring[i].status, np->tx_ring[i].buffer1); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 11a0ba47b67..027f7aba26a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { struct tun_file *tfile = file->private_data; struct tun_struct *tun = __tun_get(tfile); - struct sock *sk = tun->sk; + struct sock *sk; unsigned int mask = 0; if (!tun) return POLLERR; + sk = tun->sk; + DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); poll_wait(file, &tun->socket.wait, wait); @@ -1324,20 +1326,22 @@ static int tun_chr_close(struct inode *inode, struct file *file) struct tun_file *tfile = file->private_data; struct tun_struct *tun; - - rtnl_lock(); tun = __tun_get(tfile); if (tun) { - DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); + struct net_device *dev = tun->dev; + + DBG(KERN_INFO "%s: tun_chr_close\n", dev->name); __tun_detach(tun); /* If desireable, unregister the netdevice. */ - if (!(tun->flags & TUN_PERSIST)) - unregister_netdevice(tun->dev); - + if (!(tun->flags & TUN_PERSIST)) { + rtnl_lock(); + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(dev); + rtnl_unlock(); + } } - rtnl_unlock(); tun = tfile->tun; if (tun) diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c index 223238de475..1ea1ef6c3b9 100644 --- a/drivers/net/wan/hd64570.c +++ b/drivers/net/wan/hd64570.c @@ -584,8 +584,9 @@ static void sca_dump_rings(struct net_device *dev) sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + printk(KERN_CONT "\n"); - printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " "last=%u %sactive", sca_inw(get_dmac_tx(port) + CDAL, card), sca_inw(get_dmac_tx(port) + EDAL, card), diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c index 497b003d723..f099c34a3ae 100644 --- a/drivers/net/wan/hd64572.c +++ b/drivers/net/wan/hd64572.c @@ -529,8 +529,9 @@ static void sca_dump_rings(struct net_device *dev) sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++) printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + printk(KERN_CONT "\n"); - printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " "last=%u %sactive", sca_inl(get_dmac_tx(port) + CDAL, card), sca_inl(get_dmac_tx(port) + EDAL, card), diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 3fb9dbc88a1..d14e95a08d6 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -326,11 +326,9 @@ sbni_pci_probe( struct net_device *dev ) } if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs) - printk( KERN_WARNING " WARNING: The PCI BIOS assigned " - "this PCI card to IRQ %d, which is unlikely " - "to work!.\n" - KERN_WARNING " You should use the PCI BIOS " - "setup to assign a valid IRQ line.\n", + printk( KERN_WARNING + " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n" + " You should use the PCI BIOS setup to assign a valid IRQ line.\n", pci_irq_line ); /* avoiding re-enable dual adapters */ diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index d26e7b48531..eb0337c4954 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -1,5 +1,6 @@ config ATH_COMMON tristate "Atheros Wireless Cards" + depends on WLAN_80211 depends on ATH5K || ATH9K || AR9170_USB source "drivers/net/wireless/ath/ath5k/Kconfig" diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b61a071788a..4ccf48e396d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } if (bf_next == NULL) { - INIT_LIST_HEAD(&bf_head); + /* + * Make sure the last desc is reclaimed if it + * not a holding desc. + */ + if (!bf_last->bf_stale) + list_move_tail(&bf->list, &bf_head); + else + INIT_LIST_HEAD(&bf_head); } else { ASSERT(!list_empty(bf_q)); list_move_tail(&bf->list, &bf_head); diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f580c2812d9..40448067e4c 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -648,6 +648,7 @@ struct b43_wl { u8 nr_devs; bool radiotap_enabled; + bool radio_enabled; /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6456afebdba..e71c8d9cd70 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3497,8 +3497,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); - if (!!conf->radio_enabled != phy->radio_on) { - if (conf->radio_enabled) { + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { b43_software_rfkill(dev, false); b43info(dev->wl, "Radio turned on by software\n"); if (!dev->radio_hw_enable) { @@ -4339,6 +4339,7 @@ static int b43_op_start(struct ieee80211_hw *hw) wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; wl->beacon_templates_virgin = 1; + wl->radio_enabled = 1; mutex_lock(&wl->mutex); @@ -4378,6 +4379,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) if (b43_status(dev) >= B43_STAT_STARTED) b43_wireless_core_stop(dev); b43_wireless_core_exit(dev); + wl->radio_enabled = 0; mutex_unlock(&wl->mutex); cancel_work_sync(&(wl->txpower_adjust_work)); @@ -4560,6 +4562,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) B43_WARN_ON(1); dev->phy.gmode = have_2ghz_phy; + dev->phy.radio_on = 1; tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; b43_wireless_core_reset(dev, tmp); diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 3cfc30307a2..6c3a74964ab 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -35,6 +35,7 @@ static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), + PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), PCMCIA_DEVICE_NULL, }; diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 77fda148ac4..038baa8869e 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -607,6 +607,7 @@ struct b43legacy_wl { u8 nr_devs; bool radiotap_enabled; + bool radio_enabled; /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index e5136fb65dd..c4973c1942b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2689,8 +2689,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Antennas for RX and management frame TX. */ b43legacy_mgmtframe_txantenna(dev, antenna_tx); - if (!!conf->radio_enabled != phy->radio_on) { - if (conf->radio_enabled) { + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { b43legacy_radio_turn_on(dev); b43legacyinfo(dev->wl, "Radio turned on by software\n"); if (!dev->radio_hw_enable) @@ -3441,6 +3441,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; wl->beacon_templates_virgin = 1; + wl->radio_enabled = 1; mutex_lock(&wl->mutex); @@ -3479,6 +3480,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) b43legacy_wireless_core_stop(dev); b43legacy_wireless_core_exit(dev); + wl->radio_enabled = 0; mutex_unlock(&wl->mutex); } @@ -3620,6 +3622,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) have_bphy = 1; dev->phy.gmode = (have_gphy || have_bphy); + dev->phy.radio_on = 1; tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; b43legacy_wireless_core_reset(dev, tmp); diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 1eccb6df46d..030401d367d 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -4,6 +4,15 @@ config IWM depends on CFG80211 select WIRELESS_EXT select FW_LOADER + help + The Intel Wireless Multicomm 3200 hardware is a combo + card with GPS, Bluetooth, WiMax and 802.11 radios. It + runs over SDIO and is typically found on Moorestown + based platform. This driver takes care of the 802.11 + part, which is a fullmac one. + + If you choose to build it as a module, it'll be called + iwmc3200wifi.ko. config IWM_DEBUG bool "Enable full debugging output in iwmc3200wifi" diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e789c6e9938..a111bda392e 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -418,6 +418,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, continue; if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || + !data->channel || !data2->channel || data->channel->center_freq != data2->channel->center_freq || !(data->group & data2->group)) continue; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b618bd14583..22ca122bd79 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -823,30 +823,30 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_info *range; unsigned long flags; - if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue))) + if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) return; - /* There used to be a check here to see if the SKB was on the - * TX queue or not. This can never happen because all SKBs we - * see here successfully went through p54_assign_address() - * which means the SKB is on the ->tx_queue. + /* + * don't try to free an already unlinked skb */ + if (unlikely((!skb->next) || (!skb->prev))) + return; spin_lock_irqsave(&priv->tx_queue.lock, flags); info = IEEE80211_SKB_CB(skb); range = (void *)info->rate_driver_data; - if (!skb_queue_is_first(&priv->tx_queue, skb)) { + if (skb->prev != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb)); + ni = IEEE80211_SKB_CB(skb->prev); mr = (struct p54_tx_info *)ni->rate_driver_data; } - if (!skb_queue_is_last(&priv->tx_queue, skb)) { + if (skb->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb)); + ni = IEEE80211_SKB_CB(skb->next); mr = (struct p54_tx_info *)ni->rate_driver_data; } __skb_unlink(skb, &priv->tx_queue); @@ -864,13 +864,15 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, unsigned long flags; spin_lock_irqsave(&priv->tx_queue.lock, flags); - skb_queue_walk(&priv->tx_queue, entry) { + entry = priv->tx_queue.next; + while (entry != (struct sk_buff *)&priv->tx_queue) { struct p54_hdr *hdr = (struct p54_hdr *) entry->data; if (hdr->req_id == req_id) { spin_unlock_irqrestore(&priv->tx_queue.lock, flags); return entry; } + entry = entry->next; } spin_unlock_irqrestore(&priv->tx_queue.lock, flags); return NULL; @@ -888,33 +890,36 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) int count, idx; spin_lock_irqsave(&priv->tx_queue.lock, flags); - skb_queue_walk(&priv->tx_queue, entry) { + entry = (struct sk_buff *) priv->tx_queue.next; + while (entry != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct p54_hdr *entry_hdr; struct p54_tx_data *entry_data; unsigned int pad = 0, frame_len; range = (void *)info->rate_driver_data; - if (range->start_addr != addr) + if (range->start_addr != addr) { + entry = entry->next; continue; + } - if (!skb_queue_is_last(&priv->tx_queue, entry)) { + if (entry->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, - entry)); + ni = IEEE80211_SKB_CB(entry->next); mr = (struct p54_tx_info *)ni->rate_driver_data; } __skb_unlink(entry, &priv->tx_queue); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); frame_len = entry->len; entry_hdr = (struct p54_hdr *) entry->data; entry_data = (struct p54_tx_data *) entry_hdr->data; - priv->tx_stats[entry_data->hw_queue].len--; + if (priv->tx_stats[entry_data->hw_queue].len) + priv->tx_stats[entry_data->hw_queue].len--; priv->stats.dot11ACKFailureCount += payload->tries - 1; + spin_unlock_irqrestore(&priv->tx_queue.lock, flags); /* * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are @@ -1164,21 +1169,23 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, } } - skb_queue_walk(&priv->tx_queue, entry) { + entry = priv->tx_queue.next; + while (left--) { u32 hole_size; info = IEEE80211_SKB_CB(entry); range = (void *)info->rate_driver_data; hole_size = range->start_addr - last_addr; if (!target_skb && hole_size >= len) { - target_skb = skb_queue_prev(&priv->tx_queue, entry); + target_skb = entry->prev; hole_size -= len; target_addr = last_addr; } largest_hole = max(largest_hole, hole_size); last_addr = range->end_addr; + entry = entry->next; } if (!target_skb && priv->rx_end - last_addr >= len) { - target_skb = skb_peek_tail(&priv->tx_queue); + target_skb = priv->tx_queue.prev; largest_hole = max(largest_hole, priv->rx_end - last_addr - len); if (!skb_queue_empty(&priv->tx_queue)) { info = IEEE80211_SKB_CB(target_skb); @@ -2084,6 +2091,7 @@ out: static void p54_stop(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; + struct sk_buff *skb; mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; @@ -2098,7 +2106,8 @@ static void p54_stop(struct ieee80211_hw *dev) p54_tx_cancel(dev, priv->cached_beacon); priv->stop(dev); - skb_queue_purge(&priv->tx_queue); + while ((skb = skb_dequeue(&priv->tx_queue))) + kfree_skb(skb); priv->cached_beacon = NULL; priv->tsf_high32 = priv->tsf_low32 = 0; mutex_unlock(&priv->conf_mutex); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index b10b0383dfa..698b11b1cad 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2427,11 +2427,10 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) #ifdef PCMCIA_DEBUG if (pc_debug > 3) { - int i; - printk(KERN_DEBUG "skb->data before untranslate"); - for (i = 0; i < 64; i++) - printk("%02x ", skb->data[i]); - printk("\n" KERN_DEBUG + print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ", + DUMP_PREFIX_NONE, 16, 1, + skb->data, 64, true); + printk(KERN_DEBUG "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, psnap->org[0], psnap->org[1], psnap->org[2]); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 6af706408ac..c6d300666ad 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3556,17 +3556,8 @@ wv_82593_config(struct net_device * dev) cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ #ifdef DEBUG_I82593_SHOW - { - u_char *c = (u_char *) &cfblk; - int i; - printk(KERN_DEBUG "wavelan_cs: config block:"); - for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++) - { - if((i % 16) == 0) printk("\n" KERN_DEBUG); - printk("%02x ", *c); - } - printk("\n"); - } + print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE, + 16, 1, &cfblk, sizeof(struct i82593_conf_block), false); #endif /* Copy the config block to the i82593 */ diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 14a19baff21..0e6e44689cc 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -38,7 +38,6 @@ static struct usb_device_id usb_ids[] = { /* ZD1211 */ { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, @@ -61,6 +60,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ + { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, @@ -87,6 +87,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 3c7a5053f1d..a07580138e8 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -109,7 +109,7 @@ static int gx_fix; /* These identify the driver base version and may not be removed. */ static const char version[] __devinitconst = KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n" - KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; + " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); @@ -700,12 +700,15 @@ static void yellowfin_tx_timeout(struct net_device *dev) int i; printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", yp->rx_ring[i].result_status); - printk("\n"KERN_WARNING" Tx ring %p: ", yp->tx_ring); + printk(KERN_CONT " %8.8x", + yp->rx_ring[i].result_status); + printk(KERN_CONT "\n"); + printk(KERN_WARNING" Tx ring %p: ", yp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs, - yp->tx_ring[i].result_status); - printk("\n"); + printk(KERN_CONT " %4.4x /%8.8x", + yp->tx_status[i].tx_errs, + yp->tx_ring[i].result_status); + printk(KERN_CONT "\n"); } /* If the hardware is found to hang regularly, we will update the code @@ -1216,20 +1219,20 @@ static int yellowfin_close(struct net_device *dev) #if defined(__i386__) if (yellowfin_debug > 2) { - printk("\n"KERN_DEBUG" Tx ring at %8.8llx:\n", + printk(KERN_DEBUG" Tx ring at %8.8llx:\n", (unsigned long long)yp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE*2; i++) - printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", + printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); for (i = 0; i < TX_RING_SIZE; i++) - printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n", + printk(KERN_DEBUG " #%d status %4.4x %4.4x %4.4x %4.4x.\n", i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); - printk("\n"KERN_DEBUG " Rx ring %8.8llx:\n", + printk(KERN_DEBUG " Rx ring %8.8llx:\n", (unsigned long long)yp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index e1f6ce03705..3c2270a8300 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -33,6 +33,7 @@ void oprofile_reset_stats(void) atomic_set(&oprofile_stats.sample_lost_no_mm, 0); atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); atomic_set(&oprofile_stats.event_lost_overflow, 0); + atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); } diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index c709ecc2b7f..0be1d50645a 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -101,7 +101,7 @@ static int configure_memory(const unsigned char *buf, printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(mem_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -191,7 +191,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(io_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -224,7 +224,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_BYTE: s=1; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outb((inb(get_16(buf+len+1) & get_8(buf+len+3)) | get_8(buf+len+4)), get_16(buf+len+1)); @@ -249,7 +249,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_DWORD: s=4; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outl((inl(get_16(buf+len+1) & get_32(buf+len+3)) | get_32(buf+len+7)), get_16(buf+len+1)); @@ -259,7 +259,7 @@ static int configure_port_init(const unsigned char *buf) break; default: - printk("\n" KERN_ERR "Invalid port init word %02x\n", c); + printk(KERN_ERR "Invalid port init word %02x\n", c); return 0; } @@ -297,7 +297,7 @@ static int configure_type_string(const unsigned char *buf) /* just skip past the type field */ len = get_8(buf); if (len > 80) { - printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); + printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); } return 1+len; @@ -398,7 +398,7 @@ static int parse_slot_config(int slot, } if (p0 + function_len < pos) { - printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match " + printk(KERN_ERR "eisa_enumerator: function %d length mis-match " "got %d, expected %d\n", num_func, pos-p0, function_len); res=-1; diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 844580489d4..5c5043f239c 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name) * @slot: pointer to the &struct hotplug_slot to register * @devnr: device number * @name: name registered with kobject core + * @owner: caller module owner + * @mod_name: caller module name * * Registers a hotplug slot with the pci hotplug subsystem, which will allow * userspace interaction to the slot. diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 53075424a43..ebc9b8dca88 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2117,6 +2117,47 @@ static int domain_add_dev_info(struct dmar_domain *domain, return 0; } +static int iommu_should_identity_map(struct pci_dev *pdev, int startup) +{ + if (iommu_identity_mapping == 2) + return IS_GFX_DEVICE(pdev); + + /* + * We want to start off with all devices in the 1:1 domain, and + * take them out later if we find they can't access all of memory. + * + * However, we can't do this for PCI devices behind bridges, + * because all PCI devices behind the same bridge will end up + * with the same source-id on their transactions. + * + * Practically speaking, we can't change things around for these + * devices at run-time, because we can't be sure there'll be no + * DMA transactions in flight for any of their siblings. + * + * So PCI devices (unless they're on the root bus) as well as + * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of + * the 1:1 domain, just in _case_ one of their siblings turns out + * not to be able to map all of memory. + */ + if (!pdev->is_pcie) { + if (!pci_is_root_bus(pdev->bus)) + return 0; + if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) + return 0; + } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + return 0; + + /* + * At boot time, we don't yet know if devices will be 64-bit capable. + * Assume that they will -- if they turn out not to be, then we can + * take them out of the 1:1 domain later. + */ + if (!startup) + return pdev->dma_mask > DMA_BIT_MASK(32); + + return 1; +} + static int iommu_prepare_static_identity_mapping(void) { struct pci_dev *pdev = NULL; @@ -2127,16 +2168,18 @@ static int iommu_prepare_static_identity_mapping(void) return -EFAULT; for_each_pci_dev(pdev) { - printk(KERN_INFO "IOMMU: identity mapping for device %s\n", - pci_name(pdev)); + if (iommu_should_identity_map(pdev, 1)) { + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", + pci_name(pdev)); - ret = domain_context_mapping(si_domain, pdev, - CONTEXT_TT_MULTI_LEVEL); - if (ret) - return ret; - ret = domain_add_dev_info(si_domain, pdev); - if (ret) - return ret; + ret = domain_context_mapping(si_domain, pdev, + CONTEXT_TT_MULTI_LEVEL); + if (ret) + return ret; + ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return ret; + } } return 0; @@ -2291,6 +2334,10 @@ int __init init_dmars(void) * identity mapping if iommu_identity_mapping is set. */ if (!iommu_pass_through) { +#ifdef CONFIG_DMAR_BROKEN_GFX_WA + if (!iommu_identity_mapping) + iommu_identity_mapping = 2; +#endif if (iommu_identity_mapping) iommu_prepare_static_identity_mapping(); /* @@ -2368,15 +2415,15 @@ error: return ret; } +/* Returns a number of VTD pages, but aligned to MM page size */ static inline unsigned long aligned_nrpages(unsigned long host_addr, size_t size) { host_addr &= ~PAGE_MASK; - host_addr += size + PAGE_SIZE - 1; - - return host_addr >> VTD_PAGE_SHIFT; + return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT; } +/* This takes a number of _MM_ pages, not VTD pages */ static struct iova *intel_alloc_iova(struct device *dev, struct dmar_domain *domain, unsigned long nrpages, uint64_t dma_mask) @@ -2443,16 +2490,24 @@ static int iommu_dummy(struct pci_dev *pdev) } /* Check if the pdev needs to go through non-identity map and unmap process.*/ -static int iommu_no_mapping(struct pci_dev *pdev) +static int iommu_no_mapping(struct device *dev) { + struct pci_dev *pdev; int found; + if (unlikely(dev->bus != &pci_bus_type)) + return 1; + + pdev = to_pci_dev(dev); + if (iommu_dummy(pdev)) + return 1; + if (!iommu_identity_mapping) - return iommu_dummy(pdev); + return 0; found = identity_mapping(pdev); if (found) { - if (pdev->dma_mask > DMA_BIT_MASK(32)) + if (iommu_should_identity_map(pdev, 0)) return 1; else { /* @@ -2469,9 +2524,12 @@ static int iommu_no_mapping(struct pci_dev *pdev) * In case of a detached 64 bit DMA device from vm, the device * is put into si_domain for identity mapping. */ - if (pdev->dma_mask > DMA_BIT_MASK(32)) { + if (iommu_should_identity_map(pdev, 0)) { int ret; ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return 0; + ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); if (!ret) { printk(KERN_INFO "64bit %s uses identity mapping\n", pci_name(pdev)); @@ -2480,7 +2538,7 @@ static int iommu_no_mapping(struct pci_dev *pdev) } } - return iommu_dummy(pdev); + return 0; } static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, @@ -2496,7 +2554,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, BUG_ON(dir == DMA_NONE); - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return paddr; domain = get_valid_domain_for_dev(pdev); @@ -2506,7 +2564,8 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, iommu = domain_get_iommu(domain); size = aligned_nrpages(paddr, size); - iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), + pdev->dma_mask); if (!iova) goto error; @@ -2635,7 +2694,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, struct iova *iova; struct intel_iommu *iommu; - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(dev)) return; domain = find_domain(pdev); @@ -2726,7 +2785,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, struct iova *iova; struct intel_iommu *iommu; - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return; domain = find_domain(pdev); @@ -2785,7 +2844,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne struct intel_iommu *iommu; BUG_ON(dir == DMA_NONE); - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); domain = get_valid_domain_for_dev(pdev); @@ -2797,7 +2856,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne for_each_sg(sglist, sg, nelems, i) size += aligned_nrpages(sg->offset, sg->length); - iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), + pdev->dma_mask); if (!iova) { sglist->dma_length = 0; return 0; @@ -3540,6 +3600,9 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, { struct dmar_domain *dmar_domain = domain->priv; + if (!size) + return; + dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, (iova + size - 1) >> VTD_PAGE_SHIFT); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d9f06fbfa0b..d986afb7032 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control) * reliably as devices without an INTx disable bit will then generate a * level IRQ which will never be cleared. */ -static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) { u32 mask_bits = desc->masked; if (!desc->msi_attrib.maskbit) - return; + return 0; mask_bits &= ~mask; mask_bits |= flag; pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); - desc->masked = mask_bits; + + return mask_bits; +} + +static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +{ + desc->masked = __msi_mask_irq(desc, mask, flag); } /* @@ -147,15 +153,21 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) * file. This saves a few milliseconds when initialising devices with lots * of MSI-X interrupts. */ -static void msix_mask_irq(struct msi_desc *desc, u32 flag) +static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) { u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; + PCI_MSIX_ENTRY_VECTOR_CTRL; mask_bits &= ~1; mask_bits |= flag; writel(mask_bits, desc->mask_base + offset); - desc->masked = mask_bits; + + return mask_bits; +} + +static void msix_mask_irq(struct msi_desc *desc, u32 flag) +{ + desc->masked = __msix_mask_irq(desc, flag); } static void msi_set_mask_bit(unsigned irq, u32 flag) @@ -188,9 +200,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) void __iomem *base = entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; - msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); + msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); + msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); + msg->data = readl(base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; int pos = entry->msi_attrib.pos; @@ -225,11 +237,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) base = entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; - writel(msg->address_lo, - base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(msg->address_hi, - base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); + writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); + writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); + writel(msg->data, base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; int pos = entry->msi_attrib.pos; @@ -385,6 +395,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) /* Configure MSI capability structure */ ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); if (ret) { + msi_mask_irq(entry, mask, ~mask); msi_free_irqs(dev); return ret; } @@ -439,8 +450,14 @@ static int msix_capability_init(struct pci_dev *dev, for (i = 0; i < nvec; i++) { entry = alloc_msi_entry(dev); - if (!entry) - break; + if (!entry) { + if (!i) + iounmap(base); + else + msi_free_irqs(dev); + /* No enough memory. Don't try again */ + return -ENOMEM; + } j = entries[i].entry; entry->msi_attrib.is_msix = 1; @@ -487,7 +504,7 @@ static int msix_capability_init(struct pci_dev *dev, set_irq_msi(entry->irq, entry); j = entries[i].entry; entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); + PCI_MSIX_ENTRY_VECTOR_CTRL); msix_mask_irq(entry, 1); i++; } @@ -611,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev) pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; + /* Return the device with MSI unmasked as initial states */ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); mask = msi_capable_mask(ctrl); - msi_mask_irq(desc, mask, ~mask); + /* Keep cached state to be restored */ + __msi_mask_irq(desc, mask, ~mask); /* Restore dev->irq to its default pin-assertion irq */ dev->irq = desc->msi_attrib.default_irq; @@ -653,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev) list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { if (entry->msi_attrib.is_msix) { - msix_mask_irq(entry, 1); if (list_is_last(&entry->list, &dev->msi_list)) iounmap(entry->mask_base); } @@ -741,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev) void pci_msix_shutdown(struct pci_dev* dev) { + struct msi_desc *entry; + if (!pci_msi_enable || !dev || !dev->msix_enabled) return; + /* Return the device with MSI-X masked as initial states */ + list_for_each_entry(entry, &dev->msi_list, list) { + /* Keep cached states to be restored */ + __msix_mask_irq(entry, 1); + } + msix_set_enable(dev, 0); pci_intx_for_msi(dev, 1); dev->msix_enabled = 0; diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index a0662842550..de27c1cb5a2 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,11 +6,11 @@ #ifndef MSI_H #define MSI_H -#define PCI_MSIX_ENTRY_SIZE 16 -#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 -#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 -#define PCI_MSIX_ENTRY_DATA_OFFSET 8 -#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 #define msi_control_reg(base) (base + PCI_MSI_FLAGS) #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6c93af5ced1..dbd0f947f49 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev) * * Perform INTx swizzling for a device behind one level of bridge. This is * required by section 9.1 of the PCI-to-PCI bridge specification for devices - * behind bridges on add-in cards. + * behind bridges on add-in cards. For devices with ARI enabled, the slot + * number is always 0 (see the Implementation Note in section 2.2.8.1 of + * the PCI Express Base Specification, Revision 2.1) */ u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) { - return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; + int slot; + + if (pci_ari_enabled(dev->bus)) + slot = 0; + else + slot = PCI_SLOT(dev->devfn); + + return (((pin - 1) + slot) % 4) + 1; } int @@ -2171,7 +2180,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) u16 ctrl; struct pci_dev *pdev; - if (dev->subordinate) + if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) return -ENOTTY; list_for_each_entry(pdev, &dev->bus->devices, bus_list) diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c index ece97df4df6..a928d8ab6bd 100644 --- a/drivers/pci/pcie/aer/ecrc.c +++ b/drivers/pci/pcie/aer/ecrc.c @@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev) disable_ecrc_checking(dev); break; case ECRC_POLICY_ON: - enable_ecrc_checking(dev);; + enable_ecrc_checking(dev); break; default: return; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 56552d74abe..06b96562396 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); +/* ALi loses some register settings that we cannot then restore */ +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3); +/* VIA comes back fine but we need to keep it alive or ACPI GTM failures + occur when mode detecting */ +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3); /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index eddb0748b0e..8c02b6c53bd 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot); #include <linux/pci_hotplug.h> /** * pci_hp_create_link - create symbolic link to the hotplug driver module. - * @slot: struct pci_slot + * @pci_slot: struct pci_slot * * Helper function for pci_hotplug_core.c to create symbolic link to * the hotplug driver module. @@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link); /** * pci_hp_remove_link - remove symbolic link to the hotplug driver module. - * @slot: struct pci_slot + * @pci_slot: struct pci_slot * * Helper function for pci_hotplug_core.c to remove symbolic link to * the hotplug driver module. diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 9ad97ea836e..8eb04230fec 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -472,7 +472,8 @@ static int __init init_tcic(void) init_timer(&poll_timer); /* Build interrupt mask */ - printk(", %d sockets\n" KERN_INFO " irq list (", sockets); + printk(KERN_CONT ", %d sockets\n", sockets); + printk(KERN_INFO " irq list ("); if (irq_list_count == 0) mask = irq_mask; else diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 4ac2311c00a..ca508564a18 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void) static int hp_wmi_set_block(void *data, bool blocked) { unsigned long b = (unsigned long) data; - int query = BIT(b + 8) | ((!!blocked) << b); + int query = BIT(b + 8) | ((!blocked) << b); return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); } diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 32b27739ec2..713f7bf5afb 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -283,7 +283,7 @@ static void ds1374_work(struct work_struct *work) stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); if (stat < 0) - return; + goto unlock; if (stat & DS1374_REG_SR_AF) { stat &= ~DS1374_REG_SR_AF; @@ -302,7 +302,7 @@ static void ds1374_work(struct work_struct *work) out: if (!ds1374->exiting) enable_irq(client->irq); - +unlock: mutex_unlock(&ds1374->mutex); } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0471f880048..4240b05aef6 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2826,8 +2826,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd) */ local_irq_restore(flags); - printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" - KERN_INFO " before abortion\n", HOSTNO); + printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); /* Maybe it is sufficient just to release the ST-DMA lock... (if * possible at all) At least, we should check if the lock could be diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index b12ad7c7c67..18735b39b3d 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -75,8 +75,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd * int i; printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); for (i = 0; i < cmd->cmd_len; ++i) - printk(" %.2x", cmd->cmnd[i]); - printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + printk(KERN_CONT " %.2x", cmd->cmnd[i]); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd)); } #endif diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ef142fd47a8..9230402c45a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -619,7 +619,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (strcmp(current->comm, cmd) && printk_ratelimit()) { printk(KERN_WARNING "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--" - "guessing data in;\n" KERN_WARNING " " + "guessing data in;\n " "program %s not setting count and/or reply_len properly\n", old_hdr.reply_len - (int)SZ_SG_HEADER, input_size, (unsigned int) cmnd[0], @@ -1656,6 +1656,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) md->nr_entries = req_schp->k_use_sg; md->offset = 0; md->null_mapped = hp->dxferp ? 0 : 1; + if (dxfer_dir == SG_DXFER_TO_FROM_DEV) + md->from_user = 1; + else + md->from_user = 0; } if (iov_count) { diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index bcaba86060a..75da6e58ce5 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2860,8 +2860,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) */ local_irq_restore(flags); - printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" - KERN_INFO " before abortion\n", HOSTNO); + printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); return SCSI_ABORT_NOT_RUNNING; } diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 6160e03f410..e7108e75653 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -60,11 +60,12 @@ struct serial_private { static void moan_device(const char *str, struct pci_dev *dev) { - printk(KERN_WARNING "%s: %s\n" - KERN_WARNING "Please send the output of lspci -vv, this\n" - KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" - KERN_WARNING "manufacturer and name of serial board or\n" - KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n", + printk(KERN_WARNING + "%s: %s\n" + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" + "modem board to rmk+serial@arm.linux.org.uk.\n", pci_name(dev), str, dev->vendor, dev->device, dev->subsystem_vendor, dev->subsystem_device); } diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 12bd64684f1..8e2feb56334 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -716,16 +716,16 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); /* Tx Interrupt */ - if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE)) + if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE)) ret = sci_tx_interrupt(irq, ptr); /* Rx Interrupt */ - if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE)) + if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE)) ret = sci_rx_interrupt(irq, ptr); /* Error Interrupt */ - if ((ssr_status & 0x0080) && err_enabled) + if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) ret = sci_er_interrupt(irq, ptr); /* Break Interrupt */ - if ((ssr_status & 0x0010) && err_enabled) + if ((ssr_status & SCxSR_BRK(port)) && err_enabled) ret = sci_br_interrupt(irq, ptr); return ret; diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbfadbac67e..100e7a5c5ea 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) ssb_printk("."); err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); if (err) { - ssb_printk("\n" KERN_NOTICE PFX + ssb_printk(KERN_NOTICE PFX "Failed to write to SPROM.\n"); failed = 1; break; @@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) } err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); if (err) { - ssb_printk("\n" KERN_NOTICE PFX + ssb_printk(KERN_NOTICE PFX "Could not disable SPROM write access.\n"); failed = 1; } @@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, sprom->board_rev = tuple.TupleData[1]; break; case SSB_PCMCIA_CIS_PA: - GOTO_ERROR_ON(tuple.TupleDataLen != 9, + GOTO_ERROR_ON((tuple.TupleDataLen != 9) && + (tuple.TupleDataLen != 10), "pa tpl size"); sprom->pa0b0 = tuple.TupleData[1] | ((u16)tuple.TupleData[2] << 8); @@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; break; case SSB_PCMCIA_CIS_BFLAGS: - GOTO_ERROR_ON(tuple.TupleDataLen != 3, + GOTO_ERROR_ON((tuple.TupleDataLen != 3) && + (tuple.TupleDataLen != 5), "bfl tpl size"); sprom->boardflags_lo = tuple.TupleData[1] | ((u16)tuple.TupleData[2] << 8); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ce3f453f02e..95ccfa0b9fc 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -648,7 +648,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) struct urb *urb; int length; unsigned long flags; - char buffer[4]; /* Any root hubs with > 31 ports? */ + char buffer[6]; /* Any root hubs with > 31 ports? */ if (unlikely(!hcd->rh_registered)) return; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f8d9045d668..0f7a30b7d2d 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages) return -ENOMEM; } map[n].ptr = (unsigned char *) vaddr; - map[n].pg = virt_to_page(vaddr); + map[n].pg = virt_to_page((void *) vaddr); } return 0; } diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index fb8163d181a..a21efcd10b7 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -226,9 +226,10 @@ static int clcdfb_set_par(struct fb_info *info) clcdfb_enable(fb, regs.cntl); #ifdef DEBUG - printk(KERN_INFO "CLCD: Registers set to\n" - KERN_INFO " %08x %08x %08x %08x\n" - KERN_INFO " %08x %08x %08x %08x\n", + printk(KERN_INFO + "CLCD: Registers set to\n" + " %08x %08x %08x %08x\n" + " %08x %08x %08x %08x\n", readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 497ff8af03e..8cd279be74e 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2405,6 +2405,9 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) return 0; } +/* fbhw->encode_fix() must be called with fb_info->mm_lock held + * if it is called after the register_framebuffer() - not a case here + */ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) { struct atafb_par par; @@ -2414,9 +2417,7 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) if (err) return err; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - mutex_lock(&info->mm_lock); err = fbhw->encode_fix(fix, &par); - mutex_unlock(&info->mm_lock); return err; } diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index cb88394ba99..da05f0801bb 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -261,6 +261,9 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) /** * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory * @sinfo: the frame buffer to allocate memory for + * + * This function is called only from the atmel_lcdfb_probe() + * so no locking by fb_info->mm_lock around smem_len setting is needed. */ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) { @@ -270,9 +273,7 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) smem_len = (var->xres_virtual * var->yres_virtual * ((var->bits_per_pixel + 7) / 8)); - mutex_lock(&info->mm_lock); info->fix.smem_len = max(smem_len, sinfo->smem_len); - mutex_unlock(&info->mm_lock); info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0bf2190928d..72d68b3dc47 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1223,12 +1223,6 @@ static int __devinit install_fb(struct fb_info *info) return -EINVAL; } - if (fsl_diu_set_par(info)) { - printk(KERN_ERR "fb_set_par failed"); - fb_dealloc_cmap(&info->cmap); - return -EINVAL; - } - if (register_framebuffer(info) < 0) { printk(KERN_ERR "register_framebuffer failed"); unmap_video_memory(info); diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 020db7fc915..e7116a6d82d 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -44,9 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = { .accel = FB_ACCEL_NONE, }; -static u32 pseudo_palette[16]; -static struct fb_info fb_info; - static inline void hitfb_accel_wait(void) { while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; @@ -331,6 +328,8 @@ static struct fb_ops hitfb_ops = { static int __init hitfb_probe(struct platform_device *dev) { unsigned short lcdclor, ldr3, ldvndr; + struct fb_info *info; + int ret; if (fb_get_options("hitfb", NULL)) return -ENODEV; @@ -384,32 +383,53 @@ static int __init hitfb_probe(struct platform_device *dev) break; } - fb_info.fbops = &hitfb_ops; - fb_info.var = hitfb_var; - fb_info.fix = hitfb_fix; - fb_info.pseudo_palette = pseudo_palette; - fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); + if (unlikely(!info)) + return -ENOMEM; + + info->fbops = &hitfb_ops; + info->var = hitfb_var; + info->fix = hitfb_fix; + info->pseudo_palette = info->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; - fb_info.screen_base = (void *)hitfb_fix.smem_start; + info->screen_base = (void *)hitfb_fix.smem_start; - fb_alloc_cmap(&fb_info.cmap, 256, 0); + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (unlikely(ret < 0)) + goto err_fb; - if (register_framebuffer(&fb_info) < 0) - return -EINVAL; + ret = register_framebuffer(info); + if (unlikely(ret < 0)) + goto err; + + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + info->node, info->fix.id); + return 0; + +err: + fb_dealloc_cmap(&info->cmap); +err_fb: + framebuffer_release(info); + return ret; } static int __exit hitfb_remove(struct platform_device *dev) { - return unregister_framebuffer(&fb_info); + struct fb_info *info = platform_get_drvdata(dev); + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + + return 0; } -#ifdef CONFIG_PM -static int hitfb_suspend(struct platform_device *dev, pm_message_t state) +static int hitfb_suspend(struct device *dev) { u16 v; @@ -421,7 +441,7 @@ static int hitfb_suspend(struct platform_device *dev, pm_message_t state) return 0; } -static int hitfb_resume(struct platform_device *dev) +static int hitfb_resume(struct device *dev) { u16 v; @@ -435,17 +455,19 @@ static int hitfb_resume(struct platform_device *dev) return 0; } -#endif + +static struct dev_pm_ops hitfb_dev_pm_ops = { + .suspend = hitfb_suspend, + .resume = hitfb_resume, +}; static struct platform_driver hitfb_driver = { .probe = hitfb_probe, .remove = __exit_p(hitfb_remove), -#ifdef CONFIG_PM - .suspend = hitfb_suspend, - .resume = hitfb_resume, -#endif .driver = { .name = "hitfb", + .owner = THIS_MODULE, + .pm = &hitfb_dev_pm_ops, }, }; diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 71960672d72..5743ea25e81 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -2060,8 +2060,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, fb_var_to_videomode(&mode, &info->var); fb_add_videomode(&mode, &info->modelist); - encode_fix(&info->fix, info); - + i810fb_init_ringbuffer(info); err = register_framebuffer(info); diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 0ce3b0a8979..a74e5da17aa 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -454,9 +454,9 @@ static void DAC1064_restore_2(WPMINFO2) { dprintk(KERN_DEBUG "DAC1064regs "); for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); - if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); + if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); } - dprintk("\n" KERN_DEBUG "DAC1064clk "); + dprintk(KERN_DEBUG "DAC1064clk "); for (i = 0; i < 6; i++) dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); dprintk("\n"); diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 13524821e24..4e825112a60 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -651,9 +651,9 @@ static void Ti3026_restore(WPMINFO2) { dprintk(KERN_DEBUG "3026DACregs "); for (i = 0; i < 21; i++) { dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); - if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); + if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); } - dprintk("\n" KERN_DEBUG "DACclk "); + dprintk(KERN_DEBUG "DACclk "); for (i = 0; i < 6; i++) dprintk("C%02X=%02X ", i, hw->DACclk[i]); dprintk("\n"); diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 59c3a2e1491..0c1049b308b 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1876,7 +1876,6 @@ static int initMatrox2(WPMINFO struct board* b){ } matroxfb_init_fix(PMINFO2); ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); - matroxfb_update_fix(PMINFO2); /* Normalize values (namely yres_virtual) */ matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 909e10a1189..ebcb5c6b496 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -289,16 +289,18 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { #undef m2info } +/* + * This function is called before the register_framebuffer so + * no locking is needed. + */ static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; strcpy(fix->id, "MATROX DH"); - mutex_lock(&m2info->fbcon.mm_lock); fix->smem_start = m2info->video.base; fix->smem_len = m2info->video.len_usable; - mutex_unlock(&m2info->fbcon.mm_lock); fix->ypanstep = 1; fix->ywrapstep = 0; fix->xpanstep = 8; /* TBD */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 567fb944bd2..f8778cde218 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1365,11 +1365,6 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) init_completion(&mx3fbi->flip_cmpl); disable_irq(ichan->eof_irq); dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); - ret = mx3fb_set_par(fbi); - if (ret < 0) - goto esetpar; - - mx3fb_blank(FB_BLANK_UNBLANK, fbi); dev_info(dev, "registered, using mode %s\n", fb_mode); diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 43680e54542..bb63c07e13d 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /** * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. + * @id: window id. * @sfb: The hardware state. * @pixclock: The pixel clock wanted, in picoseconds. * * Given the specified pixel clock, work out the necessary divider to get * close to the output frequency. */ -static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) +static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) { + struct s3c_fb_pd_win *win = sfb->pdata->win[id]; unsigned long clk = clk_get_rate(sfb->bus_clk); - unsigned long long tmp; unsigned int result; - tmp = (unsigned long long)clk; - tmp *= pixclk; - - do_div(tmp, 1000000000UL); - result = (unsigned int)tmp / 1000; + pixclk *= win->win_mode.refresh; + result = clk / pixclk; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", pixclk, clk, result, clk / result); @@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info) struct s3c_fb *sfb = win->parent; void __iomem *regs = sfb->regs; int win_no = win->index; + u32 osdc_data = 0; u32 data; u32 pagewidth; int clkdiv; @@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* use window 0 as the basis for the lcd output timings */ if (win_no == 0) { - clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); + clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); data = sfb->pdata->vidcon0; data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); @@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info) data = var->xres * var->yres; - u32 osdc_data = 0; - osdc_data = VIDISD14C_ALPHA1_R(0xf) | VIDISD14C_ALPHA1_G(0xf) | VIDISD14C_ALPHA1_B(0xf); diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 65806ec3313..98fb82f1161 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -31,7 +31,7 @@ struct sh_mobile_lcdc_chan { unsigned long enabled; /* ME and SE in LDCNT2R */ struct sh_mobile_lcdc_chan_cfg cfg; u32 pseudo_palette[PALETTE_NR]; - struct fb_info info; + struct fb_info *info; dma_addr_t dma_handle; struct fb_deferred_io defio; struct scatterlist *sglist; @@ -435,22 +435,22 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) /* set bpp format in PKF[4:0] */ tmp = lcdc_read_chan(ch, LDDFR); tmp &= ~(0x0001001f); - tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0; + tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; lcdc_write_chan(ch, LDDFR, tmp); /* point out our frame buffer */ - lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start); + lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); /* set line size */ - lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length); + lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); /* setup deferred io if SYS bus */ tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; if (ch->ldmt1r_value & (1 << 12) && tmp) { ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; ch->defio.delay = msecs_to_jiffies(tmp); - ch->info.fbdefio = &ch->defio; - fb_deferred_io_init(&ch->info); + ch->info->fbdefio = &ch->defio; + fb_deferred_io_init(ch->info); /* one-shot mode */ lcdc_write_chan(ch, LDSM1R, 1); @@ -496,12 +496,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) * flush frame, and wait for frame end interrupt * clean up deferred io and enable clock */ - if (ch->info.fbdefio) { + if (ch->info->fbdefio) { ch->frame_end = 0; - schedule_delayed_work(&ch->info.deferred_work, 0); + schedule_delayed_work(&ch->info->deferred_work, 0); wait_event(ch->frame_end_wait, ch->frame_end); - fb_deferred_io_cleanup(&ch->info); - ch->info.fbdefio = NULL; + fb_deferred_io_cleanup(ch->info); + ch->info->fbdefio = NULL; sh_mobile_lcdc_clk_on(priv); } @@ -805,9 +805,16 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); for (i = 0; i < j; i++) { - info = &priv->ch[i].info; cfg = &priv->ch[i].cfg; + priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); + if (!priv->ch[i].info) { + dev_err(&pdev->dev, "unable to allocate fb_info\n"); + error = -ENOMEM; + break; + } + + info = priv->ch[i].info; info->fbops = &sh_mobile_lcdc_ops; info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; @@ -860,7 +867,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) for (i = 0; i < j; i++) { struct sh_mobile_lcdc_chan *ch = priv->ch + i; - info = &ch->info; + info = ch->info; if (info->fbdefio) { priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * @@ -903,15 +910,15 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) int i; for (i = 0; i < ARRAY_SIZE(priv->ch); i++) - if (priv->ch[i].info.dev) - unregister_framebuffer(&priv->ch[i].info); + if (priv->ch[i].info->dev) + unregister_framebuffer(priv->ch[i].info); sh_mobile_lcdc_stop(priv); for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { - info = &priv->ch[i].info; + info = priv->ch[i].info; - if (!info->device) + if (!info || !info->device) continue; if (priv->ch[i].sglist) @@ -920,6 +927,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, info->fix.smem_len, info->screen_base, priv->ch[i].dma_handle); fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); } if (priv->dot_clk) diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index fd33455389b..4a067f0d0ce 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -6367,7 +6367,6 @@ error_3: vfree(ivideo->bios_abase); sis_fb_info->fix = ivideo->sisfb_fix; sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; sis_fb_info->fbops = &sisfb_ops; - sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); sis_fb_info->pseudo_palette = ivideo->pseudo_palette; fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 16d4f4c7d52..924d7946278 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1540,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb, if (ret) dev_err(info->dev, "check_var() failed on initial setup?\n"); - /* ensure we've activated our new configuration */ - (fb->fbops->fb_set_par)(fb); - return 0; } diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index eec9dcb7f59..6120f0c526f 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1115,10 +1115,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) if the device name contains the string "DX" and tell the user how to reconfigure the card. */ if (strstr(sti->outptr.dev_name, "DX")) { - printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " - "support '%s' in double-buffer mode.\n" - KERN_WARNING "WARNING: Please disable the double-buffer mode " - "in IPL menu (the PARISC-BIOS).\n", + printk(KERN_WARNING +"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" +"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", sti->outptr.dev_name); goto out_err0; } diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 8a141c2c637..2376f688ec8 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -748,8 +748,6 @@ int __init w100fb_probe(struct platform_device *pdev) goto out; } - w100fb_set_par(info); - if (register_framebuffer(info) < 0) { err = -EINVAL; goto out; diff --git a/drivers/vlynq/Kconfig b/drivers/vlynq/Kconfig index f6542211db4..a9efb162532 100644 --- a/drivers/vlynq/Kconfig +++ b/drivers/vlynq/Kconfig @@ -13,7 +13,7 @@ config VLYNQ config VLYNQ_DEBUG bool "VLYNQ bus debug" - depends on VLYNQ && KERNEL_DEBUG + depends on VLYNQ && DEBUG_KERNEL help Turn on VLYNQ bus debugging. diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index 7335433b067..f05d2a36836 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c @@ -76,7 +76,7 @@ struct vlynq_regs { u32 int_device[8]; }; -#ifdef VLYNQ_DEBUG +#ifdef CONFIG_VLYNQ_DEBUG static void vlynq_dump_regs(struct vlynq_device *dev) { int i; diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 5c7011cda6a..751c003864a 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -161,7 +161,7 @@ static long bcm47xx_wdt_ioctl(struct file *file, { void __user *argp = (void __user *)arg; int __user *p = argp; - int new_value, retval = -EINVAL;; + int new_value, retval = -EINVAL; switch (cmd) { case WDIOC_GETSUPPORT: diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index ee1caae4d33..016245419fa 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -38,7 +38,7 @@ static unsigned long oscr_freq; static unsigned long sa1100wdt_users; -static int pre_margin; +static unsigned int pre_margin; static int boot_status; /* @@ -84,6 +84,7 @@ static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "SA1100/PXA255 Watchdog", + .firmware_version = 1, }; static long sa1100dog_ioctl(struct file *file, unsigned int cmd, @@ -118,7 +119,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (time <= 0 || time > 255) { + if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { ret = -EINVAL; break; } diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 916890abffd..f201accc4e3 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -89,6 +89,11 @@ static void w83627hf_select_wd_register(void) c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ outb_p(0x2b, WDT_EFER); outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ + } else if (c == 0x88) { /* W83627EHF */ + outb_p(0x2d, WDT_EFER); /* select GPIO5 */ + c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ + outb_p(0x2d, WDT_EFER); + outb_p(c, WDT_EFDR); /* set GPIO5 to WDT0 */ } outb_p(0x07, WDT_EFER); /* point to logical device number reg */ diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index 883b5f79673..a6c12dec91a 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -149,8 +149,10 @@ static void wdt_ctrl(int timeout) { spin_lock(&io_lock); - if (w83697ug_select_wd_register() < 0) + if (w83697ug_select_wd_register() < 0) { + spin_unlock(&io_lock); return; + } outb_p(0xF4, WDT_EFER); /* Select CRF4 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 891d2e90753..abad71b1632 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -927,9 +927,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { void __init xen_init_IRQ(void) { int i; - size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s); - cpu_evtchn_mask_p = alloc_bootmem(size); + cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s), + GFP_KERNEL); BUG_ON(cpu_evtchn_mask_p == NULL); init_evtchn_cpu_bindings(); diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index c52be53f694..5ffb570cd3a 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -17,7 +17,6 @@ #include <linux/pagemap.h> #include <linux/mount.h> #include <linux/namei.h> -#include <linux/mnt_namespace.h> #include "internal.h" @@ -705,14 +705,13 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, } static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, - struct sg_iovec *iov, int iov_count, int uncopy, - int do_free_page) + struct sg_iovec *iov, int iov_count, + int to_user, int from_user, int do_free_page) { int ret = 0, i; struct bio_vec *bvec; int iov_idx = 0; unsigned int iov_off = 0; - int read = bio_data_dir(bio) == READ; __bio_for_each_segment(bvec, bio, i, 0) { char *bv_addr = page_address(bvec->bv_page); @@ -727,13 +726,14 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, iov_addr = iov[iov_idx].iov_base + iov_off; if (!ret) { - if (!read && !uncopy) - ret = copy_from_user(bv_addr, iov_addr, - bytes); - if (read && uncopy) + if (to_user) ret = copy_to_user(iov_addr, bv_addr, bytes); + if (from_user) + ret = copy_from_user(bv_addr, iov_addr, + bytes); + if (ret) ret = -EFAULT; } @@ -770,7 +770,8 @@ int bio_uncopy_user(struct bio *bio) if (!bio_flagged(bio, BIO_NULL_MAPPED)) ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, - bmd->nr_sgvecs, 1, bmd->is_our_pages); + bmd->nr_sgvecs, bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); bio_free_map_data(bmd); bio_put(bio); return ret; @@ -875,8 +876,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q, /* * success */ - if (!write_to_vm && (!map_data || !map_data->null_mapped)) { - ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); + if ((!write_to_vm && (!map_data || !map_data->null_mapped)) || + (map_data && map_data->from_user)) { + ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0); if (ret) goto cleanup; } diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3a9b7a58a51..92888aa9074 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -5,7 +5,11 @@ client generated ones by default (mount option "serverino" turned on by default if server supports it). Add forceuid and forcegid mount options (so that when negotiating unix extensions specifying which uid mounted does not immediately force the server's reported -uids to be overridden). Add support for scope moutn parm. +uids to be overridden). Add support for scope mount parm. Improve +hard link detection to use same inode for both. Do not set +read-only dos attribute on directories (for chmod) since Windows +explorer special cases this attribute bit for directories for +a different purpose. Version 1.58 ------------ diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 4a4581cb2b5..051caecf7d6 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -86,6 +86,9 @@ struct key_type cifs_spnego_key_type = { /* strlen of ";user=" */ #define USER_KEY_LEN 6 +/* strlen of ";pid=0x" */ +#define PID_KEY_LEN 7 + /* get a key struct with a SPNEGO security blob, suitable for session setup */ struct key * cifs_get_spnego_key(struct cifsSesInfo *sesInfo) @@ -103,7 +106,8 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) IP_KEY_LEN + INET6_ADDRSTRLEN + MAX_MECH_STR_LEN + UID_KEY_LEN + (sizeof(uid_t) * 2) + - USER_KEY_LEN + strlen(sesInfo->userName) + 1; + USER_KEY_LEN + strlen(sesInfo->userName) + + PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; spnego_key = ERR_PTR(-ENOMEM); description = kzalloc(desc_len, GFP_KERNEL); @@ -141,6 +145,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); sprintf(dp, ";user=%s", sesInfo->userName); + dp = description + strlen(description); + sprintf(dp, ";pid=0x%x", current->pid); + cFYI(1, ("key description = %s", description)); spnego_key = request_key(&cifs_spnego_key_type, description, ""); diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1403b5d86a7..6941c22398a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, - struct inode *inode) + struct cifs_fattr *fattr) { int i; int num_aces = 0; @@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, if (!pdacl) { /* no DACL in the security descriptor, set all the permissions for user/group/other */ - inode->i_mode |= S_IRWXUGO; + fattr->cf_mode |= S_IRWXUGO; return; } @@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, /* reset rwx permissions for user/group/other. Also, if num_aces is 0 i.e. DACL has no ACEs, user/group/other have no permissions */ - inode->i_mode &= ~(S_IRWXUGO); + fattr->cf_mode &= ~(S_IRWXUGO); acl_base = (char *)pdacl; acl_size = sizeof(struct cifs_acl); @@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, if (compare_sids(&(ppace[i]->sid), pownersid)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &user_mask); if (compare_sids(&(ppace[i]->sid), pgrpsid)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &group_mask); if (compare_sids(&(ppace[i]->sid), &sid_everyone)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &other_mask); /* memcpy((void *)(&(cifscred->aces[i])), @@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) /* Convert CIFS ACL to POSIX form */ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, - struct inode *inode) + struct cifs_fattr *fattr) { int rc; struct cifs_sid *owner_sid_ptr, *group_sid_ptr; @@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, char *end_of_acl = ((char *)pntsd) + acl_len; __u32 dacloffset; - if ((inode == NULL) || (pntsd == NULL)) + if (pntsd == NULL) return -EIO; owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + @@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, if (dacloffset) parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, - group_sid_ptr, inode); + group_sid_ptr, fattr); else cFYI(1, ("no ACL")); /* BB grant all or default perms? */ @@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, sizeof(struct cifs_sid)); */ - return 0; } @@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, } /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ -void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, - const char *path, const __u16 *pfid) +void +cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + struct inode *inode, const char *path, const __u16 *pfid) { struct cifs_ntsd *pntsd = NULL; u32 acllen = 0; @@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ if (pntsd) - rc = parse_sec_desc(pntsd, acllen, inode); + rc = parse_sec_desc(pntsd, acllen, fattr); if (rc) cFYI(1, ("parse sec desc failed rc = %d", rc)); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9f669f982c4..44f30504b82 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -308,7 +308,6 @@ cifs_alloc_inode(struct super_block *sb) if (!cifs_inode) return NULL; cifs_inode->cifsAttrs = 0x20; /* default */ - atomic_set(&cifs_inode->inUse, 0); cifs_inode->time = 0; cifs_inode->write_behind_rc = 0; /* Until the file is open and we have gotten oplock diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023..6c170948300 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -24,6 +24,19 @@ #define ROOT_I 2 +/* + * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down + * so that it will fit. + */ +static inline ino_t +cifs_uniqueid_to_ino_t(u64 fileid) +{ + ino_t ino = (ino_t) fileid; + if (sizeof(ino_t) < sizeof(u64)) + ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; + return ino; +} + extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; @@ -100,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.59" +#define CIFS_VERSION "1.60" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2..63f6cdfa563 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -364,13 +364,13 @@ struct cifsInodeInfo { struct list_head openFileList; int write_behind_rc; __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ - atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ unsigned long time; /* jiffies of last update/check of inode */ bool clientCanCacheRead:1; /* read oplock */ bool clientCanCacheAll:1; /* read and writebehind oplock */ bool oplockPending:1; bool delete_pending:1; /* DELETE_ON_CLOSE is set */ u64 server_eof; /* current file size on server */ + u64 uniqueid; /* server inode number */ struct inode vfs_inode; }; @@ -472,6 +472,32 @@ struct dfs_info3_param { char *node_name; }; +/* + * common struct for holding inode info when searching for or updating an + * inode with new info + */ + +#define CIFS_FATTR_DFS_REFERRAL 0x1 +#define CIFS_FATTR_DELETE_PENDING 0x2 +#define CIFS_FATTR_NEED_REVAL 0x4 + +struct cifs_fattr { + u32 cf_flags; + u32 cf_cifsattrs; + u64 cf_uniqueid; + u64 cf_eof; + u64 cf_bytes; + uid_t cf_uid; + gid_t cf_gid; + umode_t cf_mode; + dev_t cf_rdev; + unsigned int cf_nlink; + unsigned int cf_dtype; + struct timespec cf_atime; + struct timespec cf_mtime; + struct timespec cf_ctime; +}; + static inline void free_dfs_info_param(struct dfs_info3_param *param) { if (param) { diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9..2d07f890a84 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -2328,19 +2328,7 @@ struct file_attrib_tag { typedef struct { __le32 NextEntryOffset; __u32 ResumeKey; /* as with FileIndex - no need to convert */ - __le64 EndOfFile; - __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ - __le64 LastAccessTime; - __le64 LastModificationTime; - __le64 Uid; - __le64 Gid; - __le32 Type; - __le64 DevMajor; - __le64 DevMinor; - __le64 UniqueId; - __le64 Permissions; - __le64 Nlinks; + FILE_UNIX_BASIC_INFO basic; char FileName[1]; } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42e..da8fbf56599 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -98,9 +98,13 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, extern int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, int *poplock, __u16 *pnetfid, int xid); -extern void posix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_BASIC_INFO *pData, int isNewInode); -extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); +extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, + FILE_UNIX_BASIC_INFO *info, + struct cifs_sb_info *cifs_sb); +extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); +extern struct inode *cifs_iget(struct super_block *sb, + struct cifs_fattr *fattr); + extern int cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, FILE_ALL_INFO *pfile_info, @@ -108,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid); -extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, - const char *path, const __u16 *pfid); +extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, + struct cifs_fattr *fattr, struct inode *inode, + const char *path, const __u16 *pfid); extern int mode_to_acl(struct inode *inode, const char *path, __u64); extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, @@ -215,7 +220,11 @@ struct cifs_unix_set_info_args { dev_t device; }; -extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, +extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, + const struct cifs_unix_set_info_args *args, + u16 fid, u32 pid_of_opener); + +extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, char *fileName, const struct cifs_unix_set_info_args *args, const struct nls_table *nls_codepage, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61007c62749..922f5fe2084 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5074,10 +5074,114 @@ SetAttrLgcyRetry: } #endif /* temporarily unneeded SetAttr legacy function */ +static void +cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, + const struct cifs_unix_set_info_args *args) +{ + u64 mode = args->mode; + + /* + * Samba server ignores set of file size to zero due to bugs in some + * older clients, but we should be precise - we use SetFileSize to + * set file size and do not want to truncate file size to zero + * accidently as happened on one Samba server beta by putting + * zero instead of -1 here + */ + data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); + data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); + data_offset->LastStatusChange = cpu_to_le64(args->ctime); + data_offset->LastAccessTime = cpu_to_le64(args->atime); + data_offset->LastModificationTime = cpu_to_le64(args->mtime); + data_offset->Uid = cpu_to_le64(args->uid); + data_offset->Gid = cpu_to_le64(args->gid); + /* better to leave device as zero when it is */ + data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); + data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); + data_offset->Permissions = cpu_to_le64(mode); + + if (S_ISREG(mode)) + data_offset->Type = cpu_to_le32(UNIX_FILE); + else if (S_ISDIR(mode)) + data_offset->Type = cpu_to_le32(UNIX_DIR); + else if (S_ISLNK(mode)) + data_offset->Type = cpu_to_le32(UNIX_SYMLINK); + else if (S_ISCHR(mode)) + data_offset->Type = cpu_to_le32(UNIX_CHARDEV); + else if (S_ISBLK(mode)) + data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); + else if (S_ISFIFO(mode)) + data_offset->Type = cpu_to_le32(UNIX_FIFO); + else if (S_ISSOCK(mode)) + data_offset->Type = cpu_to_le32(UNIX_SOCKET); +} + int -CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, - const struct cifs_unix_set_info_args *args, - const struct nls_table *nls_codepage, int remap) +CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, + const struct cifs_unix_set_info_args *args, + u16 fid, u32 pid_of_opener) +{ + struct smb_com_transaction2_sfi_req *pSMB = NULL; + FILE_UNIX_BASIC_INFO *data_offset; + int rc = 0; + u16 params, param_offset, offset, byte_count, count; + + cFYI(1, ("Set Unix Info (via SetFileInfo)")); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + + if (rc) + return rc; + + pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); + + params = 6; + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; + offset = param_offset + params; + + data_offset = (FILE_UNIX_BASIC_INFO *) + ((char *)(&pSMB->hdr.Protocol) + offset); + count = sizeof(FILE_UNIX_BASIC_INFO); + + pSMB->MaxParameterCount = cpu_to_le16(2); + /* BB find max SMB PDU from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); + byte_count = 3 /* pad */ + params + count; + pSMB->DataCount = cpu_to_le16(count); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->Fid = fid; + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + cifs_fill_unix_set_info(data_offset, args); + + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); + if (rc) + cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ + + return rc; +} + +int +CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, + const struct cifs_unix_set_info_args *args, + const struct nls_table *nls_codepage, int remap) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -5086,7 +5190,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, int bytes_returned = 0; FILE_UNIX_BASIC_INFO *data_offset; __u16 params, param_offset, offset, count, byte_count; - __u64 mode = args->mode; cFYI(1, ("In SetUID/GID/Mode")); setPermsRetry: @@ -5137,38 +5240,8 @@ setPermsRetry: pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; - /* Samba server ignores set of file size to zero due to bugs in some - older clients, but we should be precise - we use SetFileSize to - set file size and do not want to truncate file size to zero - accidently as happened on one Samba server beta by putting - zero instead of -1 here */ - data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); - data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); - data_offset->LastStatusChange = cpu_to_le64(args->ctime); - data_offset->LastAccessTime = cpu_to_le64(args->atime); - data_offset->LastModificationTime = cpu_to_le64(args->mtime); - data_offset->Uid = cpu_to_le64(args->uid); - data_offset->Gid = cpu_to_le64(args->gid); - /* better to leave device as zero when it is */ - data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); - data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); - data_offset->Permissions = cpu_to_le64(mode); - - if (S_ISREG(mode)) - data_offset->Type = cpu_to_le32(UNIX_FILE); - else if (S_ISDIR(mode)) - data_offset->Type = cpu_to_le32(UNIX_DIR); - else if (S_ISLNK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SYMLINK); - else if (S_ISCHR(mode)) - data_offset->Type = cpu_to_le32(UNIX_CHARDEV); - else if (S_ISBLK(mode)) - data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); - else if (S_ISFIFO(mode)) - data_offset->Type = cpu_to_le32(UNIX_FIFO); - else if (S_ISSOCK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SOCKET); + cifs_fill_unix_set_info(data_offset, args); pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9de..4326ffd90fa 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, FILE_UNIX_BASIC_INFO *presp_data; __u32 posix_flags = 0; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + struct cifs_fattr fattr; cFYI(1, ("posix open %s", full_path)); @@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, if (presp_data->Type == cpu_to_le32(-1)) goto posix_open_ret; /* open ok, caller does qpathinfo */ - /* get new inode and set it up */ if (!pinode) goto posix_open_ret; /* caller does not need info */ + cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); + + /* get new inode and set it up */ if (*pinode == NULL) { - __u64 unique_id = le64_to_cpu(presp_data->UniqueId); - *pinode = cifs_new_inode(sb, &unique_id); + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) { + rc = -ENOMEM; + goto posix_open_ret; + } + } else { + cifs_fattr_to_inode(*pinode, &fattr); } - /* else an inode was passed in. Update its info, don't create one */ - - /* We do not need to close the file if new_inode fails since - the caller will retry qpathinfo as long as inode is null */ - if (*pinode == NULL) - goto posix_open_ret; - - posix_fill_in_inode(*pinode, presp_data, 1); cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); @@ -425,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { /* BB implement mode setting via Windows security descriptors e.g. */ @@ -515,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, - &args, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path, @@ -643,6 +644,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } } + /* + * O_EXCL: optimize away the lookup, but don't hash the dentry. Let + * the VFS handle the create. + */ + if (nd->flags & LOOKUP_EXCL) { + d_instantiate(direntry, NULL); + return 0; + } + /* can not grab the rename sem here since it would deadlock in the cases (beginning of sys_rename itself) in which we already have the sb rename sem */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 97ce4bf89d1..c34b7f8a217 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -448,9 +448,9 @@ int cifs_open(struct inode *inode, struct file *file) .mtime = NO_CHANGE_64, .device = 0, }; - CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0..18afe57b246 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -77,239 +77,202 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) } } -static void cifs_unix_info_to_inode(struct inode *inode, - FILE_UNIX_BASIC_INFO *info, int force_uid_gid) +/* populate an inode with info from a cifs_fattr struct */ +void +cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) { + struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsInodeInfo *cifsInfo = CIFS_I(inode); - __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); - __u64 end_of_file = le64_to_cpu(info->EndOfFile); + unsigned long oldtime = cifs_i->time; + + inode->i_atime = fattr->cf_atime; + inode->i_mtime = fattr->cf_mtime; + inode->i_ctime = fattr->cf_ctime; + inode->i_rdev = fattr->cf_rdev; + inode->i_nlink = fattr->cf_nlink; + inode->i_uid = fattr->cf_uid; + inode->i_gid = fattr->cf_gid; + + /* if dynperm is set, don't clobber existing mode */ + if (inode->i_state & I_NEW || + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) + inode->i_mode = fattr->cf_mode; + + cifs_i->cifsAttrs = fattr->cf_cifsattrs; + cifs_i->uniqueid = fattr->cf_uniqueid; + + if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) + cifs_i->time = 0; + else + cifs_i->time = jiffies; + + cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, + oldtime, cifs_i->time)); - inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); - inode->i_mtime = - cifs_NTtimeToUnix(info->LastModificationTime); - inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); - inode->i_mode = le64_to_cpu(info->Permissions); + cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; + + /* + * Can't safely change the file size here if the client is writing to + * it due to potential races. + */ + spin_lock(&inode->i_lock); + if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { + i_size_write(inode, fattr->cf_eof); + + /* + * i_blocks is not related to (i_size / i_blksize), + * but instead 512 byte (2**9) size is required for + * calculating num blocks. + */ + inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; + } + spin_unlock(&inode->i_lock); + + cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); +} + +/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ +void +cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, + struct cifs_sb_info *cifs_sb) +{ + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); + fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); + fattr->cf_eof = le64_to_cpu(info->EndOfFile); + + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); + fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); + fattr->cf_mode = le64_to_cpu(info->Permissions); /* * Since we set the inode type below we need to mask off * to avoid strange results if bits set above. */ - inode->i_mode &= ~S_IFMT; + fattr->cf_mode &= ~S_IFMT; switch (le32_to_cpu(info->Type)) { case UNIX_FILE: - inode->i_mode |= S_IFREG; + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; break; case UNIX_SYMLINK: - inode->i_mode |= S_IFLNK; + fattr->cf_mode |= S_IFLNK; + fattr->cf_dtype = DT_LNK; break; case UNIX_DIR: - inode->i_mode |= S_IFDIR; + fattr->cf_mode |= S_IFDIR; + fattr->cf_dtype = DT_DIR; break; case UNIX_CHARDEV: - inode->i_mode |= S_IFCHR; - inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); + fattr->cf_mode |= S_IFCHR; + fattr->cf_dtype = DT_CHR; + fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), + le64_to_cpu(info->DevMinor) & MINORMASK); break; case UNIX_BLOCKDEV: - inode->i_mode |= S_IFBLK; - inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); + fattr->cf_mode |= S_IFBLK; + fattr->cf_dtype = DT_BLK; + fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), + le64_to_cpu(info->DevMinor) & MINORMASK); break; case UNIX_FIFO: - inode->i_mode |= S_IFIFO; + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; break; case UNIX_SOCKET: - inode->i_mode |= S_IFSOCK; + fattr->cf_mode |= S_IFSOCK; + fattr->cf_dtype = DT_SOCK; break; default: /* safest to call it a file if we do not know */ - inode->i_mode |= S_IFREG; + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); break; } - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && - !force_uid_gid) - inode->i_uid = cifs_sb->mnt_uid; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) + fattr->cf_uid = cifs_sb->mnt_uid; else - inode->i_uid = le64_to_cpu(info->Uid); + fattr->cf_uid = le64_to_cpu(info->Uid); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && - !force_uid_gid) - inode->i_gid = cifs_sb->mnt_gid; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) + fattr->cf_gid = cifs_sb->mnt_gid; else - inode->i_gid = le64_to_cpu(info->Gid); - - inode->i_nlink = le64_to_cpu(info->Nlinks); - - cifsInfo->server_eof = end_of_file; - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* - * We can not safely change the file size here if the client - * is writing to it due to potential races. - */ - i_size_write(inode, end_of_file); + fattr->cf_gid = le64_to_cpu(info->Gid); - /* - * i_blocks is not related to (i_size / i_blksize), - * but instead 512 byte (2**9) size is required for - * calculating num blocks. - */ - inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; - } - spin_unlock(&inode->i_lock); + fattr->cf_nlink = le64_to_cpu(info->Nlinks); } - /* - * Needed to setup inode data for the directory which is the - * junction to the new submount (ie to setup the fake directory - * which represents a DFS referral) - */ -static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, - struct super_block *sb) -{ - struct inode *pinode = NULL; - - memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); - -/* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); - __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); - __u64 UniqueId = 0; */ - pfnd_dat->LastStatusChange = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastModificationTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->Type = cpu_to_le32(UNIX_DIR); - pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); - pfnd_dat->Nlinks = cpu_to_le64(2); - if (sb->s_root) - pinode = sb->s_root->d_inode; - if (pinode == NULL) - return; - - /* fill in default values for the remaining based on root - inode since we can not query the server for this inode info */ - pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); - pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); - pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); - pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); -} - -/** - * cifs_new inode - create new inode, initialize, and hash it - * @sb - pointer to superblock - * @inum - if valid pointer and serverino is enabled, replace i_ino with val - * - * Create a new inode, initialize it for CIFS and hash it. Returns the new - * inode or NULL if one couldn't be allocated. + * Fill a cifs_fattr struct with fake inode info. * - * If the share isn't mounted with "serverino" or inum is a NULL pointer then - * we'll just use the inode number assigned by new_inode(). Note that this can - * mean i_ino collisions since the i_ino assigned by new_inode is not - * guaranteed to be unique. + * Needed to setup cifs_fattr data for the directory which is the + * junction to the new submount (ie to setup the fake directory + * which represents a DFS referral). */ -struct inode * -cifs_new_inode(struct super_block *sb, __u64 *inum) +void +cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) { - struct inode *inode; - - inode = new_inode(sb); - if (inode == NULL) - return NULL; - - /* - * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we - * stop passing inum as ptr. Are there sanity checks we can use to - * ensure that the server is really filling in that field? Also, - * if serverino is disabled, perhaps we should be using iunique()? - */ - if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) - inode->i_ino = (unsigned long) *inum; - - /* - * must set this here instead of cifs_alloc_inode since VFS will - * clobber i_flags - */ - if (sb->s_flags & MS_NOATIME) - inode->i_flags |= S_NOATIME | S_NOCMTIME; - - insert_inode_hash(inode); + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - return inode; + cFYI(1, ("creating fake fattr for DFS referral")); + + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; + fattr->cf_atime = CURRENT_TIME; + fattr->cf_ctime = CURRENT_TIME; + fattr->cf_mtime = CURRENT_TIME; + fattr->cf_nlink = 2; + fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *full_path, struct super_block *sb, int xid) + const unsigned char *full_path, + struct super_block *sb, int xid) { - int rc = 0; + int rc; FILE_UNIX_BASIC_INFO find_data; - struct cifsTconInfo *pTcon; - struct inode *inode; + struct cifs_fattr fattr; + struct cifsTconInfo *tcon; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - bool is_dfs_referral = false; - struct cifsInodeInfo *cifsInfo; - __u64 num_of_bytes; - __u64 end_of_file; - pTcon = cifs_sb->tcon; + tcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); /* could have done a find first instead but this returns more info */ - rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, + rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == -EREMOTE && !is_dfs_referral) { - is_dfs_referral = true; - cFYI(DBG2, ("DFS ref")); - /* for DFS, server does not give us real inode data */ - fill_fake_finddataunix(&find_data, sb); - rc = 0; - } else if (rc) - goto cgiiu_exit; - num_of_bytes = le64_to_cpu(find_data.NumOfBytes); - end_of_file = le64_to_cpu(find_data.EndOfFile); + if (!rc) { + cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, sb); + rc = 0; + } else { + return rc; + } - /* get new inode */ if (*pinode == NULL) { - __u64 unique_id = le64_to_cpu(find_data.UniqueId); - *pinode = cifs_new_inode(sb, &unique_id); - if (*pinode == NULL) { + /* get new inode */ + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) rc = -ENOMEM; - goto cgiiu_exit; - } + } else { + /* we already have inode, update it */ + cifs_fattr_to_inode(*pinode, &fattr); } - inode = *pinode; - cifsInfo = CIFS_I(inode); - - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - /* this is ok to set on every inode revalidate */ - atomic_set(&cifsInfo->inUse, 1); - - cifs_unix_info_to_inode(inode, &find_data, 0); - - if (num_of_bytes < end_of_file) - cFYI(1, ("allocation size less than end of file")); - cFYI(1, ("Size %ld and blocks %llu", - (unsigned long) inode->i_size, - (unsigned long long)inode->i_blocks)); - - cifs_set_ops(inode, is_dfs_referral); -cgiiu_exit: return rc; } -static int decode_sfu_inode(struct inode *inode, __u64 size, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) +static int +cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, + struct cifs_sb_info *cifs_sb, int xid) { int rc; int oplock = 0; @@ -321,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, pbuf = buf; - if (size == 0) { - inode->i_mode |= S_IFIFO; + fattr->cf_mode &= ~S_IFMT; + + if (fattr->cf_eof == 0) { + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; return 0; - } else if (size < 8) { + } else if (fattr->cf_eof < 8) { + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; return -EINVAL; /* EOPNOTSUPP? */ } @@ -336,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, if (rc == 0) { int buf_type = CIFS_NO_BUFFER; /* Read header */ - rc = CIFSSMBRead(xid, pTcon, - netfid, + rc = CIFSSMBRead(xid, pTcon, netfid, 24 /* length */, 0 /* offset */, &bytes_read, &pbuf, &buf_type); if ((rc == 0) && (bytes_read >= 8)) { if (memcmp("IntxBLK", pbuf, 8) == 0) { cFYI(1, ("Block device")); - inode->i_mode |= S_IFBLK; + fattr->cf_mode |= S_IFBLK; + fattr->cf_dtype = DT_BLK; if (bytes_read == 24) { /* we have enough to decode dev num */ __u64 mjr; /* major */ __u64 mnr; /* minor */ mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - inode->i_rdev = MKDEV(mjr, mnr); + fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxCHR", pbuf, 8) == 0) { cFYI(1, ("Char device")); - inode->i_mode |= S_IFCHR; + fattr->cf_mode |= S_IFCHR; + fattr->cf_dtype = DT_CHR; if (bytes_read == 24) { /* we have enough to decode dev num */ __u64 mjr; /* major */ __u64 mnr; /* minor */ mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - inode->i_rdev = MKDEV(mjr, mnr); + fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxLNK", pbuf, 7) == 0) { cFYI(1, ("Symlink")); - inode->i_mode |= S_IFLNK; + fattr->cf_mode |= S_IFLNK; + fattr->cf_dtype = DT_LNK; } else { - inode->i_mode |= S_IFREG; /* file? */ + fattr->cf_mode |= S_IFREG; /* file? */ + fattr->cf_dtype = DT_REG; rc = -EOPNOTSUPP; } } else { - inode->i_mode |= S_IFREG; /* then it is a file */ + fattr->cf_mode |= S_IFREG; /* then it is a file */ + fattr->cf_dtype = DT_REG; rc = -EOPNOTSUPP; /* or some unknown SFU type */ } CIFSSMBClose(xid, pTcon, netfid); @@ -381,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ -static int get_sfu_mode(struct inode *inode, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) +/* + * Fetch mode bits as provided by SFU. + * + * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? + */ +static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, + struct cifs_sb_info *cifs_sb, int xid) { #ifdef CONFIG_CIFS_XATTR ssize_t rc; @@ -391,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, __u32 mode; rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", - ea_value, 4 /* size of buf */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + ea_value, 4 /* size of buf */, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc < 0) return (int)rc; else if (rc > 3) { mode = le32_to_cpu(*((__le32 *)ea_value)); - inode->i_mode &= ~SFBITS_MASK; - cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); - inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; + fattr->cf_mode &= ~SFBITS_MASK; + cFYI(1, ("special bits 0%o org mode 0%o", mode, + fattr->cf_mode)); + fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; cFYI(1, ("special mode bits 0%o", mode)); - return 0; - } else { - return 0; } + + return 0; #else return -EOPNOTSUPP; #endif } -/* - * Needed to setup inode data for the directory which is the - * junction to the new submount (ie to setup the fake directory - * which represents a DFS referral) - */ -static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, - struct super_block *sb) +/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ +void +cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, + struct cifs_sb_info *cifs_sb, bool adjust_tz) { - memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); - -/* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); - __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); - __u8 pfnd_dat->DeletePending = 0; - __u8 pfnd_data->Directory = 0; - __le32 pfnd_dat->EASize = 0; - __u64 pfnd_dat->IndexNumber = 0; - __u64 pfnd_dat->IndexNumber1 = 0; */ - pfnd_dat->CreationTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastWriteTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->ChangeTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); - pfnd_dat->NumberOfLinks = cpu_to_le32(2); + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); + if (info->DeletePending) + fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; + + if (info->LastAccessTime) + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + else + fattr->cf_atime = CURRENT_TIME; + + fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); + + if (adjust_tz) { + fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; + fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; + } + + fattr->cf_eof = le64_to_cpu(info->EndOfFile); + fattr->cf_bytes = le64_to_cpu(info->AllocationSize); + + if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { + fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; + fattr->cf_dtype = DT_DIR; + } else { + fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; + fattr->cf_dtype = DT_REG; + + /* clear write bits if ATTR_READONLY is set */ + if (fattr->cf_cifsattrs & ATTR_READONLY) + fattr->cf_mode &= ~(S_IWUGO); + } + + fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); + + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; } int cifs_get_inode_info(struct inode **pinode, const unsigned char *full_path, FILE_ALL_INFO *pfindData, struct super_block *sb, int xid, const __u16 *pfid) { - int rc = 0; - __u32 attr; - struct cifsInodeInfo *cifsInfo; + int rc = 0, tmprc; struct cifsTconInfo *pTcon; - struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *buf = NULL; bool adjustTZ = false; - bool is_dfs_referral = false; - umode_t default_mode; + struct cifs_fattr fattr; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); @@ -487,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode, adjustTZ = true; } } - /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ - if (rc == -EREMOTE) { - is_dfs_referral = true; - fill_fake_finddata(pfindData, sb); + + if (!rc) { + cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, + cifs_sb, adjustTZ); + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, sb); rc = 0; - } else if (rc) + } else { goto cgii_exit; + } - attr = le32_to_cpu(pfindData->Attributes); - - /* get new inode */ + /* + * If an inode wasn't passed in, then get the inode number + * + * Is an i_ino of zero legal? Can we use that to check if the server + * supports returning inode numbers? Are there other sanity checks we + * can use to ensure that the server is really filling in that field? + * + * We can not use the IndexNumber field by default from Windows or + * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA + * CIFS spec claims that this value is unique within the scope of a + * share, and the windows docs hint that it's actually unique + * per-machine. + * + * There may be higher info levels that work but are there Windows + * server or network appliances for which IndexNumber field is not + * guaranteed unique? + */ if (*pinode == NULL) { - __u64 inode_num; - __u64 *pinum = &inode_num; - - /* Is an i_ino of zero legal? Can we use that to check - if the server supports returning inode numbers? Are - there other sanity checks we can use to ensure that - the server is really filling in that field? */ - - /* We can not use the IndexNumber field by default from - Windows or Samba (in ALL_INFO buf) but we can request - it explicitly. It may not be unique presumably if - the server has multiple devices mounted under one share */ - - /* There may be higher info levels that work but are - there Windows server or network appliances for which - IndexNumber field is not guaranteed unique? */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { int rc1 = 0; rc1 = CIFSGetSrvInodeNumber(xid, pTcon, - full_path, pinum, + full_path, &fattr.cf_uniqueid, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc1) { - cFYI(1, ("GetSrvInodeNum rc %d", rc1)); - pinum = NULL; /* BB EOPNOSUPP disable SERVER_INUM? */ + cFYI(1, ("GetSrvInodeNum rc %d", rc1)); + fattr.cf_uniqueid = iunique(sb, ROOT_I); } } else { - pinum = NULL; - } - - *pinode = cifs_new_inode(sb, pinum); - if (*pinode == NULL) { - rc = -ENOMEM; - goto cgii_exit; + fattr.cf_uniqueid = iunique(sb, ROOT_I); } - } - inode = *pinode; - cifsInfo = CIFS_I(inode); - cifsInfo->cifsAttrs = attr; - cifsInfo->delete_pending = pfindData->DeletePending ? true : false; - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - - /* blksize needs to be multiple of two. So safer to default to - blksize and blkbits set in superblock so 2**blkbits and blksize - will match rather than setting to: - (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ - - /* Linux can not store file creation time so ignore it */ - if (pfindData->LastAccessTime) - inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); - else /* do not need to use current_fs_time - time not stored */ - inode->i_atime = CURRENT_TIME; - inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); - inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); - cFYI(DBG2, ("Attributes came in as 0x%x", attr)); - if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { - inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; - inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; - } - - /* get default inode mode */ - if (attr & ATTR_DIRECTORY) - default_mode = cifs_sb->mnt_dir_mode; - else - default_mode = cifs_sb->mnt_file_mode; - - /* set permission bits */ - if (atomic_read(&cifsInfo->inUse) == 0 || - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) - inode->i_mode = default_mode; - else { - /* just reenable write bits if !ATTR_READONLY */ - if ((inode->i_mode & S_IWUGO) == 0 && - (attr & ATTR_READONLY) == 0) - inode->i_mode |= (S_IWUGO & default_mode); - - inode->i_mode &= ~S_IFMT; - } - /* clear write bits if ATTR_READONLY is set */ - if (attr & ATTR_READONLY) - inode->i_mode &= ~S_IWUGO; - - /* set inode type */ - if ((attr & ATTR_SYSTEM) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { - /* no need to fix endianness on 0 */ - if (pfindData->EndOfFile == 0) - inode->i_mode |= S_IFIFO; - else if (decode_sfu_inode(inode, - le64_to_cpu(pfindData->EndOfFile), - full_path, cifs_sb, xid)) - cFYI(1, ("unknown SFU file type\n")); } else { - if (attr & ATTR_DIRECTORY) - inode->i_mode |= S_IFDIR; - else - inode->i_mode |= S_IFREG; + fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; } - cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { - /* can not safely shrink the file size here if the - client is writing to it due to potential races */ - i_size_write(inode, cifsInfo->server_eof); - - /* 512 bytes (2**9) is the fake blocksize that must be - used for this calculation */ - inode->i_blocks = (512 - 1 + le64_to_cpu( - pfindData->AllocationSize)) >> 9; + /* query for SFU type info if supported and needed */ + if (fattr.cf_cifsattrs & ATTR_SYSTEM && + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); } - spin_unlock(&inode->i_lock); - inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); - - /* BB fill in uid and gid here? with help from winbind? - or retrieve from NTFS stream extended attribute */ #ifdef CONFIG_CIFS_EXPERIMENTAL /* fill in 0777 bits from ACL */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { cFYI(1, ("Getting mode bits from ACL")); - acl_to_uid_mode(cifs_sb, inode, full_path, pfid); + cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); } #endif - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - /* fill in remaining high mode bits e.g. SUID, VTX */ - get_sfu_mode(inode, full_path, cifs_sb, xid); - } else if (atomic_read(&cifsInfo->inUse) == 0) { - inode->i_uid = cifs_sb->mnt_uid; - inode->i_gid = cifs_sb->mnt_gid; - /* set so we do not keep refreshing these fields with - bad data after user has changed them in memory */ - atomic_set(&cifsInfo->inUse, 1); - } - - cifs_set_ops(inode, is_dfs_referral); - + /* fill in remaining high mode bits e.g. SUID, VTX */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) + cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); + if (!*pinode) { + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) + rc = -ENOMEM; + } else { + cifs_fattr_to_inode(*pinode, &fattr); + } cgii_exit: kfree(buf); @@ -695,33 +602,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) return full_path; } +static int +cifs_find_inode(struct inode *inode, void *opaque) +{ + struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; + + if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) + return 0; + + return 1; +} + +static int +cifs_init_inode(struct inode *inode, void *opaque) +{ + struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; + + CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; + return 0; +} + +/* Given fattrs, get a corresponding inode */ +struct inode * +cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) +{ + unsigned long hash; + struct inode *inode; + + cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); + + /* hash down to 32-bits on 32-bit arch */ + hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); + + inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); + + /* we have fattrs in hand, update the inode */ + if (inode) { + cifs_fattr_to_inode(inode, fattr); + if (sb->s_flags & MS_NOATIME) + inode->i_flags |= S_NOATIME | S_NOCMTIME; + if (inode->i_state & I_NEW) { + inode->i_ino = hash; + unlock_new_inode(inode); + } + } + + return inode; +} + /* gets root inode */ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) { int xid; struct cifs_sb_info *cifs_sb; - struct inode *inode; + struct inode *inode = NULL; long rc; char *full_path; - inode = iget_locked(sb, ino); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - - cifs_sb = CIFS_SB(inode->i_sb); + cifs_sb = CIFS_SB(sb); full_path = cifs_build_path_to_root(cifs_sb); if (full_path == NULL) return ERR_PTR(-ENOMEM); xid = GetXid(); if (cifs_sb->tcon->unix_ext) - rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, - xid); + rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); else - rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, + rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); + + if (!inode) + return ERR_PTR(-ENOMEM); + if (rc && cifs_sb->tcon->ipc) { cFYI(1, ("ipc connection - fake read inode")); inode->i_mode |= S_IFDIR; @@ -737,7 +689,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) return ERR_PTR(rc); } - unlock_new_inode(inode); kfree(full_path); /* can not call macro FreeXid here since in a void func @@ -1063,44 +1014,6 @@ out_reval: return rc; } -void posix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_BASIC_INFO *pData, int isNewInode) -{ - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - loff_t local_size; - struct timespec local_mtime; - - cifsInfo->time = jiffies; - atomic_inc(&cifsInfo->inUse); - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - cifs_unix_info_to_inode(tmp_inode, pData, 1); - cifs_set_ops(tmp_inode, false); - - if (!S_ISREG(tmp_inode->i_mode)) - return; - - /* - * No sense invalidating pages for new inode - * since we we have not started caching - * readahead file data yet. - */ - if (isNewInode) - return; - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } -} - int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) { int rc = 0, tmprc; @@ -1109,6 +1022,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; + struct cifs_fattr fattr; cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); @@ -1148,7 +1062,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) cFYI(1, ("posix mkdir returned 0x%x", rc)); d_drop(direntry); } else { - __u64 unique_id; if (pInfo->Type == cpu_to_le32(-1)) { /* no return info, go query for it */ kfree(pInfo); @@ -1162,20 +1075,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) else direntry->d_op = &cifs_dentry_ops; - unique_id = le64_to_cpu(pInfo->UniqueId); - newinode = cifs_new_inode(inode->i_sb, &unique_id); - if (newinode == NULL) { + cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); + newinode = cifs_iget(inode->i_sb, &fattr); + if (!newinode) { kfree(pInfo); goto mkdir_get_info; } - newinode->i_nlink = 2; d_instantiate(direntry, newinode); - /* we already checked in POSIXCreate whether - frame was long enough */ - posix_fill_in_inode(direntry->d_inode, - pInfo, 1 /* NewInode */); #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("instantiated dentry %p %s to inode %p", direntry, direntry->d_name.name, newinode)); @@ -1238,10 +1146,10 @@ mkdir_get_info: args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && (mode & S_IWUGO) == 0) { @@ -1622,6 +1530,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, if (!err) { generic_fillattr(dentry->d_inode, stat); stat->blksize = CIFS_MAX_MSGSIZE; + stat->ino = CIFS_I(dentry->d_inode)->uniqueid; } return err; } @@ -1786,6 +1695,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsTconInfo *pTcon = cifs_sb->tcon; struct cifs_unix_set_info_args *args = NULL; + struct cifsFileInfo *open_file; cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", direntry->d_name.name, attrs->ia_valid)); @@ -1872,10 +1782,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) args->ctime = NO_CHANGE_64; args->device = 0; - rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + open_file = find_writable_file(cifsInode); + if (open_file) { + u16 nfid = open_file->netfid; + u32 npid = open_file->pid; + rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); + atomic_dec(&open_file->wrtPending); + } else { + rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } if (!rc) rc = inode_setattr(inode, attrs); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc52..f823a4a208a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -63,374 +63,123 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) } #endif /* DEBUG2 */ -/* Returns 1 if new inode created, 2 if both dentry and inode were */ -/* Might check in the future if inode number changed so we can rehash inode */ -static int -construct_dentry(struct qstr *qstring, struct file *file, - struct inode **ptmp_inode, struct dentry **pnew_dentry, - __u64 *inum) +/* + * Find the dentry that matches "name". If there isn't one, create one. If it's + * a negative dentry or the uniqueid changed, then drop it and recreate it. + */ +static struct dentry * +cifs_readdir_lookup(struct dentry *parent, struct qstr *name, + struct cifs_fattr *fattr) { - struct dentry *tmp_dentry = NULL; - struct super_block *sb = file->f_path.dentry->d_sb; - int rc = 0; + struct dentry *dentry, *alias; + struct inode *inode; + struct super_block *sb = parent->d_inode->i_sb; + + cFYI(1, ("For %s", name->name)); + + dentry = d_lookup(parent, name); + if (dentry) { + /* FIXME: check for inode number changes? */ + if (dentry->d_inode != NULL) + return dentry; + d_drop(dentry); + dput(dentry); + } - cFYI(1, ("For %s", qstring->name)); - - qstring->hash = full_name_hash(qstring->name, qstring->len); - tmp_dentry = d_lookup(file->f_path.dentry, qstring); - if (tmp_dentry) { - /* BB: overwrite old name? i.e. tmp_dentry->d_name and - * tmp_dentry->d_name.len?? - */ - cFYI(0, ("existing dentry with inode 0x%p", - tmp_dentry->d_inode)); - *ptmp_inode = tmp_dentry->d_inode; - if (*ptmp_inode == NULL) { - *ptmp_inode = cifs_new_inode(sb, inum); - if (*ptmp_inode == NULL) - return rc; - rc = 1; - } - } else { - tmp_dentry = d_alloc(file->f_path.dentry, qstring); - if (tmp_dentry == NULL) { - cERROR(1, ("Failed allocating dentry")); - *ptmp_inode = NULL; - return rc; - } + dentry = d_alloc(parent, name); + if (dentry == NULL) + return NULL; - if (CIFS_SB(sb)->tcon->nocase) - tmp_dentry->d_op = &cifs_ci_dentry_ops; - else - tmp_dentry->d_op = &cifs_dentry_ops; + inode = cifs_iget(sb, fattr); + if (!inode) { + dput(dentry); + return NULL; + } - *ptmp_inode = cifs_new_inode(sb, inum); - if (*ptmp_inode == NULL) - return rc; - rc = 2; + if (CIFS_SB(sb)->tcon->nocase) + dentry->d_op = &cifs_ci_dentry_ops; + else + dentry->d_op = &cifs_dentry_ops; + + alias = d_materialise_unique(dentry, inode); + if (alias != NULL) { + dput(dentry); + if (IS_ERR(alias)) + return NULL; + dentry = alias; } - tmp_dentry->d_time = jiffies; - *pnew_dentry = tmp_dentry; - return rc; + return dentry; } -static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, - char *buf, unsigned int *pobject_type, int isNewInode) +static void +cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) { - loff_t local_size; - struct timespec local_mtime; - - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); - __u32 attr; - __u64 allocation_size; - __u64 end_of_file; - umode_t default_mode; - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - if (new_buf_type) { - FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; - - attr = le32_to_cpu(pfindData->ExtFileAttributes); - allocation_size = le64_to_cpu(pfindData->AllocationSize); - end_of_file = le64_to_cpu(pfindData->EndOfFile); - tmp_inode->i_atime = - cifs_NTtimeToUnix(pfindData->LastAccessTime); - tmp_inode->i_mtime = - cifs_NTtimeToUnix(pfindData->LastWriteTime); - tmp_inode->i_ctime = - cifs_NTtimeToUnix(pfindData->ChangeTime); - } else { /* legacy, OS2 and DOS style */ - int offset = cifs_sb->tcon->ses->server->timeAdj; - FIND_FILE_STANDARD_INFO *pfindData = - (FIND_FILE_STANDARD_INFO *)buf; - - tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate, - pfindData->LastWriteTime, - offset); - tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate, - pfindData->LastAccessTime, - offset); - tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate, - pfindData->LastWriteTime, - offset); - attr = le16_to_cpu(pfindData->Attributes); - allocation_size = le32_to_cpu(pfindData->AllocationSize); - end_of_file = le32_to_cpu(pfindData->DataSize); - } + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; - /* Linux can not store file creation time unfortunately so ignore it */ - - cifsInfo->cifsAttrs = attr; -#ifdef CONFIG_CIFS_EXPERIMENTAL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - /* get more accurate mode via ACL - so force inode refresh */ - cifsInfo->time = 0; - } else -#endif /* CONFIG_CIFS_EXPERIMENTAL */ - cifsInfo->time = jiffies; - - /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ - /* 2767 perms - indicate mandatory locking */ - /* BB fill in uid and gid here? with help from winbind? - or retrieve from NTFS stream extended attribute */ - if (atomic_read(&cifsInfo->inUse) == 0) { - tmp_inode->i_uid = cifs_sb->mnt_uid; - tmp_inode->i_gid = cifs_sb->mnt_gid; - } - - if (attr & ATTR_DIRECTORY) - default_mode = cifs_sb->mnt_dir_mode; - else - default_mode = cifs_sb->mnt_file_mode; - - /* set initial permissions */ - if ((atomic_read(&cifsInfo->inUse) == 0) || - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) - tmp_inode->i_mode = default_mode; - else { - /* just reenable write bits if !ATTR_READONLY */ - if ((tmp_inode->i_mode & S_IWUGO) == 0 && - (attr & ATTR_READONLY) == 0) - tmp_inode->i_mode |= (S_IWUGO & default_mode); - - tmp_inode->i_mode &= ~S_IFMT; + if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { + fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; + fattr->cf_dtype = DT_DIR; + } else { + fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; + fattr->cf_dtype = DT_REG; } - /* clear write bits if ATTR_READONLY is set */ - if (attr & ATTR_READONLY) - tmp_inode->i_mode &= ~S_IWUGO; + if (fattr->cf_cifsattrs & ATTR_READONLY) + fattr->cf_mode &= ~S_IWUGO; - /* set inode type */ - if ((attr & ATTR_SYSTEM) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { - if (end_of_file == 0) { - tmp_inode->i_mode |= S_IFIFO; - *pobject_type = DT_FIFO; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && + fattr->cf_cifsattrs & ATTR_SYSTEM) { + if (fattr->cf_eof == 0) { + fattr->cf_mode &= ~S_IFMT; + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; } else { /* - * trying to get the type can be slow, so just call - * this a regular file for now, and mark for reval + * trying to get the type and mode via SFU can be slow, + * so just call those regular files for now, and mark + * for reval */ - tmp_inode->i_mode |= S_IFREG; - *pobject_type = DT_REG; - cifsInfo->time = 0; - } - } else { - if (attr & ATTR_DIRECTORY) { - tmp_inode->i_mode |= S_IFDIR; - *pobject_type = DT_DIR; - } else { - tmp_inode->i_mode |= S_IFREG; - *pobject_type = DT_REG; + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; } } +} - /* can not fill in nlink here as in qpathinfo version and Unx search */ - if (atomic_read(&cifsInfo->inUse) == 0) - atomic_set(&cifsInfo->inUse, 1); - - cifsInfo->server_eof = end_of_file; - spin_lock(&tmp_inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* can not safely change the file size here if the - client is writing to it due to potential races */ - i_size_write(tmp_inode, end_of_file); - - /* 512 bytes (2**9) is the fake blocksize that must be used */ - /* for this calculation, even though the reported blocksize is larger */ - tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; - } - spin_unlock(&tmp_inode->i_lock); - - if (allocation_size < end_of_file) - cFYI(1, ("May be sparse file, allocation less than file size")); - cFYI(1, ("File Size %ld and blocks %llu", - (unsigned long)tmp_inode->i_size, - (unsigned long long)tmp_inode->i_blocks)); - if (S_ISREG(tmp_inode->i_mode)) { - cFYI(1, ("File inode")); - tmp_inode->i_op = &cifs_file_inode_ops; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_direct_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_ops; - - if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && - (cifs_sb->tcon->ses->server->maxBuf < - PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) - tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; - else - tmp_inode->i_data.a_ops = &cifs_addr_ops; - - if (isNewInode) - return; /* No sense invalidating pages for new inode - since have not started caching readahead file - data yet */ - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } - } else if (S_ISDIR(tmp_inode->i_mode)) { - cFYI(1, ("Directory inode")); - tmp_inode->i_op = &cifs_dir_inode_ops; - tmp_inode->i_fop = &cifs_dir_ops; - } else if (S_ISLNK(tmp_inode->i_mode)) { - cFYI(1, ("Symbolic Link inode")); - tmp_inode->i_op = &cifs_symlink_inode_ops; - } else { - cFYI(1, ("Init special inode")); - init_special_inode(tmp_inode, tmp_inode->i_mode, - tmp_inode->i_rdev); - } +void +cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, + struct cifs_sb_info *cifs_sb) +{ + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); + fattr->cf_eof = le64_to_cpu(info->EndOfFile); + fattr->cf_bytes = le64_to_cpu(info->AllocationSize); + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); + + cifs_fill_common_info(fattr, cifs_sb); } -static void unix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) +void +cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, + struct cifs_sb_info *cifs_sb) { - loff_t local_size; - struct timespec local_mtime; - - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); - - __u32 type = le32_to_cpu(pfindData->Type); - __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); - __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); - cifsInfo->time = jiffies; - atomic_inc(&cifsInfo->inUse); - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - tmp_inode->i_atime = - cifs_NTtimeToUnix(pfindData->LastAccessTime); - tmp_inode->i_mtime = - cifs_NTtimeToUnix(pfindData->LastModificationTime); - tmp_inode->i_ctime = - cifs_NTtimeToUnix(pfindData->LastStatusChange); - - tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); - /* since we set the inode type below we need to mask off type - to avoid strange results if bits above were corrupt */ - tmp_inode->i_mode &= ~S_IFMT; - if (type == UNIX_FILE) { - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - } else if (type == UNIX_SYMLINK) { - *pobject_type = DT_LNK; - tmp_inode->i_mode |= S_IFLNK; - } else if (type == UNIX_DIR) { - *pobject_type = DT_DIR; - tmp_inode->i_mode |= S_IFDIR; - } else if (type == UNIX_CHARDEV) { - *pobject_type = DT_CHR; - tmp_inode->i_mode |= S_IFCHR; - tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), - le64_to_cpu(pfindData->DevMinor) & MINORMASK); - } else if (type == UNIX_BLOCKDEV) { - *pobject_type = DT_BLK; - tmp_inode->i_mode |= S_IFBLK; - tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), - le64_to_cpu(pfindData->DevMinor) & MINORMASK); - } else if (type == UNIX_FIFO) { - *pobject_type = DT_FIFO; - tmp_inode->i_mode |= S_IFIFO; - } else if (type == UNIX_SOCKET) { - *pobject_type = DT_SOCK; - tmp_inode->i_mode |= S_IFSOCK; - } else { - /* safest to just call it a file */ - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - cFYI(1, ("unknown inode type %d", type)); - } + int offset = cifs_sb->tcon->ses->server->timeAdj; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) - tmp_inode->i_uid = cifs_sb->mnt_uid; - else - tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) - tmp_inode->i_gid = cifs_sb->mnt_gid; - else - tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); - tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); - - cifsInfo->server_eof = end_of_file; - spin_lock(&tmp_inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* can not safely change the file size here if the - client is writing to it due to potential races */ - i_size_write(tmp_inode, end_of_file); - - /* 512 bytes (2**9) is the fake blocksize that must be used */ - /* for this calculation, not the real blocksize */ - tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; - } - spin_unlock(&tmp_inode->i_lock); + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, + info->LastAccessTime, offset); + fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, + info->LastWriteTime, offset); + fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, + info->LastWriteTime, offset); - if (S_ISREG(tmp_inode->i_mode)) { - cFYI(1, ("File inode")); - tmp_inode->i_op = &cifs_file_inode_ops; + fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); + fattr->cf_bytes = le32_to_cpu(info->AllocationSize); + fattr->cf_eof = le32_to_cpu(info->DataSize); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_direct_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_ops; - - if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && - (cifs_sb->tcon->ses->server->maxBuf < - PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) - tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; - else - tmp_inode->i_data.a_ops = &cifs_addr_ops; - - if (isNewInode) - return; /* No sense invalidating pages for new inode - since we have not started caching readahead - file data for it yet */ - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } - } else if (S_ISDIR(tmp_inode->i_mode)) { - cFYI(1, ("Directory inode")); - tmp_inode->i_op = &cifs_dir_inode_ops; - tmp_inode->i_fop = &cifs_dir_ops; - } else if (S_ISLNK(tmp_inode->i_mode)) { - cFYI(1, ("Symbolic Link inode")); - tmp_inode->i_op = &cifs_symlink_inode_ops; -/* tmp_inode->i_fop = *//* do not need to set to anything */ - } else { - cFYI(1, ("Special inode")); - init_special_inode(tmp_inode, tmp_inode->i_mode, - tmp_inode->i_rdev); - } + cifs_fill_common_info(fattr, cifs_sb); } /* BB eventually need to add the following helper function to @@ -872,7 +621,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, len = strnlen(filename, PATH_MAX); } - *pinum = le64_to_cpu(pFindData->UniqueId); + *pinum = le64_to_cpu(pFindData->basic.UniqueId); } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { FILE_DIRECTORY_INFO *pFindData = (FILE_DIRECTORY_INFO *)current_entry; @@ -932,11 +681,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, int rc = 0; struct qstr qstring; struct cifsFileInfo *pCifsF; - unsigned int obj_type; - __u64 inum; + u64 inum; + ino_t ino; + struct super_block *sb; struct cifs_sb_info *cifs_sb; - struct inode *tmp_inode; struct dentry *tmp_dentry; + struct cifs_fattr fattr; /* get filename and len into qstring */ /* get dentry */ @@ -954,60 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, if (rc != 0) return 0; - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + sb = file->f_path.dentry->d_sb; + cifs_sb = CIFS_SB(sb); qstring.name = scratch_buf; rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, pCifsF->srch_inf.info_level, pCifsF->srch_inf.unicode, cifs_sb, - max_len, - &inum /* returned */); + max_len, &inum /* returned */); if (rc) return rc; - /* only these two infolevels return valid inode numbers */ - if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || - pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, - &inum); - else - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, - NULL); - - if ((tmp_inode == NULL) || (tmp_dentry == NULL)) - return -ENOMEM; - - /* we pass in rc below, indicating whether it is a new inode, - so we can figure out whether to invalidate the inode cached - data if the file has changed */ if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) - unix_fill_in_inode(tmp_inode, - (FILE_UNIX_INFO *)pfindEntry, - &obj_type, rc); + cifs_unix_basic_to_fattr(&fattr, + &((FILE_UNIX_INFO *) pfindEntry)->basic, + cifs_sb); else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) - fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, - pfindEntry, &obj_type, rc); + cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) + pfindEntry, cifs_sb); else - fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); + cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) + pfindEntry, cifs_sb); - if (rc) /* new inode - needs to be tied to dentry */ { - d_instantiate(tmp_dentry, tmp_inode); - if (rc == 2) - d_rehash(tmp_dentry); - } + /* FIXME: make _to_fattr functions fill this out */ + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) + fattr.cf_uniqueid = inum; + else + fattr.cf_uniqueid = iunique(sb, ROOT_I); + ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); + tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, - tmp_inode->i_ino, obj_type); + ino, fattr.cf_dtype); + + /* + * we can not return filldir errors to the caller since they are + * "normal" when the stat blocksize is too small - we return remapped + * error instead + * + * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above + * case already. Why should we be clobbering other errors from it? + */ if (rc) { cFYI(1, ("filldir rc = %d", rc)); - /* we can not return filldir errors to the caller - since they are "normal" when the stat blocksize - is too small - we return remapped error instead */ rc = -EOVERFLOW; } - dput(tmp_dentry); return rc; } diff --git a/fs/compat.c b/fs/compat.c index cdd51a3a7c5..fbadb947727 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1486,8 +1486,8 @@ int compat_do_execve(char * filename, if (!bprm) goto out_files; - retval = mutex_lock_interruptible(¤t->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; current->in_execve = 1; diff --git a/fs/exec.c b/fs/exec.c index e639957d7a5..4a8849e45b2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1277,8 +1277,8 @@ int do_execve(char * filename, if (!bprm) goto out_files; - retval = mutex_lock_interruptible(¤t->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; current->in_execve = 1; diff --git a/fs/fat/file.c b/fs/fat/file.c index b28ea646ff6..f042b965c95 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -134,7 +134,7 @@ static int fat_file_release(struct inode *inode, struct file *filp) if ((filp->f_mode & FMODE_WRITE) && MSDOS_SB(inode->i_sb)->options.flush) { fat_flush_inodes(inode->i_sb, inode, NULL); - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } return 0; } diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index f58ecbc416c..6484eb75acd 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -286,8 +286,8 @@ __releases(&fc->lock) } if (fc->num_background == FUSE_CONGESTION_THRESHOLD && fc->connected && fc->bdi_initialized) { - clear_bdi_congested(&fc->bdi, READ); - clear_bdi_congested(&fc->bdi, WRITE); + clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); + clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC); } fc->num_background--; fc->active_background--; @@ -414,8 +414,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, fc->blocked = 1; if (fc->num_background == FUSE_CONGESTION_THRESHOLD && fc->bdi_initialized) { - set_bdi_congested(&fc->bdi, READ); - set_bdi_congested(&fc->bdi, WRITE); + set_bdi_congested(&fc->bdi, BLK_RW_SYNC); + set_bdi_congested(&fc->bdi, BLK_RW_ASYNC); } list_add_tail(&req->list, &fc->bg_queue); flush_bg_queue(fc); diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a0244740b75..b47679be118 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -270,19 +270,21 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, D2({ int i=0; struct jffs2_raw_node_ref *this; - printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); + printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n"); this = ic->nodes; + printk(KERN_DEBUG); while(this) { - printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); + printk(KERN_CONT "0x%08x(%d)->", + ref_offset(this), ref_flags(this)); if (++i == 5) { - printk("\n" KERN_DEBUG); + printk(KERN_DEBUG); i=0; } this = this->next_in_ino; } - printk("\n"); + printk(KERN_CONT "\n"); }); switch (ic->class) { diff --git a/fs/namespace.c b/fs/namespace.c index 3dc283fd471..277c28a63ea 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -22,6 +22,7 @@ #include <linux/seq_file.h> #include <linux/mnt_namespace.h> #include <linux/namei.h> +#include <linux/nsproxy.h> #include <linux/security.h> #include <linux/mount.h> #include <linux/ramfs.h> diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 46177cb8706..b35d2a61606 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -30,7 +30,6 @@ #include <linux/nfs_idmap.h> #include <linux/vfs.h> #include <linux/namei.h> -#include <linux/mnt_namespace.h> #include <linux/security.h> #include <asm/system.h> diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ce728829f79..0a0a2ff767c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -202,8 +202,10 @@ static int nfs_set_page_writeback(struct page *page) struct nfs_server *nfss = NFS_SERVER(inode); if (atomic_long_inc_return(&nfss->writeback) > - NFS_CONGESTION_ON_THRESH) - set_bdi_congested(&nfss->backing_dev_info, WRITE); + NFS_CONGESTION_ON_THRESH) { + set_bdi_congested(&nfss->backing_dev_info, + BLK_RW_ASYNC); + } } return ret; } @@ -215,7 +217,7 @@ static void nfs_end_page_writeback(struct page *page) end_page_writeback(page); if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) - clear_bdi_congested(&nfss->backing_dev_info, WRITE); + clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); } /* diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 36df60b6d8a..99d58a028b9 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -568,6 +568,7 @@ void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap, } static struct lock_class_key nilfs_bmap_dat_lock_key; +static struct lock_class_key nilfs_bmap_mdt_lock_key; /** * nilfs_bmap_read - read a bmap from an inode @@ -603,7 +604,11 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) bmap->b_ptr_type = NILFS_BMAP_PTR_VS; bmap->b_last_allocated_key = 0; bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); break; + case NILFS_IFILE_INO: + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); + /* Fall through */ default: bmap->b_ptr_type = NILFS_BMAP_PTR_VM; bmap->b_last_allocated_key = 0; diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 7d49813f66d..aec942cf79e 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -307,7 +307,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); if (ret < 0) { if (ret != -ENOENT) - goto out_header; + break; /* skip hole */ ret = 0; continue; @@ -340,7 +340,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, continue; printk(KERN_ERR "%s: cannot delete block\n", __func__); - goto out_header; + break; } } @@ -358,7 +358,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, kunmap_atomic(kaddr, KM_USER0); } - out_header: brelse(header_bh); out_sem: diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 0b2710e2d56..8927ca27e6f 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -134,15 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, req->pr_entry_bh, kaddr); entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat)); - if (entry->de_blocknr != cpu_to_le64(0) || - entry->de_end != cpu_to_le64(NILFS_CNO_MAX)) { - printk(KERN_CRIT - "%s: vbn = %llu, start = %llu, end = %llu, pbn = %llu\n", - __func__, (unsigned long long)req->pr_entry_nr, - (unsigned long long)le64_to_cpu(entry->de_start), - (unsigned long long)le64_to_cpu(entry->de_end), - (unsigned long long)le64_to_cpu(entry->de_blocknr)); - } entry->de_blocknr = cpu_to_le64(blocknr); kunmap_atomic(kaddr, KM_USER0); diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index aa977549919..8b5e4778cf2 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1829,26 +1829,13 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, err = nilfs_segbuf_write(segbuf, &wi); res = nilfs_segbuf_wait(segbuf, &wi); - err = unlikely(err) ? : res; - if (unlikely(err)) + err = err ? : res; + if (err) return err; } return 0; } -static int nilfs_page_has_uncleared_buffer(struct page *page) -{ - struct buffer_head *head, *bh; - - head = bh = page_buffers(page); - do { - if (buffer_dirty(bh) && !list_empty(&bh->b_assoc_buffers)) - return 1; - bh = bh->b_this_page; - } while (bh != head); - return 0; -} - static void __nilfs_end_page_io(struct page *page, int err) { if (!err) { @@ -1872,12 +1859,11 @@ static void nilfs_end_page_io(struct page *page, int err) if (!page) return; - if (buffer_nilfs_node(page_buffers(page)) && - nilfs_page_has_uncleared_buffer(page)) - /* For b-tree node pages, this function may be called twice - or more because they might be split in a segment. - This check assures that cleanup has been done for all - buffers in a split btnode page. */ + if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) + /* + * For b-tree node pages, this function may be called twice + * or more because they might be split in a segment. + */ return; __nilfs_end_page_io(page, err); @@ -1940,7 +1926,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, } if (bh->b_page != fs_page) { nilfs_end_page_io(fs_page, err); - if (unlikely(fs_page == failed_page)) + if (fs_page && fs_page == failed_page) goto done; fs_page = bh->b_page; } diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 607c579e5ec..70f36c043d6 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2042,8 +2042,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, * changes */ invalidate_bdev(sb->s_bdev); } - mutex_lock(&inode->i_mutex); mutex_lock(&dqopt->dqonoff_mutex); + mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); if (sb_has_quota_loaded(sb, type)) { error = -EBUSY; goto out_lock; @@ -2094,7 +2094,6 @@ out_file_init: dqopt->files[type] = NULL; iput(inode); out_lock: - mutex_unlock(&dqopt->dqonoff_mutex); if (oldflags != -1) { down_write(&dqopt->dqptr_sem); /* Set the flags back (in the case of accidental quotaon() @@ -2104,6 +2103,7 @@ out_lock: up_write(&dqopt->dqptr_sem); } mutex_unlock(&inode->i_mutex); + mutex_unlock(&dqopt->dqonoff_mutex); out_fmt: put_quota_format(fmt); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 77f5bb746bf..90622200b39 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -997,7 +997,7 @@ static int reiserfs_async_progress_wait(struct super_block *s) DEFINE_WAIT(wait); struct reiserfs_journal *j = SB_JOURNAL(s); if (atomic_read(&j->j_async_throttle)) - congestion_wait(WRITE, HZ / 10); + congestion_wait(BLK_RW_ASYNC, HZ / 10); return 0; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d3aeb061612..7adea74d6a8 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -24,7 +24,6 @@ #include <linux/exportfs.h> #include <linux/quotaops.h> #include <linux/vfs.h> -#include <linux/mnt_namespace.h> #include <linux/mount.h> #include <linux/namei.h> #include <linux/crc32.h> diff --git a/fs/sync.c b/fs/sync.c index dd200025af8..3422ba61d86 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -112,8 +112,13 @@ restart: mutex_unlock(&mutex); } +/* + * sync everything. Start out by waking pdflush, because that writes back + * all queues in parallel. + */ SYSCALL_DEFINE0(sync) { + wakeup_pdflush(0); sync_filesystems(0); sync_filesystems(1); if (unlikely(laptop_mode)) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 9345806c885..2524714bece 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -171,6 +171,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, if (count > 0) *off = offs + count; + kfree(temp); return count; } diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 1cd3b55ee3d..2d3f90afe5f 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -53,7 +53,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __func__, lflags); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); } @@ -130,7 +130,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __func__, lflags); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 1418b916fc2..0c93c7ef3d1 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -412,7 +412,7 @@ _xfs_buf_lookup_pages( XFS_STATS_INC(xb_page_retries); xfsbufd_wakeup(0, gfp_mask); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry; } diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 0ec2c594868..3a52a63c135 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -229,9 +229,9 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) (1 << BDI_async_congested)); } -void clear_bdi_congested(struct backing_dev_info *bdi, int rw); -void set_bdi_congested(struct backing_dev_info *bdi, int rw); -long congestion_wait(int rw, long timeout); +void clear_bdi_congested(struct backing_dev_info *bdi, int sync); +void set_bdi_congested(struct backing_dev_info *bdi, int sync); +long congestion_wait(int sync, long timeout); static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 49ae07951d5..0146e0fecf1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -723,6 +723,7 @@ struct rq_map_data { int nr_entries; unsigned long offset; int null_mapped; + int from_user; }; struct req_iterator { @@ -779,18 +780,18 @@ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, * congested queues, and wake up anyone who was waiting for requests to be * put back. */ -static inline void blk_clear_queue_congested(struct request_queue *q, int rw) +static inline void blk_clear_queue_congested(struct request_queue *q, int sync) { - clear_bdi_congested(&q->backing_dev_info, rw); + clear_bdi_congested(&q->backing_dev_info, sync); } /* * A queue has just entered congestion. Flag that in the queue's VM-visible * state flags and increment the global gounter of congested queues. */ -static inline void blk_set_queue_congested(struct request_queue *q, int rw) +static inline void blk_set_queue_congested(struct request_queue *q, int sync) { - set_bdi_congested(&q->backing_dev_info, rw); + set_bdi_congested(&q->backing_dev_info, sync); } extern void blk_start_queue(struct request_queue *q); diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 7605c5e9589..00d6a68d042 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -122,9 +122,10 @@ static inline void elf_core_copy_kernel_regs(elf_gregset_t *elfregs, struct pt_r static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { -#ifdef ELF_CORE_COPY_TASK_REGS - +#if defined (ELF_CORE_COPY_TASK_REGS) return ELF_CORE_COPY_TASK_REGS(t, elfregs); +#elif defined (task_pt_regs) + elf_core_copy_regs(elfregs, task_pt_regs(t)); #endif return 0; } diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 9823946adbc..192d1e43c43 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -127,6 +127,7 @@ struct fw_card { struct delayed_work work; int bm_retries; int bm_generation; + __be32 bm_transaction_data[2]; bool broadcast_channel_allocated; u32 broadcast_channel; diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index ae3a1871413..70fdba2bbf7 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -78,6 +78,7 @@ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h new file mode 100644 index 00000000000..7964516c695 --- /dev/null +++ b/include/linux/input/matrix_keypad.h @@ -0,0 +1,65 @@ +#ifndef _MATRIX_KEYPAD_H +#define _MATRIX_KEYPAD_H + +#include <linux/types.h> +#include <linux/input.h> + +#define MATRIX_MAX_ROWS 16 +#define MATRIX_MAX_COLS 16 + +#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\ + (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\ + (val & 0xffff)) + +#define KEY_ROW(k) (((k) >> 24) & 0xff) +#define KEY_COL(k) (((k) >> 16) & 0xff) +#define KEY_VAL(k) ((k) & 0xffff) + +/** + * struct matrix_keymap_data - keymap for matrix keyboards + * @keymap: pointer to array of uint32 values encoded with KEY() macro + * representing keymap + * @keymap_size: number of entries (initialized) in this keymap + * @max_keymap_size: maximum size of keymap supported by the device + * + * This structure is supposed to be used by platform code to supply + * keymaps to drivers that implement matrix-like keypads/keyboards. + */ +struct matrix_keymap_data { + const uint32_t *keymap; + unsigned int keymap_size; + unsigned int max_keymap_size; +}; + +/** + * struct matrix_keypad_platform_data - platform-dependent keypad data + * @keymap_data: pointer to &matrix_keymap_data + * @row_gpios: array of gpio numbers reporesenting rows + * @col_gpios: array of gpio numbers reporesenting colums + * @num_row_gpios: actual number of row gpios used by device + * @num_col_gpios: actual number of col gpios used by device + * @col_scan_delay_us: delay, measured in microseconds, that is + * needed before we can keypad after activating column gpio + * @debounce_ms: debounce interval in milliseconds + * + * This structure represents platform-specific data that use used by + * matrix_keypad driver to perform proper initialization. + */ +struct matrix_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; + + unsigned int row_gpios[MATRIX_MAX_ROWS]; + unsigned int col_gpios[MATRIX_MAX_COLS]; + unsigned int num_row_gpios; + unsigned int num_col_gpios; + + unsigned int col_scan_delay_us; + + /* key debounce interval in milli-second */ + unsigned int debounce_ms; + + bool active_low; + bool wakeup; +}; + +#endif /* _MATRIX_KEYPAD_H */ diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h index 3beb2592b03..d74785c2393 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h @@ -2,10 +2,9 @@ #define _NAMESPACE_H_ #ifdef __KERNEL__ -#include <linux/mount.h> -#include <linux/sched.h> -#include <linux/nsproxy.h> +#include <linux/path.h> #include <linux/seq_file.h> +#include <linux/wait.h> struct mnt_namespace { atomic_t count; @@ -28,14 +27,6 @@ extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt); extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, struct fs_struct *); extern void put_mnt_ns(struct mnt_namespace *ns); - -static inline void exit_mnt_ns(struct task_struct *p) -{ - struct mnt_namespace *ns = p->nsproxy->mnt_ns; - if (ns) - put_mnt_ns(ns); -} - static inline void get_mnt_ns(struct mnt_namespace *ns) { atomic_inc(&ns->count); diff --git a/include/linux/pci.h b/include/linux/pci.h index d304ddf412d..115fb7ba508 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1145,7 +1145,7 @@ static inline void pci_set_drvdata(struct pci_dev *pdev, void *data) /* If you want to know what to call your pci_dev, ask this function. * Again, it's a wrapper around the generic device. */ -static inline const char *pci_name(struct pci_dev *pdev) +static inline const char *pci_name(const struct pci_dev *pdev) { return dev_name(&pdev->dev); } diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e73e2429a1b..2ce29831feb 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -99,7 +99,6 @@ enum rfkill_user_states { #undef RFKILL_STATE_UNBLOCKED #undef RFKILL_STATE_HARD_BLOCKED -#include <linux/types.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/mutex.h> diff --git a/include/linux/sched.h b/include/linux/sched.h index 0085d758d64..16a982e389f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -498,6 +498,15 @@ struct task_cputime { .sum_exec_runtime = 0, \ } +/* + * Disable preemption until the scheduler is running. + * Reset by start_kernel()->sched_init()->init_idle(). + * + * We include PREEMPT_ACTIVE to avoid cond_resched() from working + * before the scheduler is active -- see should_resched(). + */ +#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE) + /** * struct thread_group_cputimer - thread group interval timer counts * @cputime: thread group interval timers. diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 252b245cfcf..4be57ab0347 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -132,6 +132,11 @@ do { \ #endif /*__raw_spin_is_contended*/ #endif +/* The lock does not imply full memory barrier. */ +#ifndef ARCH_HAS_SMP_MB_AFTER_LOCK +static inline void smp_mb__after_lock(void) { smp_mb(); } +#endif + /** * spin_unlock_wait - wait until the spinlock gets unlocked * @lock: the spinlock in question. diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index fa4242cdade..80de7003d8c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -321,6 +321,8 @@ asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, siginfo_t __user *uinfo, const struct timespec __user *uts, size_t sigsetsize); +asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, + siginfo_t __user *uinfo); asmlinkage long sys_kill(int pid, int sig); asmlinkage long sys_tgkill(int tgid, int pid, int sig); asmlinkage long sys_tkill(int pid, int sig); diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 98a1d8cfb73..99adcdc0d3c 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -14,6 +14,8 @@ #ifndef _LINUX_SYSRQ_H #define _LINUX_SYSRQ_H +#include <linux/errno.h> + struct pt_regs; struct tty_struct; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 8a025d51090..95846d98801 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -318,6 +318,8 @@ struct v4l2_pix_format { /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ + /* * 10bit raw bayer, expanded to 16 bits * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 4d7e2272c42..11a4a2d3e36 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -155,6 +155,9 @@ enum { /* module cafe_ccic, just ident 8801 */ V4L2_IDENT_CAFE = 8801, + /* module mt9v011, just ident 8243 */ + V4L2_IDENT_MT9V011 = 8243, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, diff --git a/include/net/sock.h b/include/net/sock.h index 352f06bbd7a..2c0da9239b9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -54,6 +54,7 @@ #include <linux/filter.h> #include <linux/rculist_nulls.h> +#include <linux/poll.h> #include <asm/atomic.h> #include <net/dst.h> @@ -1241,6 +1242,74 @@ static inline int sk_has_allocations(const struct sock *sk) return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk); } +/** + * sk_has_sleeper - check if there are any waiting processes + * @sk: socket + * + * Returns true if socket has waiting processes + * + * The purpose of the sk_has_sleeper and sock_poll_wait is to wrap the memory + * barrier call. They were added due to the race found within the tcp code. + * + * Consider following tcp code paths: + * + * CPU1 CPU2 + * + * sys_select receive packet + * ... ... + * __add_wait_queue update tp->rcv_nxt + * ... ... + * tp->rcv_nxt check sock_def_readable + * ... { + * schedule ... + * if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + * wake_up_interruptible(sk->sk_sleep) + * ... + * } + * + * The race for tcp fires when the __add_wait_queue changes done by CPU1 stay + * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 + * could then endup calling schedule and sleep forever if there are no more + * data on the socket. + * + * The sk_has_sleeper is always called right after a call to read_lock, so we + * can use smp_mb__after_lock barrier. + */ +static inline int sk_has_sleeper(struct sock *sk) +{ + /* + * We need to be sure we are in sync with the + * add_wait_queue modifications to the wait queue. + * + * This memory barrier is paired in the sock_poll_wait. + */ + smp_mb__after_lock(); + return sk->sk_sleep && waitqueue_active(sk->sk_sleep); +} + +/** + * sock_poll_wait - place memory barrier behind the poll_wait call. + * @filp: file + * @wait_address: socket wait queue + * @p: poll_table + * + * See the comments in the sk_has_sleeper function. + */ +static inline void sock_poll_wait(struct file *filp, + wait_queue_head_t *wait_address, poll_table *p) +{ + if (p && wait_address) { + poll_wait(filp, wait_address, p); + /* + * We need to be sure we are in sync with the + * socket flags modification. + * + * This memory barrier is paired in the sk_has_sleeper. + */ + smp_mb(); + } +} + /* * Queue a received datagram if it will fit. Stream and sequenced * protocols can't normally use this as they need to fit buffers in diff --git a/kernel/exit.c b/kernel/exit.c index 628d41f0dd5..869dc221733 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -12,7 +12,6 @@ #include <linux/completion.h> #include <linux/personality.h> #include <linux/tty.h> -#include <linux/mnt_namespace.h> #include <linux/iocontext.h> #include <linux/key.h> #include <linux/security.h> diff --git a/kernel/fork.c b/kernel/fork.c index 467746b3f0a..bd295922887 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/completion.h> -#include <linux/mnt_namespace.h> #include <linux/personality.h> #include <linux/mempolicy.h> #include <linux/sem.h> diff --git a/kernel/kmod.c b/kernel/kmod.c index 7e95bedb2bf..385c31a1bdb 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -24,7 +24,6 @@ #include <linux/unistd.h> #include <linux/kmod.h> #include <linux/slab.h> -#include <linux/mnt_namespace.h> #include <linux/completion.h> #include <linux/file.h> #include <linux/fdtable.h> diff --git a/kernel/kprobes.c b/kernel/kprobes.c index c0fa54b276d..16b5739c516 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -237,13 +237,9 @@ static int __kprobes collect_garbage_slots(void) { struct kprobe_insn_page *kip; struct hlist_node *pos, *next; - int safety; /* Ensure no-one is preepmted on the garbages */ - mutex_unlock(&kprobe_insn_mutex); - safety = check_safety(); - mutex_lock(&kprobe_insn_mutex); - if (safety != 0) + if (check_safety()) return -EAGAIN; hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) { diff --git a/kernel/module.c b/kernel/module.c index 38928fcaff2..0a049837008 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2451,9 +2451,9 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, return ret; } if (ret > 0) { - printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, " - "it should follow 0/-E convention\n" - KERN_WARNING "%s: loading module anyway...\n", + printk(KERN_WARNING +"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" +"%s: loading module anyway...\n", __func__, mod->name, ret, __func__); dump_stack(); diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index d55a50da234..a641eb753b8 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -2020,7 +2020,7 @@ fail: static void perf_mmap_free_page(unsigned long addr) { - struct page *page = virt_to_page(addr); + struct page *page = virt_to_page((void *)addr); page->mapping = NULL; __free_page(page); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 61c78b2c07b..082c320e4db 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -181,8 +181,8 @@ int ptrace_attach(struct task_struct *task) * interference; SUID, SGID and LSM creds get determined differently * under ptrace. */ - retval = mutex_lock_interruptible(&task->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) goto out; task_lock(task); diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 0dccfbba6d2..7717b95c202 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1533,7 +1533,7 @@ void __init __rcu_init(void) int j; struct rcu_node *rnp; - printk(KERN_WARNING "Experimental hierarchical RCU implementation.\n"); + printk(KERN_INFO "Hierarchical RCU implementation.\n"); #ifdef CONFIG_RCU_CPU_STALL_DETECTOR printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n"); #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ @@ -1546,7 +1546,6 @@ void __init __rcu_init(void) rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i); /* Register notifier for non-boot CPUs */ register_cpu_notifier(&rcu_nb); - printk(KERN_WARNING "Experimental hierarchical RCU init done.\n"); } module_param(blimit, int, 0); diff --git a/kernel/sched.c b/kernel/sched.c index 7c9098d186e..01f55ada359 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6541,6 +6541,11 @@ SYSCALL_DEFINE0(sched_yield) return 0; } +static inline int should_resched(void) +{ + return need_resched() && !(preempt_count() & PREEMPT_ACTIVE); +} + static void __cond_resched(void) { #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP @@ -6560,8 +6565,7 @@ static void __cond_resched(void) int __sched _cond_resched(void) { - if (need_resched() && !(preempt_count() & PREEMPT_ACTIVE) && - system_state == SYSTEM_RUNNING) { + if (should_resched()) { __cond_resched(); return 1; } @@ -6579,12 +6583,12 @@ EXPORT_SYMBOL(_cond_resched); */ int cond_resched_lock(spinlock_t *lock) { - int resched = need_resched() && system_state == SYSTEM_RUNNING; + int resched = should_resched(); int ret = 0; if (spin_needbreak(lock) || resched) { spin_unlock(lock); - if (resched && need_resched()) + if (resched) __cond_resched(); else cpu_relax(); @@ -6599,7 +6603,7 @@ int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched() && system_state == SYSTEM_RUNNING) { + if (should_resched()) { local_bh_enable(); __cond_resched(); local_bh_disable(); diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 1551f47e766..019f380fd76 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -226,13 +226,13 @@ config BOOT_TRACER the timings of the initcalls and traces key events and the identity of tasks that can cause boot delays, such as context-switches. - Its aim is to be parsed by the /scripts/bootgraph.pl tool to + Its aim is to be parsed by the scripts/bootgraph.pl tool to produce pretty graphics about boot inefficiencies, giving a visual representation of the delays during initcalls - but the raw /debug/tracing/trace text output is readable too. - You must pass in ftrace=initcall to the kernel command line - to enable this on bootup. + You must pass in initcall_debug and ftrace=initcall to the kernel + command line to enable this on bootup. config TRACE_BRANCH_PROFILING bool diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f3716bf04df..bce9e01a29c 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3160,10 +3160,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, ret = proc_dointvec(table, write, file, buffer, lenp, ppos); - if (ret || !write || (last_ftrace_enabled == ftrace_enabled)) + if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) goto out; - last_ftrace_enabled = ftrace_enabled; + last_ftrace_enabled = !!ftrace_enabled; if (ftrace_enabled) { diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h index 5e32e375134..6db005e1248 100644 --- a/kernel/trace/trace_event_types.h +++ b/kernel/trace/trace_event_types.h @@ -26,6 +26,9 @@ TRACE_EVENT_FORMAT(funcgraph_exit, TRACE_GRAPH_RET, ftrace_graph_ret_entry, ignore, TRACE_STRUCT( TRACE_FIELD(unsigned long, ret.func, func) + TRACE_FIELD(unsigned long long, ret.calltime, calltime) + TRACE_FIELD(unsigned long long, ret.rettime, rettime) + TRACE_FIELD(unsigned long, ret.overrun, overrun) TRACE_FIELD(int, ret.depth, depth) ), TP_RAW_FMT("<-- %lx (%d)") diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 7938f3ae93e..e0c2545622e 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -27,8 +27,7 @@ void trace_print_seq(struct seq_file *m, struct trace_seq *s) { int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; - s->buffer[len] = 0; - seq_puts(m, s->buffer); + seq_write(m, s->buffer, len); trace_seq_init(s); } diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 2d7aebd71db..e644af91012 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -326,10 +326,10 @@ stack_trace_sysctl(struct ctl_table *table, int write, ret = proc_dointvec(table, write, file, buffer, lenp, ppos); if (ret || !write || - (last_stack_tracer_enabled == stack_tracer_enabled)) + (last_stack_tracer_enabled == !!stack_tracer_enabled)) goto out; - last_stack_tracer_enabled = stack_tracer_enabled; + last_stack_tracer_enabled = !!stack_tracer_enabled; if (stack_tracer_enabled) register_ftrace_function(&trace_ops); diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 3b93129a968..65b0d99b6d0 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -716,7 +716,7 @@ void dma_debug_init(u32 num_entries) for (i = 0; i < HASH_SIZE; ++i) { INIT_LIST_HEAD(&dma_entry_hash[i].list); - dma_entry_hash[i].lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&dma_entry_hash[i].lock); } if (dma_debug_fs_init() != 0) { @@ -856,22 +856,21 @@ static void check_for_stack(struct device *dev, void *addr) "stack [addr=%p]\n", addr); } -static inline bool overlap(void *addr, u64 size, void *start, void *end) +static inline bool overlap(void *addr, unsigned long len, void *start, void *end) { - void *addr2 = (char *)addr + size; + unsigned long a1 = (unsigned long)addr; + unsigned long b1 = a1 + len; + unsigned long a2 = (unsigned long)start; + unsigned long b2 = (unsigned long)end; - return ((addr >= start && addr < end) || - (addr2 >= start && addr2 < end) || - ((addr < start) && (addr2 >= end))); + return !(b1 <= a2 || a1 >= b2); } -static void check_for_illegal_area(struct device *dev, void *addr, u64 size) +static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len) { - if (overlap(addr, size, _text, _etext) || - overlap(addr, size, __start_rodata, __end_rodata)) - err_printk(dev, NULL, "DMA-API: device driver maps " - "memory from kernel text or rodata " - "[addr=%p] [size=%llu]\n", addr, size); + if (overlap(addr, len, _text, _etext) || + overlap(addr, len, __start_rodata, __end_rodata)) + err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len); } static void check_sync(struct device *dev, @@ -969,7 +968,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, entry->type = dma_debug_single; if (!PageHighMem(page)) { - void *addr = ((char *)page_address(page)) + offset; + void *addr = page_address(page) + offset; + check_for_stack(dev, addr); check_for_illegal_area(dev, addr, size); } diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 493b468a503..c86edd24429 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -283,7 +283,6 @@ static wait_queue_head_t congestion_wqh[2] = { __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) }; - void clear_bdi_congested(struct backing_dev_info *bdi, int sync) { enum bdi_state bit; @@ -308,18 +307,18 @@ EXPORT_SYMBOL(set_bdi_congested); /** * congestion_wait - wait for a backing_dev to become uncongested - * @rw: READ or WRITE + * @sync: SYNC or ASYNC IO * @timeout: timeout in jiffies * * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit * write congestion. If no backing_devs are congested then just wait for the * next write to be completed. */ -long congestion_wait(int rw, long timeout) +long congestion_wait(int sync, long timeout) { long ret; DEFINE_WAIT(wait); - wait_queue_head_t *wqh = &congestion_wqh[rw]; + wait_queue_head_t *wqh = &congestion_wqh[sync]; prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); ret = io_schedule_timeout(timeout); diff --git a/mm/filemap.c b/mm/filemap.c index 22396713feb..ccea3b665c1 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2272,6 +2272,7 @@ again: pagefault_enable(); flush_dcache_page(page); + mark_page_accessed(page); status = a_ops->write_end(file, mapping, pos, bytes, copied, page, fsdata); if (unlikely(status < 0)) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e2fa20dadf4..e717964cb5a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1973,7 +1973,7 @@ try_to_free: if (!progress) { nr_retries--; /* maybe some writeback is necessary */ - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 7687879253b..81627ebcd31 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -575,7 +575,7 @@ static void balance_dirty_pages(struct address_space *mapping) if (pages_written >= write_chunk) break; /* We've done our duty */ - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh && @@ -669,7 +669,7 @@ void throttle_vm_writeout(gfp_t gfp_mask) if (global_page_state(NR_UNSTABLE_NFS) + global_page_state(NR_WRITEBACK) <= dirty_thresh) break; - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * The caller might hold locks which can prevent IO completion @@ -715,7 +715,7 @@ static void background_writeout(unsigned long _min_pages) if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) { /* Wrote less than expected */ if (wbc.encountered_congestion || wbc.more_io) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); else break; } @@ -787,7 +787,7 @@ static void wb_kupdate(unsigned long arg) writeback_inodes(&wbc); if (wbc.nr_to_write > 0) { if (wbc.encountered_congestion || wbc.more_io) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); else break; /* All the old data is written */ } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e0f2cdf9d8b..a35eeab2724 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1666,7 +1666,7 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, preferred_zone, migratetype); if (!page && gfp_mask & __GFP_NOFAIL) - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (!page && (gfp_mask & __GFP_NOFAIL)); return page; @@ -1831,7 +1831,7 @@ rebalance: pages_reclaimed += did_some_progress; if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) { /* Wait for some write requests to complete then retry */ - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto rebalance; } @@ -1983,7 +1983,7 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask) unsigned long alloc_end = addr + (PAGE_SIZE << order); unsigned long used = addr + PAGE_ALIGN(size); - split_page(virt_to_page(addr), order); + split_page(virt_to_page((void *)addr), order); while (used < alloc_end) { free_page(used); used += PAGE_SIZE; diff --git a/mm/slab.c b/mm/slab.c index e74a16e4ced..7b5d4deacfc 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1544,9 +1544,6 @@ void __init kmem_cache_init(void) } g_cpucache_up = EARLY; - - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); } void __init kmem_cache_init_late(void) @@ -1563,6 +1560,9 @@ void __init kmem_cache_init_late(void) /* Done! */ g_cpucache_up = FULL; + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* * Register a cpu startup notifier callback that initializes * cpu_cache_get for all new cpus @@ -2547,7 +2547,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep) } if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) - synchronize_rcu(); + rcu_barrier(); __kmem_cache_destroy(cachep); mutex_unlock(&cache_chain_mutex); diff --git a/mm/slob.c b/mm/slob.c index c78742defdc..9641da3d5e5 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -595,6 +595,8 @@ EXPORT_SYMBOL(kmem_cache_create); void kmem_cache_destroy(struct kmem_cache *c) { kmemleak_free(c); + if (c->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); slob_free(c, sizeof(struct kmem_cache)); } EXPORT_SYMBOL(kmem_cache_destroy); diff --git a/mm/slub.c b/mm/slub.c index 819f056b39c..a9201d83178 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2595,6 +2595,8 @@ static inline int kmem_cache_close(struct kmem_cache *s) */ void kmem_cache_destroy(struct kmem_cache *s) { + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); down_write(&slub_lock); s->refcount--; if (!s->refcount) { diff --git a/mm/vmscan.c b/mm/vmscan.c index 54155268dfc..dea7abd3109 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1104,7 +1104,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, */ if (nr_freed < nr_taken && !current_is_kswapd() && lumpy_reclaim) { - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * The attempt at page out may have made some @@ -1721,7 +1721,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, /* Take a nap, wait for some writeback to complete */ if (sc->nr_scanned && priority < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } /* top priority shrink_zones still had more to do? don't OOM, then */ if (!sc->all_unreclaimable && scanning_global_lru(sc)) @@ -1960,7 +1960,7 @@ loop_again: * another pass across the zones. */ if (total_scanned && priority < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * We do this so kswapd doesn't build up large priorities for @@ -2233,7 +2233,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) goto out; if (sc.nr_scanned && prio < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ / 10); + congestion_wait(BLK_RW_ASYNC, HZ / 10); } } diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a2a1814c7a8..8c2588e4edc 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) if (!*p) continue; token = match_token(p, tokens, args); - r = match_int(&args[0], &option); - if (r < 0) { - P9_DPRINTK(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; + if (token != Opt_err) { + r = match_int(&args[0], &option); + if (r < 0) { + P9_DPRINTK(P9_DEBUG_ERROR, + "integer field, but no integer?\n"); + ret = r; + continue; + } } switch (token) { case Opt_port: diff --git a/net/atm/common.c b/net/atm/common.c index c1c97936192..8c4d843eb17 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -92,7 +92,7 @@ static void vcc_sock_destruct(struct sock *sk) static void vcc_def_wakeup(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up(sk->sk_sleep); read_unlock(&sk->sk_callback_lock); } @@ -110,7 +110,7 @@ static void vcc_write_space(struct sock *sk) read_lock(&sk->sk_callback_lock); if (vcc_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); @@ -594,7 +594,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) struct atm_vcc *vcc; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; vcc = ATM_SD(sock); diff --git a/net/core/datagram.c b/net/core/datagram.c index 58abee1f1df..b0fe69211ee 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -712,7 +712,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9675f312830..df30feb2fc7 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -740,7 +740,7 @@ int netpoll_setup(struct netpoll *np) np->name); break; } - cond_resched(); + msleep(1); } /* If carrier appears to come up instantly, we don't diff --git a/net/core/sock.c b/net/core/sock.c index b0ba569bc97..6354863b1c6 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1715,7 +1715,7 @@ EXPORT_SYMBOL(sock_no_sendpage); static void sock_def_wakeup(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_all(sk->sk_sleep); read_unlock(&sk->sk_callback_lock); } @@ -1723,7 +1723,7 @@ static void sock_def_wakeup(struct sock *sk) static void sock_def_error_report(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_poll(sk->sk_sleep, POLLERR); sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); read_unlock(&sk->sk_callback_lock); @@ -1732,7 +1732,7 @@ static void sock_def_error_report(struct sock *sk) static void sock_def_readable(struct sock *sk, int len) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); @@ -1747,7 +1747,7 @@ static void sock_def_write_space(struct sock *sk) * progress. --DaveM */ if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND); diff --git a/net/dccp/output.c b/net/dccp/output.c index c0e88c16d08..c96119fda68 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -196,7 +196,7 @@ void dccp_write_space(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 314a1b5c033..94ca8eaace7 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -311,7 +311,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, unsigned int mask; struct sock *sk = sock->sk; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == DCCP_LISTEN) return inet_csk_listen_poll(sk); diff --git a/net/dsa/mv88e6xxx.c b/net/dsa/mv88e6xxx.c index 4e4d8b5ad03..efe661a9def 100644 --- a/net/dsa/mv88e6xxx.c +++ b/net/dsa/mv88e6xxx.c @@ -418,7 +418,7 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds) int i; for (i = 0; i < 10; i++) { - ret = REG_READ(REG_GLOBAL2, 0x1d); + ret = REG_READ(REG_GLOBAL, 0x1d); if ((ret & 0x8000) == 0) return 0; } diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 00a54b246df..63c2fa7b68c 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -316,8 +316,8 @@ static inline void check_tnode(const struct tnode *tn) static const int halve_threshold = 25; static const int inflate_threshold = 50; -static const int halve_threshold_root = 8; -static const int inflate_threshold_root = 15; +static const int halve_threshold_root = 15; +static const int inflate_threshold_root = 25; static void __alias_free_mem(struct rcu_head *head) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7870a535dac..91145244ea6 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -339,7 +339,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) struct sock *sk = sock->sk; struct tcp_sock *tp = tcp_sk(sk); - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == TCP_LISTEN) return inet_csk_listen_poll(sk); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 60d918c96a4..0071ee6f441 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -136,7 +136,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: - if (pskb_may_pull(skb, xprth + 4 - skb->data)) { + if (xprth + 4 < skb->data || + pskb_may_pull(skb, xprth + 4 - skb->data)) { __be16 *ports = (__be16 *)xprth; fl->fl_ip_sport = ports[!!reverse]; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3883b4036a7..43b3c9f89c1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1916,8 +1916,32 @@ ok: update_lft = 1; else if (stored_lft <= MIN_VALID_LIFETIME) { /* valid_lft <= stored_lft is always true */ - /* XXX: IPsec */ - update_lft = 0; + /* + * RFC 4862 Section 5.5.3e: + * "Note that the preferred lifetime of + * the corresponding address is always + * reset to the Preferred Lifetime in + * the received Prefix Information + * option, regardless of whether the + * valid lifetime is also reset or + * ignored." + * + * So if the preferred lifetime in + * this advertisement is different + * than what we have stored, but the + * valid lifetime is invalid, just + * reset prefered_lft. + * + * We must set the valid lifetime + * to the stored lifetime since we'll + * be updating the timestamp below, + * else we'll set it back to the + * minumum. + */ + if (prefered_lft != ifp->prefered_lft) { + valid_lft = stored_lft; + update_lft = 1; + } } else { valid_lft = MIN_VALID_LIFETIME; if (valid_lft < prefered_lft) @@ -3085,7 +3109,7 @@ restart: spin_unlock(&ifp->lock); continue; } else if (age >= ifp->prefered_lft) { - /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ + /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */ int deprecate = 0; if (!(ifp->flags&IFA_F_DEPRECATED)) { diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b4b16a43f27..3a3c677bc0f 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); - while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { + while (nh + offset + 1 < skb->data || + pskb_may_pull(skb, nh + offset + 1 - skb->data)) { nh = skb_network_header(skb); exthdr = (struct ipv6_opt_hdr *)(nh + offset); @@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: - if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { + if (!onlyproto && (nh + offset + 4 < skb->data || + pskb_may_pull(skb, nh + offset + 4 - skb->data))) { __be16 *ports = (__be16 *)exthdr; fl->fl_ip_sport = ports[!!reverse]; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 6be5f92d109..49c15b48408 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -306,7 +306,7 @@ static inline int iucv_below_msglim(struct sock *sk) static void iucv_sock_wake_msglim(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_all(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); read_unlock(&sk->sk_callback_lock); @@ -1256,7 +1256,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk; unsigned int mask = 0; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == IUCV_LISTEN) return iucv_accept_poll(sk); diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 003cb470ac8..f49ef288e2e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -637,7 +637,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; - preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); + preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); if (!preq_node) { printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); return; diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b218b98fba7..37771abd8f5 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -66,7 +66,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) for (i = rix; i >= 0; i--) if (mi->r[i].rix == rix) break; - WARN_ON(mi->r[i].rix != rix); + WARN_ON(i < 0); return i; } @@ -181,6 +181,9 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, break; ndx = rix_to_ndx(mi, ar[i].idx); + if (ndx < 0) + continue; + mi->r[ndx].attempts += ar[i].count; if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index eac5e7bb736..bfe493ebf27 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -63,7 +63,7 @@ static void rxrpc_write_space(struct sock *sk) _enter("%p", sk); read_lock(&sk->sk_callback_lock); if (rxrpc_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } @@ -588,7 +588,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, unsigned int mask; struct sock *sk = sock->sk; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* the socket is readable if there are any messages waiting on the Rx diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 35ba035970a..971890dbfea 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) finish_wait(sk->sk_sleep, &wait); } -static void sctp_sock_rfree_frag(struct sk_buff *skb) -{ - struct sk_buff *frag; - - if (!skb->data_len) - goto done; - - /* Don't forget the fragments. */ - skb_walk_frags(skb, frag) - sctp_sock_rfree_frag(frag); - -done: - sctp_sock_rfree(skb); -} - static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) { struct sk_buff *frag; @@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsk->sk_receive_queue); __skb_queue_tail(&newsk->sk_receive_queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsp->pd_lobby); __skb_queue_tail(queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, } - sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } - sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } /* Set the type of socket to indicate that it is peeled off from the * original UDP-style socket or created with the accept() call on a diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 36d4e44d623..fc3ebb90691 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk) { read_lock(&sk->sk_callback_lock); if (unix_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } @@ -1985,7 +1985,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table struct sock *sk = sock->sk; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ @@ -2022,7 +2022,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk, *other; unsigned int mask, writable; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ @@ -2053,7 +2053,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, other = unix_peer_get(sk); if (other) { if (unix_peer(other) != sk) { - poll_wait(file, &unix_sk(other)->peer_wait, + sock_poll_wait(file, &unix_sk(other)->peer_wait, wait); if (unix_recvq_full(other)) writable = 0; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 241bddd0b4f..43bdb1372ca 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -447,6 +447,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) rdev = __cfg80211_drv_from_info(info); if (IS_ERR(rdev)) { + mutex_unlock(&cfg80211_mutex); result = PTR_ERR(rdev); goto unlock; } diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e95b638b919..f8e71b30000 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -366,7 +366,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, found = rb_find_bss(dev, res); if (found) { - kref_get(&found->ref); found->pub.beacon_interval = res->pub.beacon_interval; found->pub.tsf = res->pub.tsf; found->pub.signal = res->pub.signal; diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index e617acaf10e..61b8ab39800 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -644,7 +644,7 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * int err; int capture=1; - /* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */ + /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */ emu->p16v_device_offset = device; if (rpcm) *rpcm = NULL; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index dd1ab617784..9efd27f6b52 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -296,9 +296,10 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, struct snd_usX2Y_substream *subs, struct urb *urb) { - snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" - KERN_ERR "Most propably some urb of usb-frame %i is still missing.\n" - KERN_ERR "Cause could be too long delays in usb-hcd interrupt handling.\n", + snd_printk(KERN_ERR +"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" +"Most propably some urb of usb-frame %i is still missing.\n" +"Cause could be too long delays in usb-hcd interrupt handling.\n", usb_get_current_frame_number(usX2Y->chip.dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 9c6d0ae3708..7822b3d6bac 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -164,7 +164,7 @@ endif # CFLAGS and LDFLAGS are for the users to override from the command line. -CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 +CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 LDFLAGS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) ALL_LDFLAGS = $(LDFLAGS) @@ -223,7 +223,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ # Those must not be GNU-specific; they are shared with perl/ which may # be built by a different compiler. (Note that this is an artifact now # but it still might be nice to keep that distinction.) -BASIC_CFLAGS = +BASIC_CFLAGS = -Iutil/include BASIC_LDFLAGS = # Guard against environment variables @@ -289,10 +289,11 @@ export PERL_PATH LIB_FILE=libperf.a LIB_H += ../../include/linux/perf_counter.h +LIB_H += ../../include/linux/rbtree.h +LIB_H += ../../include/linux/list.h +LIB_H += util/include/linux/list.h LIB_H += perf.h LIB_H += util/types.h -LIB_H += util/list.h -LIB_H += util/rbtree.h LIB_H += util/levenshtein.h LIB_H += util/parse-options.h LIB_H += util/parse-events.h @@ -305,6 +306,7 @@ LIB_H += util/strlist.h LIB_H += util/run-command.h LIB_H += util/sigchain.h LIB_H += util/symbol.h +LIB_H += util/module.h LIB_H += util/color.h LIB_OBJS += util/abspath.o @@ -328,6 +330,7 @@ LIB_OBJS += util/usage.o LIB_OBJS += util/wrapper.o LIB_OBJS += util/sigchain.o LIB_OBJS += util/symbol.o +LIB_OBJS += util/module.o LIB_OBJS += util/color.o LIB_OBJS += util/pager.o LIB_OBJS += util/header.o @@ -381,12 +384,6 @@ ifndef CC_LD_DYNPATH endif endif -ifdef ZLIB_PATH - BASIC_CFLAGS += -I$(ZLIB_PATH)/include - EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib) -endif -EXTLIBS += -lz - ifdef NEEDS_SOCKET EXTLIBS += -lsocket endif @@ -697,6 +694,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS util/config.o: util/config.c PERF-CFLAGS $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS + $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< + perf-%$X: %.o $(PERFLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 722c0f54e54..5f9eefecc57 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -10,9 +10,9 @@ #include "util/util.h" #include "util/color.h" -#include "util/list.h" +#include <linux/list.h> #include "util/cache.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/symbol.h" #include "util/string.h" @@ -25,10 +25,6 @@ #define SHOW_USER 2 #define SHOW_HV 4 -#define MIN_GREEN 0.5 -#define MIN_RED 5.0 - - static char const *input_name = "perf.data"; static char *vmlinux = "vmlinux"; @@ -43,6 +39,10 @@ static int dump_trace = 0; static int verbose; +static int modules; + +static int full_paths; + static int print_line; static unsigned long page_size; @@ -160,7 +160,7 @@ static void dsos__fprintf(FILE *fp) static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) { - return dso__find_symbol(kernel_dso, ip); + return dso__find_symbol(dso, ip); } static int load_kernel(void) @@ -171,8 +171,8 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); - if (err) { + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); + if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; } else @@ -203,7 +203,7 @@ static u64 map__map_ip(struct map *map, u64 ip) return ip - map->start + map->pgoff; } -static u64 vdso__map_ip(struct map *map, u64 ip) +static u64 vdso__map_ip(struct map *map __used, u64 ip) { return ip; } @@ -600,7 +600,7 @@ static LIST_HEAD(hist_entry__sort_list); static int sort_dimension__add(char *tok) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { struct sort_dimension *sd = &sort_dimensions[i]; @@ -1043,24 +1043,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) return 0; } -static char *get_color(double percent) -{ - char *color = PERF_COLOR_NORMAL; - - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (percent >= MIN_RED) - color = PERF_COLOR_RED; - else { - if (percent > MIN_GREEN) - color = PERF_COLOR_GREEN; - } - return color; -} - static int parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) { @@ -1069,7 +1051,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) static const char *prev_color; unsigned int offset; size_t line_len; - u64 line_ip; + s64 line_ip; int ret; char *c; @@ -1122,7 +1104,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) } else if (sym->hist_sum) percent = 100.0 * hits / sym->hist_sum; - color = get_color(percent); + color = get_percent_color(percent); /* * Also color the filename and line if needed, with @@ -1258,7 +1240,7 @@ static void print_summary(char *filename) sym_ext = rb_entry(node, struct sym_ext, node); percent = sym_ext->percent; - color = get_color(percent); + color = get_percent_color(percent); path = sym_ext->path; color_fprintf(stdout, color, " %7.2f %s", percent, path); @@ -1268,19 +1250,25 @@ static void print_summary(char *filename) static void annotate_sym(struct dso *dso, struct symbol *sym) { - char *filename = dso->name; + char *filename = dso->name, *d_filename; u64 start, end, len; char command[PATH_MAX*2]; FILE *file; if (!filename) return; - if (dso == kernel_dso) + if (sym->module) + filename = sym->module->path; + else if (dso == kernel_dso) filename = vmlinux; start = sym->obj_start; if (!start) start = sym->start; + if (full_paths) + d_filename = filename; + else + d_filename = basename(filename); end = start + sym->end - sym->start + 1; len = sym->end - sym->start; @@ -1291,13 +1279,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) } printf("\n\n------------------------------------------------\n"); - printf(" Percent | Source code & Disassembly of %s\n", filename); + printf(" Percent | Source code & Disassembly of %s\n", d_filename); printf("------------------------------------------------\n"); if (verbose >= 2) printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); - sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); + sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", + (u64)start, (u64)end, filename, filename); if (verbose >= 3) printf("doing: %s\n", command); @@ -1428,7 +1417,7 @@ more: head += size; - if (offset + head < stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; rc = EXIT_SUCCESS; @@ -1472,8 +1461,12 @@ static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), + OPT_BOOLEAN('m', "modules", &modules, + "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_BOOLEAN('l', "print-line", &print_line, "print matching source lines (may be slow)"), + OPT_BOOLEAN('P', "full-paths", &full_paths, + "Don't shorten the displayed pathnames"), OPT_END() }; @@ -1492,7 +1485,7 @@ static void setup_sorting(void) free(str); } -int cmd_annotate(int argc, const char **argv, const char *prefix) +int cmd_annotate(int argc, const char **argv, const char *prefix __used) { symbol__init(); diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 0f32dc3f3c4..2599d86a733 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -3,6 +3,7 @@ * * Builtin help command */ +#include "perf.h" #include "util/cache.h" #include "builtin.h" #include "util/exec_cmd.h" @@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds; void list_common_cmds_help(void) { - int i, longest = 0; + unsigned int i, longest = 0; for (i = 0; i < ARRAY_SIZE(common_cmds); i++) { if (longest < strlen(common_cmds[i].name)) @@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd) open_html(page_path.buf); } -int cmd_help(int argc, const char **argv, const char *prefix) +int cmd_help(int argc, const char **argv, const char *prefix __used) { const char *alias; + load_command_list("perf-", &main_cmds, &other_cmds); perf_config(perf_help_config, NULL); diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index fe60e37c96e..f990fa8a35c 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -13,7 +13,7 @@ #include "util/parse-options.h" #include "util/parse-events.h" -int cmd_list(int argc, const char **argv, const char *prefix) +int cmd_list(int argc __used, const char **argv __used, const char *prefix __used) { print_events(); return 0; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d18546f37d7..4ef78a5e6f3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -294,7 +294,7 @@ static void pid_synthesize_mmap_samples(pid_t pid) while (1) { char bf[BUFSIZ], *pbf = bf; struct mmap_event mmap_ev = { - .header.type = PERF_EVENT_MMAP, + .header = { .type = PERF_EVENT_MMAP }, }; int n; size_t size; @@ -650,7 +650,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_record(int argc, const char **argv, const char *prefix) +int cmd_record(int argc, const char **argv, const char *prefix __used) { int counter; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 135b7837e6b..4e5cc266311 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -10,9 +10,9 @@ #include "util/util.h" #include "util/color.h" -#include "util/list.h" +#include <linux/list.h> #include "util/cache.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/symbol.h" #include "util/string.h" #include "util/callchain.h" @@ -46,6 +46,8 @@ static int dump_trace = 0; static int verbose; #define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) +static int modules; + static int full_paths; static unsigned long page_size; @@ -56,8 +58,17 @@ static char *parent_pattern = default_parent_pattern; static regex_t parent_regex; static int exclude_other = 1; + +static char callchain_default_opt[] = "fractal,0.5"; + static int callchain; +static +struct callchain_param callchain_param = { + .mode = CHAIN_GRAPH_ABS, + .min_percent = 0.5 +}; + static u64 sample_type; struct ip_event { @@ -121,6 +132,7 @@ typedef union event_union { static LIST_HEAD(dsos); static struct dso *kernel_dso; static struct dso *vdso; +static struct dso *hypervisor_dso; static void dsos__add(struct dso *dso) { @@ -176,7 +188,7 @@ static void dsos__fprintf(FILE *fp) static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) { - return dso__find_symbol(kernel_dso, ip); + return dso__find_symbol(dso, ip); } static int load_kernel(void) @@ -187,8 +199,8 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); - if (err) { + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); + if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; } else @@ -202,6 +214,11 @@ static int load_kernel(void) dsos__add(vdso); + hypervisor_dso = dso__new("[hypervisor]", 0); + if (!hypervisor_dso) + return -1; + dsos__add(hypervisor_dso); + return err; } @@ -233,7 +250,7 @@ static u64 map__map_ip(struct map *map, u64 ip) return ip - map->start + map->pgoff; } -static u64 vdso__map_ip(struct map *map, u64 ip) +static u64 vdso__map_ip(struct map *map __used, u64 ip) { return ip; } @@ -640,7 +657,11 @@ sort__sym_print(FILE *fp, struct hist_entry *self) if (self->sym) { ret += fprintf(fp, "[%c] %s", - self->dso == kernel_dso ? 'k' : '.', self->sym->name); + self->dso == kernel_dso ? 'k' : + self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); + + if (self->sym->module) + ret += fprintf(fp, "\t[%s]", self->sym->module->name); } else { ret += fprintf(fp, "%#016llx", (u64)self->ip); } @@ -705,7 +726,7 @@ static LIST_HEAD(hist_entry__sort_list); static int sort_dimension__add(char *tok) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { struct sort_dimension *sd = &sort_dimensions[i]; @@ -775,8 +796,109 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) return cmp; } +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) +{ + int i; + size_t ret = 0; + + ret += fprintf(fp, "%s", " "); + + for (i = 0; i < depth; i++) + if (depth_mask & (1 << i)) + ret += fprintf(fp, "| "); + else + ret += fprintf(fp, " "); + + ret += fprintf(fp, "\n"); + + return ret; +} +static size_t +ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, + int depth_mask, int count, u64 total_samples, + int hits) +{ + int i; + size_t ret = 0; + + ret += fprintf(fp, "%s", " "); + for (i = 0; i < depth; i++) { + if (depth_mask & (1 << i)) + ret += fprintf(fp, "|"); + else + ret += fprintf(fp, " "); + if (!count && i == depth - 1) { + double percent; + + percent = hits * 100.0 / total_samples; + ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); + } else + ret += fprintf(fp, "%s", " "); + } + if (chain->sym) + ret += fprintf(fp, "%s\n", chain->sym->name); + else + ret += fprintf(fp, "%p\n", (void *)(long)chain->ip); + + return ret; +} + +static size_t +callchain__fprintf_graph(FILE *fp, struct callchain_node *self, + u64 total_samples, int depth, int depth_mask) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 new_total; + size_t ret = 0; + int i; + + if (callchain_param.mode == CHAIN_GRAPH_REL) + new_total = self->cumul_hit; + else + new_total = total_samples; + + node = rb_first(&self->rb_root); + while (node) { + child = rb_entry(node, struct callchain_node, rb_node); + + /* + * The depth mask manages the output of pipes that show + * the depth. We don't want to keep the pipes of the current + * level for the last child of this depth + */ + next = rb_next(node); + if (!next) + new_depth_mask &= ~(1 << (depth - 1)); + + /* + * But we keep the older depth mask for the line seperator + * to keep the level link until we reach the last child + */ + ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); + i = 0; + list_for_each_entry(chain, &child->val, list) { + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + ret += ipchain__fprintf_graph(fp, chain, depth, + new_depth_mask, i++, + new_total, + child->cumul_hit); + } + ret += callchain__fprintf_graph(fp, child, new_total, + depth + 1, + new_depth_mask | (1 << depth)); + node = next; + } + + return ret; +} + static size_t -callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) +callchain__fprintf_flat(FILE *fp, struct callchain_node *self, + u64 total_samples) { struct callchain_list *chain; size_t ret = 0; @@ -784,11 +906,18 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) if (!self) return 0; - ret += callchain__fprintf(fp, self->parent, total_samples); + ret += callchain__fprintf_flat(fp, self->parent, total_samples); - list_for_each_entry(chain, &self->val, list) - ret += fprintf(fp, " %p\n", (void *)chain->ip); + list_for_each_entry(chain, &self->val, list) { + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + if (chain->sym) + ret += fprintf(fp, " %s\n", chain->sym->name); + else + ret += fprintf(fp, " %p\n", + (void *)(long)chain->ip); + } return ret; } @@ -807,8 +936,19 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; - ret += fprintf(fp, " %6.2f%%\n", percent); - ret += callchain__fprintf(fp, chain, total_samples); + switch (callchain_param.mode) { + case CHAIN_FLAT: + ret += percent_color_fprintf(fp, " %6.2f%%\n", + percent); + ret += callchain__fprintf_flat(fp, chain, total_samples); + break; + case CHAIN_GRAPH_ABS: /* Falldown */ + case CHAIN_GRAPH_REL: + ret += callchain__fprintf_graph(fp, chain, + total_samples, 1, 1); + default: + break; + } ret += fprintf(fp, "\n"); rb_node = rb_next(rb_node); } @@ -826,25 +966,10 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) if (exclude_other && !self->parent) return 0; - if (total_samples) { - double percent = self->count * 100.0 / total_samples; - char *color = PERF_COLOR_NORMAL; - - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (percent >= 5.0) { - color = PERF_COLOR_RED; - } else { - if (percent >= 0.5) - color = PERF_COLOR_GREEN; - } - - ret = color_fprintf(fp, color, " %6.2f%%", + if (total_samples) + ret = percent_color_fprintf(fp, " %6.2f%%", (self->count * 100.0) / total_samples); - } else + else ret = fprintf(fp, "%12Ld ", self->count); list_for_each_entry(se, &hist_entry__sort_list, list) { @@ -923,6 +1048,58 @@ static int call__match(struct symbol *sym) return 0; } +static struct symbol ** +resolve_callchain(struct thread *thread, struct map *map __used, + struct ip_callchain *chain, struct hist_entry *entry) +{ + u64 context = PERF_CONTEXT_MAX; + struct symbol **syms = NULL; + unsigned int i; + + if (callchain) { + syms = calloc(chain->nr, sizeof(*syms)); + if (!syms) { + fprintf(stderr, "Can't allocate memory for symbols\n"); + exit(-1); + } + } + + for (i = 0; i < chain->nr; i++) { + u64 ip = chain->ips[i]; + struct dso *dso = NULL; + struct symbol *sym; + + if (ip >= PERF_CONTEXT_MAX) { + context = ip; + continue; + } + + switch (context) { + case PERF_CONTEXT_HV: + dso = hypervisor_dso; + break; + case PERF_CONTEXT_KERNEL: + dso = kernel_dso; + break; + default: + break; + } + + sym = resolve_symbol(thread, NULL, &dso, &ip); + + if (sym) { + if (sort__has_parent && call__match(sym) && + !entry->parent) + entry->parent = sym; + if (!callchain) + break; + syms[i] = sym; + } + } + + return syms; +} + /* * collect histogram counts */ @@ -935,6 +1112,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, struct rb_node **p = &hist.rb_node; struct rb_node *parent = NULL; struct hist_entry *he; + struct symbol **syms = NULL; struct hist_entry entry = { .thread = thread, .map = map, @@ -948,36 +1126,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, }; int cmp; - if (sort__has_parent && chain) { - u64 context = PERF_CONTEXT_MAX; - int i; - - for (i = 0; i < chain->nr; i++) { - u64 ip = chain->ips[i]; - struct dso *dso = NULL; - struct symbol *sym; - - if (ip >= PERF_CONTEXT_MAX) { - context = ip; - continue; - } - - switch (context) { - case PERF_CONTEXT_KERNEL: - dso = kernel_dso; - break; - default: - break; - } - - sym = resolve_symbol(thread, NULL, &dso, &ip); - - if (sym && call__match(sym)) { - entry.parent = sym; - break; - } - } - } + if ((sort__has_parent || callchain) && chain) + syms = resolve_callchain(thread, map, chain, &entry); while (*p != NULL) { parent = *p; @@ -987,8 +1137,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, if (!cmp) { he->count += count; - if (callchain) - append_chain(&he->callchain, chain); + if (callchain) { + append_chain(&he->callchain, chain, syms); + free(syms); + } return 0; } @@ -1004,7 +1156,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, *he = entry; if (callchain) { callchain_init(&he->callchain); - append_chain(&he->callchain, chain); + append_chain(&he->callchain, chain, syms); + free(syms); } rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, &hist); @@ -1076,14 +1229,15 @@ static void collapse__resort(void) static struct rb_root output_hists; -static void output__insert_entry(struct hist_entry *he) +static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits) { struct rb_node **p = &output_hists.rb_node; struct rb_node *parent = NULL; struct hist_entry *iter; if (callchain) - sort_chain_to_rbtree(&he->sorted_chain, &he->callchain); + callchain_param.sort(&he->sorted_chain, &he->callchain, + min_callchain_hits, &callchain_param); while (*p != NULL) { parent = *p; @@ -1099,11 +1253,14 @@ static void output__insert_entry(struct hist_entry *he) rb_insert_color(&he->rb_node, &output_hists); } -static void output__resort(void) +static void output__resort(u64 total_samples) { struct rb_node *next; struct hist_entry *n; struct rb_root *tree = &hist; + u64 min_callchain_hits; + + min_callchain_hits = total_samples * (callchain_param.min_percent / 100); if (sort__need_collapse) tree = &collapse_hists; @@ -1115,7 +1272,7 @@ static void output__resort(void) next = rb_next(&n->rb_node); rb_erase(&n->rb_node, tree); - output__insert_entry(n); + output__insert_entry(n, min_callchain_hits); } } @@ -1141,7 +1298,7 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) fprintf(fp, "# ........"); list_for_each_entry(se, &hist_entry__sort_list, list) { - int i; + unsigned int i; if (exclude_other && (se == &sort_parent)) continue; @@ -1213,6 +1370,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) struct map *map = NULL; void *more_data = event->ip.__more_data; struct ip_callchain *chain = NULL; + int cpumode; if (sample_type & PERF_SAMPLE_PERIOD) { period = *(u64 *)more_data; @@ -1228,7 +1386,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) (long long)period); if (sample_type & PERF_SAMPLE_CALLCHAIN) { - int i; + unsigned int i; chain = (void *)more_data; @@ -1256,7 +1414,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if (comm_list && !strlist__has_entry(comm_list, thread->comm)) return 0; - if (event->header.misc & PERF_EVENT_MISC_KERNEL) { + cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK; + + if (cpumode == PERF_EVENT_MISC_KERNEL) { show = SHOW_KERNEL; level = 'k'; @@ -1264,7 +1424,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) dprintf(" ...... dso: %s\n", dso->name); - } else if (event->header.misc & PERF_EVENT_MISC_USER) { + } else if (cpumode == PERF_EVENT_MISC_USER) { show = SHOW_USER; level = '.'; @@ -1272,6 +1432,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) } else { show = SHOW_HV; level = 'H'; + + dso = hypervisor_dso; + dprintf(" ...... dso: [hypervisor]\n"); } @@ -1534,9 +1697,19 @@ static int __cmd_report(void) sample_type = perf_header__sample_type(); - if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { - fprintf(stderr, "selected --sort parent, but no callchain data\n"); - exit(-1); + if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { + if (sort__has_parent) { + fprintf(stderr, "selected --sort parent, but no" + " callchain data. Did you call" + " perf record without -g?\n"); + exit(-1); + } + if (callchain) { + fprintf(stderr, "selected -c but no callchain data." + " Did you call perf record without" + " -g?\n"); + exit(-1); + } } if (load_kernel() < 0) { @@ -1619,7 +1792,7 @@ more: if (offset + head >= header->data_offset + header->data_size) goto done; - if (offset + head < stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; done: @@ -1643,12 +1816,58 @@ done: dsos__fprintf(stdout); collapse__resort(); - output__resort(); + output__resort(total); output__fprintf(stdout, total); return rc; } +static int +parse_callchain_opt(const struct option *opt __used, const char *arg, + int unset __used) +{ + char *tok; + char *endptr; + + callchain = 1; + + if (!arg) + return 0; + + tok = strtok((char *)arg, ","); + if (!tok) + return -1; + + /* get the output mode */ + if (!strncmp(tok, "graph", strlen(arg))) + callchain_param.mode = CHAIN_GRAPH_ABS; + + else if (!strncmp(tok, "flat", strlen(arg))) + callchain_param.mode = CHAIN_FLAT; + + else if (!strncmp(tok, "fractal", strlen(arg))) + callchain_param.mode = CHAIN_GRAPH_REL; + + else + return -1; + + /* get the min percentage */ + tok = strtok(NULL, ","); + if (!tok) + goto setup; + + callchain_param.min_percent = strtod(tok, &endptr); + if (tok == endptr) + return -1; + +setup: + if (register_callchain_param(&callchain_param) < 0) { + fprintf(stderr, "Can't register callchain params\n"); + return -1; + } + return 0; +} + static const char * const report_usage[] = { "perf report [<options>] <command>", NULL @@ -1662,6 +1881,8 @@ static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), + OPT_BOOLEAN('m', "modules", &modules, + "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): pid, comm, dso, symbol, parent"), OPT_BOOLEAN('P', "full-paths", &full_paths, @@ -1670,7 +1891,9 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &exclude_other, "Only display entries with parent-match"), - OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), + OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent", + "Display callchains using output_type and min percent threshold. " + "Default: flat,0", &parse_callchain_opt, callchain_default_opt), OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", @@ -1708,7 +1931,7 @@ static void setup_list(struct strlist **list, const char *list_str, } } -int cmd_report(int argc, const char **argv, const char *prefix) +int cmd_report(int argc, const char **argv, const char *prefix __used) { symbol__init(); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 2e03524a1de..27921a8ce1a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -64,7 +64,7 @@ static struct perf_counter_attr default_attrs[] = { static int system_wide = 0; static int verbose = 0; -static int nr_cpus = 0; +static unsigned int nr_cpus = 0; static int run_idx = 0; static int run_count = 1; @@ -96,6 +96,10 @@ static u64 walltime_nsecs_noise; static u64 runtime_cycles_avg; static u64 runtime_cycles_noise; +#define MATCH_EVENT(t, c, counter) \ + (attrs[counter].type == PERF_TYPE_##t && \ + attrs[counter].config == PERF_COUNT_##c) + #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" @@ -108,7 +112,8 @@ static void create_perf_stat_counter(int counter, int pid) PERF_FORMAT_TOTAL_TIME_RUNNING; if (system_wide) { - int cpu; + unsigned int cpu; + for (cpu = 0; cpu < nr_cpus; cpu++) { fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); if (fd[cpu][counter] < 0 && verbose) @@ -132,13 +137,8 @@ static void create_perf_stat_counter(int counter, int pid) */ static inline int nsec_counter(int counter) { - if (attrs[counter].type != PERF_TYPE_SOFTWARE) - return 0; - - if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK) - return 1; - - if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) + if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || + MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) return 1; return 0; @@ -150,8 +150,8 @@ static inline int nsec_counter(int counter) static void read_counter(int counter) { u64 *count, single_count[3]; - ssize_t res; - int cpu, nv; + unsigned int cpu; + size_t res, nv; int scaled; count = event_res[run_idx][counter]; @@ -165,6 +165,7 @@ static void read_counter(int counter) res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); assert(res == nv * sizeof(u64)); + close(fd[cpu][counter]); fd[cpu][counter] = -1; @@ -192,15 +193,13 @@ static void read_counter(int counter) /* * Save the full runtime - to allow normalization during printout: */ - if (attrs[counter].type == PERF_TYPE_SOFTWARE && - attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) + if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) runtime_nsecs[run_idx] = count[0]; - if (attrs[counter].type == PERF_TYPE_HARDWARE && - attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) + if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) runtime_cycles[run_idx] = count[0]; } -static int run_perf_stat(int argc, const char **argv) +static int run_perf_stat(int argc __used, const char **argv) { unsigned long long t0, t1; int status = 0; @@ -240,7 +239,8 @@ static int run_perf_stat(int argc, const char **argv) /* * Wait until the parent tells us to go. */ - read(go_pipe[0], &buf, 1); + if (read(go_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); execvp(argv[0], (char **)argv); @@ -253,7 +253,8 @@ static int run_perf_stat(int argc, const char **argv) */ close(child_ready_pipe[1]); close(go_pipe[0]); - read(child_ready_pipe[0], &buf, 1); + if (read(child_ready_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); close(child_ready_pipe[0]); for (counter = 0; counter < nr_counters; counter++) @@ -290,9 +291,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise) fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); - if (attrs[counter].type == PERF_TYPE_SOFTWARE && - attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { - + if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { if (walltime_nsecs_avg) fprintf(stderr, " # %10.3f CPUs ", (double)count[0] / (double)walltime_nsecs_avg); @@ -305,9 +304,7 @@ static void abs_printout(int counter, u64 *count, u64 *noise) fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); if (runtime_cycles_avg && - attrs[counter].type == PERF_TYPE_HARDWARE && - attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { - + MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { fprintf(stderr, " # %10.3f IPC ", (double)count[0] / (double)runtime_cycles_avg); } else { @@ -390,7 +387,7 @@ static void calc_avg(void) event_res_avg[j]+1, event_res[i][j]+1); update_avg("counter/2", j, event_res_avg[j]+2, event_res[i][j]+2); - if (event_scaled[i][j] != -1) + if (event_scaled[i][j] != (u64)-1) update_avg("scaled", j, event_scaled_avg + j, event_scaled[i]+j); else @@ -510,7 +507,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_stat(int argc, const char **argv, const char *prefix) +int cmd_stat(int argc, const char **argv, const char *prefix __used) { int status; @@ -528,7 +525,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix) nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); assert(nr_cpus <= MAX_NR_CPUS); - assert(nr_cpus >= 0); + assert((int)nr_cpus >= 0); /* * We dont want to block the signals - that would cause diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cf0d21f1ae1..95d5c0ae375 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -23,7 +23,7 @@ #include "util/symbol.h" #include "util/color.h" #include "util/util.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/parse-options.h" #include "util/parse-events.h" @@ -66,6 +66,7 @@ static unsigned int page_size; static unsigned int mmap_pages = 16; static int freq = 0; static int verbose = 0; +static char *vmlinux = NULL; static char *sym_filter; static unsigned long filter_start; @@ -238,7 +239,6 @@ static void print_sym_table(void) for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); struct symbol *sym = (struct symbol *)(syme + 1); - char *color = PERF_COLOR_NORMAL; double pcnt; if (++printed > print_entries || syme->snap_count < count_filter) @@ -247,29 +247,20 @@ static void print_sym_table(void) pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / sum_ksamples)); - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (pcnt >= 5.0) { - color = PERF_COLOR_RED; - } else { - if (pcnt >= 0.5) - color = PERF_COLOR_GREEN; - } - if (nr_counters == 1) printf("%20.2f - ", syme->weight); else printf("%9.1f %10ld - ", syme->weight, syme->snap_count); - color_fprintf(stdout, color, "%4.1f%%", pcnt); - printf(" - %016llx : %s\n", sym->start, sym->name); + percent_color_fprintf(stdout, "%4.1f%%", pcnt); + printf(" - %016llx : %s", sym->start, sym->name); + if (sym->module) + printf("\t[%s]", sym->module->name); + printf("\n"); } } -static void *display_thread(void *arg) +static void *display_thread(void *arg __used) { struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; int delay_msecs = delay_secs * 1000; @@ -286,11 +277,31 @@ static void *display_thread(void *arg) return NULL; } +/* Tag samples to be skipped. */ +static const char *skip_symbols[] = { + "default_idle", + "cpu_idle", + "enter_idle", + "exit_idle", + "mwait_idle", + "ppc64_runlatch_off", + "pseries_dedicated_idle_sleep", + NULL +}; + static int symbol_filter(struct dso *self, struct symbol *sym) { static int filter_match; struct sym_entry *syme; const char *name = sym->name; + int i; + + /* + * ppc64 uses function descriptors and appends a '.' to the + * start of every instruction address. Remove it. + */ + if (name[0] == '.') + name++; if (!strcmp(name, "_text") || !strcmp(name, "_etext") || @@ -302,13 +313,12 @@ static int symbol_filter(struct dso *self, struct symbol *sym) return 1; syme = dso__sym_priv(self, sym); - /* Tag samples to be skipped. */ - if (!strcmp("default_idle", name) || - !strcmp("cpu_idle", name) || - !strcmp("enter_idle", name) || - !strcmp("exit_idle", name) || - !strcmp("mwait_idle", name)) - syme->skip = 1; + for (i = 0; skip_symbols[i]; i++) { + if (!strcmp(skip_symbols[i], name)) { + syme->skip = 1; + break; + } + } if (filter_match == 1) { filter_end = sym->start; @@ -340,12 +350,13 @@ static int parse_symbols(void) { struct rb_node *node; struct symbol *sym; + int modules = vmlinux ? 1 : 0; kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); if (kernel_dso == NULL) return -1; - if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) + if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0) goto out_delete_dso; node = rb_first(&kernel_dso->syms); @@ -407,7 +418,7 @@ static void process_event(u64 ip, int counter, int user) struct mmap_data { int counter; void *base; - unsigned int mask; + int mask; unsigned int prev; }; @@ -661,6 +672,7 @@ static const struct option options[] = { "system-wide collection from all CPUs"), OPT_INTEGER('C', "CPU", &profile_cpu, "CPU to profile on"), + OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), OPT_INTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, @@ -675,7 +687,7 @@ static const struct option options[] = { "put the counters into a counter group"), OPT_STRING('s', "sym-filter", &sym_filter, "pattern", "only display symbols matchig this pattern"), - OPT_BOOLEAN('z', "zero", &group, + OPT_BOOLEAN('z', "zero", &zero, "zero history across updates"), OPT_INTEGER('F', "freq", &freq, "profile at this frequency"), @@ -686,10 +698,12 @@ static const struct option options[] = { OPT_END() }; -int cmd_top(int argc, const char **argv, const char *prefix) +int cmd_top(int argc, const char **argv, const char *prefix __used) { int counter; + symbol__init(); + page_size = sysconf(_SC_PAGE_SIZE); argc = parse_options(argc, argv, options, top_usage, 0); diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 4eb72593370..c5656784c61 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -229,9 +229,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) use_pager = 1; commit_pager_choice(); - if (p->option & NEED_WORK_TREE) - /* setup_work_tree() */; - status = p->fn(argc, argv, prefix); if (status) return status & 0xff; @@ -266,7 +263,7 @@ static void handle_internal_command(int argc, const char **argv) { "annotate", cmd_annotate, 0 }, { "version", cmd_version, 0 }, }; - int i; + unsigned int i; static const char ext[] = STRIP_EXTENSION; if (sizeof(ext) > 1) { diff --git a/tools/perf/perf.h b/tools/perf/perf.h index d3042a6ba03..63e67cc5487 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -68,6 +68,8 @@ static inline unsigned long long rdclock(void) #define __user #define asmlinkage +#define __used __attribute__((__unused__)) + #define unlikely(x) __builtin_expect(!!(x), 0) #define min(x, y) ({ \ typeof(x) _min1 = (x); \ diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index 9b3dd2b428d..b8144e80bb1 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c @@ -3,7 +3,7 @@ static const char *alias_key; static char *alias_val; -static int alias_lookup_cb(const char *k, const char *v, void *cb) +static int alias_lookup_cb(const char *k, const char *v, void *cb __used) { if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { if (!v) diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 393d6146d13..161d5f413e2 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -3,6 +3,7 @@ #include "util.h" #include "strbuf.h" +#include "../perf.h" #define PERF_DIR_ENVIRONMENT "PERF_DIR" #define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index ad3c2857896..9d3c8141b8c 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -4,6 +4,9 @@ * Handle the callchains from the stream in an ad-hoc radix tree and then * sort them in an rbtree. * + * Using a radix for code path provides a fast retrieval and factorizes + * memory use. Also that lets us use the paths in a hierarchical graph view. + * */ #include <stdlib.h> @@ -13,8 +16,12 @@ #include "callchain.h" +#define chain_for_each_child(child, parent) \ + list_for_each_entry(child, &parent->children, brothers) -static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) +static void +rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, + enum chain_mode mode) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; @@ -24,32 +31,125 @@ static void rb_insert_callchain(struct rb_root *root, struct callchain_node *cha parent = *p; rnode = rb_entry(parent, struct callchain_node, rb_node); - if (rnode->hit < chain->hit) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; + switch (mode) { + case CHAIN_FLAT: + if (rnode->hit < chain->hit) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + break; + case CHAIN_GRAPH_ABS: /* Falldown */ + case CHAIN_GRAPH_REL: + if (rnode->cumul_hit < chain->cumul_hit) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + break; + default: + break; + } } rb_link_node(&chain->rb_node, parent, p); rb_insert_color(&chain->rb_node, root); } +static void +__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit) +{ + struct callchain_node *child; + + chain_for_each_child(child, node) + __sort_chain_flat(rb_root, child, min_hit); + + if (node->hit && node->hit >= min_hit) + rb_insert_callchain(rb_root, node, CHAIN_FLAT); +} + /* * Once we get every callchains from the stream, we can now * sort them by hit */ -void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) +static void +sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit, struct callchain_param *param __used) +{ + __sort_chain_flat(rb_root, node, min_hit); +} + +static void __sort_chain_graph_abs(struct callchain_node *node, + u64 min_hit) +{ + struct callchain_node *child; + + node->rb_root = RB_ROOT; + + chain_for_each_child(child, node) { + __sort_chain_graph_abs(child, min_hit); + if (child->cumul_hit >= min_hit) + rb_insert_callchain(&node->rb_root, child, + CHAIN_GRAPH_ABS); + } +} + +static void +sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root, + u64 min_hit, struct callchain_param *param __used) +{ + __sort_chain_graph_abs(chain_root, min_hit); + rb_root->rb_node = chain_root->rb_root.rb_node; +} + +static void __sort_chain_graph_rel(struct callchain_node *node, + double min_percent) { struct callchain_node *child; + u64 min_hit; - list_for_each_entry(child, &node->children, brothers) - sort_chain_to_rbtree(rb_root, child); + node->rb_root = RB_ROOT; + min_hit = node->cumul_hit * min_percent / 100.0; - if (node->hit) - rb_insert_callchain(rb_root, node); + chain_for_each_child(child, node) { + __sort_chain_graph_rel(child, min_percent); + if (child->cumul_hit >= min_hit) + rb_insert_callchain(&node->rb_root, child, + CHAIN_GRAPH_REL); + } } -static struct callchain_node *create_child(struct callchain_node *parent) +static void +sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root, + u64 min_hit __used, struct callchain_param *param) +{ + __sort_chain_graph_rel(chain_root, param->min_percent); + rb_root->rb_node = chain_root->rb_root.rb_node; +} + +int register_callchain_param(struct callchain_param *param) +{ + switch (param->mode) { + case CHAIN_GRAPH_ABS: + param->sort = sort_chain_graph_abs; + break; + case CHAIN_GRAPH_REL: + param->sort = sort_chain_graph_rel; + break; + case CHAIN_FLAT: + param->sort = sort_chain_flat; + break; + default: + return -1; + } + return 0; +} + +/* + * Create a child for a parent. If inherit_children, then the new child + * will become the new parent of it's parent children + */ +static struct callchain_node * +create_child(struct callchain_node *parent, bool inherit_children) { struct callchain_node *new; @@ -61,91 +161,147 @@ static struct callchain_node *create_child(struct callchain_node *parent) new->parent = parent; INIT_LIST_HEAD(&new->children); INIT_LIST_HEAD(&new->val); + + if (inherit_children) { + struct callchain_node *next; + + list_splice(&parent->children, &new->children); + INIT_LIST_HEAD(&parent->children); + + chain_for_each_child(next, new) + next->parent = new; + } list_add_tail(&new->brothers, &parent->children); return new; } +/* + * Fill the node with callchain values + */ static void -fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) +fill_node(struct callchain_node *node, struct ip_callchain *chain, + int start, struct symbol **syms) { - int i; + unsigned int i; for (i = start; i < chain->nr; i++) { struct callchain_list *call; - call = malloc(sizeof(*chain)); + call = malloc(sizeof(*call)); if (!call) { perror("not enough memory for the code path tree"); return; } call->ip = chain->ips[i]; + call->sym = syms[i]; list_add_tail(&call->list, &node->val); } - node->val_nr = i - start; + node->val_nr = chain->nr - start; + if (!node->val_nr) + printf("Warning: empty node in callchain tree\n"); } -static void add_child(struct callchain_node *parent, struct ip_callchain *chain) +static void +add_child(struct callchain_node *parent, struct ip_callchain *chain, + int start, struct symbol **syms) { struct callchain_node *new; - new = create_child(parent); - fill_node(new, chain, parent->val_nr); + new = create_child(parent, false); + fill_node(new, chain, start, syms); - new->hit = 1; + new->cumul_hit = new->hit = 1; } +/* + * Split the parent in two parts (a new child is created) and + * give a part of its callchain to the created child. + * Then create another child to host the given callchain of new branch + */ static void split_add_child(struct callchain_node *parent, struct ip_callchain *chain, - struct callchain_list *to_split, int idx) + struct callchain_list *to_split, int idx_parents, int idx_local, + struct symbol **syms) { struct callchain_node *new; + struct list_head *old_tail; + unsigned int idx_total = idx_parents + idx_local; /* split */ - new = create_child(parent); - list_move_tail(&to_split->list, &new->val); - new->hit = parent->hit; - parent->hit = 0; - parent->val_nr = idx; + new = create_child(parent, true); - /* create the new one */ - add_child(parent, chain); + /* split the callchain and move a part to the new child */ + old_tail = parent->val.prev; + list_del_range(&to_split->list, old_tail); + new->val.next = &to_split->list; + new->val.prev = old_tail; + to_split->list.prev = &new->val; + old_tail->next = &new->val; + + /* split the hits */ + new->hit = parent->hit; + new->cumul_hit = parent->cumul_hit; + new->val_nr = parent->val_nr - idx_local; + parent->val_nr = idx_local; + + /* create a new child for the new branch if any */ + if (idx_total < chain->nr) { + parent->hit = 0; + add_child(parent, chain, idx_total, syms); + } else { + parent->hit = 1; + } } static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start); + unsigned int start, struct symbol **syms); -static int -__append_chain_children(struct callchain_node *root, struct ip_callchain *chain) +static void +__append_chain_children(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms, unsigned int start) { struct callchain_node *rnode; /* lookup in childrens */ - list_for_each_entry(rnode, &root->children, brothers) { - int ret = __append_chain(rnode, chain, root->val_nr); + chain_for_each_child(rnode, root) { + unsigned int ret = __append_chain(rnode, chain, start, syms); + if (!ret) - return 0; + goto cumul; } - return -1; + /* nothing in children, add to the current node */ + add_child(root, chain, start, syms); + +cumul: + root->cumul_hit++; } static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start) + unsigned int start, struct symbol **syms) { struct callchain_list *cnode; - int i = start; + unsigned int i = start; bool found = false; - /* lookup in the current node */ + /* + * Lookup in the current node + * If we have a symbol, then compare the start to match + * anywhere inside a function. + */ list_for_each_entry(cnode, &root->val, list) { - if (cnode->ip != chain->ips[i++]) + if (i == chain->nr) + break; + if (cnode->sym && syms[i]) { + if (cnode->sym->start != syms[i]->start) + break; + } else if (cnode->ip != chain->ips[i]) break; if (!found) found = true; - if (i == chain->nr) - break; + i++; } /* matches not, relay on the parent */ @@ -153,22 +309,27 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, return -1; /* we match only a part of the node. Split it and add the new chain */ - if (i < root->val_nr) { - split_add_child(root, chain, cnode, i); + if (i - start < root->val_nr) { + split_add_child(root, chain, cnode, start, i - start, syms); return 0; } /* we match 100% of the path, increment the hit */ - if (i == root->val_nr) { + if (i - start == root->val_nr && i == chain->nr) { root->hit++; + root->cumul_hit++; + return 0; } - return __append_chain_children(root, chain); + /* We match the node and still have a part remaining */ + __append_chain_children(root, chain, syms, i); + + return 0; } -void append_chain(struct callchain_node *root, struct ip_callchain *chain) +void append_chain(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms) { - if (__append_chain_children(root, chain) == -1) - add_child(root, chain); + __append_chain_children(root, chain, syms, 0); } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index fa1cd2f71fd..7812122bea1 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -2,22 +2,42 @@ #define __PERF_CALLCHAIN_H #include "../perf.h" -#include "list.h" -#include "rbtree.h" +#include <linux/list.h> +#include <linux/rbtree.h> +#include "symbol.h" +enum chain_mode { + CHAIN_FLAT, + CHAIN_GRAPH_ABS, + CHAIN_GRAPH_REL +}; struct callchain_node { struct callchain_node *parent; struct list_head brothers; - struct list_head children; - struct list_head val; - struct rb_node rb_node; - int val_nr; - int hit; + struct list_head children; + struct list_head val; + struct rb_node rb_node; /* to sort nodes in an rbtree */ + struct rb_root rb_root; /* sorted tree of children */ + unsigned int val_nr; + u64 hit; + u64 cumul_hit; /* hit + hits of children */ +}; + +struct callchain_param; + +typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, + u64, struct callchain_param *); + +struct callchain_param { + enum chain_mode mode; + double min_percent; + sort_chain_func_t sort; }; struct callchain_list { - unsigned long ip; + u64 ip; + struct symbol *sym; struct list_head list; }; @@ -28,6 +48,7 @@ static inline void callchain_init(struct callchain_node *node) INIT_LIST_HEAD(&node->val); } -void append_chain(struct callchain_node *root, struct ip_callchain *chain); -void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); +int register_callchain_param(struct callchain_param *param); +void append_chain(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms); #endif diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 9a8c20ccc53..90a044d1fe7 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -11,7 +11,8 @@ static int parse_color(const char *name, int len) }; char *end; int i; - for (i = 0; i < ARRAY_SIZE(color_names); i++) { + + for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) { const char *str = color_names[i]; if (!strncasecmp(name, str, len) && !str[len]) return i - 1; @@ -28,7 +29,8 @@ static int parse_attr(const char *name, int len) static const char * const attr_names[] = { "bold", "dim", "ul", "blink", "reverse" }; - int i; + unsigned int i; + for (i = 0; i < ARRAY_SIZE(attr_names); i++) { const char *str = attr_names[i]; if (!strncasecmp(name, str, len) && !str[len]) @@ -222,10 +224,12 @@ int color_fwrite_lines(FILE *fp, const char *color, { if (!*color) return fwrite(buf, count, 1, fp) != 1; + while (count) { char *p = memchr(buf, '\n', count); + if (p != buf && (fputs(color, fp) < 0 || - fwrite(buf, p ? p - buf : count, 1, fp) != 1 || + fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || fputs(PERF_COLOR_RESET, fp) < 0)) return -1; if (!p) @@ -238,4 +242,31 @@ int color_fwrite_lines(FILE *fp, const char *color, return 0; } +char *get_percent_color(double percent) +{ + char *color = PERF_COLOR_NORMAL; + /* + * We color high-overhead entries in red, mid-overhead + * entries in green - and keep the low overhead places + * normal: + */ + if (percent >= MIN_RED) + color = PERF_COLOR_RED; + else { + if (percent > MIN_GREEN) + color = PERF_COLOR_GREEN; + } + return color; +} + +int percent_color_fprintf(FILE *fp, const char *fmt, double percent) +{ + int r; + char *color; + + color = get_percent_color(percent); + r = color_fprintf(fp, color, fmt, percent); + + return r; +} diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index 5abfd379582..706cec50bd2 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -15,6 +15,9 @@ #define PERF_COLOR_CYAN "\033[36m" #define PERF_COLOR_BG_RED "\033[41m" +#define MIN_GREEN 0.5 +#define MIN_RED 5.0 + /* * This variable stores the value of color.ui */ @@ -32,5 +35,7 @@ void color_parse_mem(const char *value, int len, const char *var, char *dst); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); +int percent_color_fprintf(FILE *fp, const char *fmt, double percent); +char *get_percent_color(double percent); #endif /* COLOR_H */ diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 3dd13faa6a2..780df541006 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -47,10 +47,12 @@ static int get_next_char(void) static char *parse_value(void) { static char value[1024]; - int quote = 0, comment = 0, len = 0, space = 0; + int quote = 0, comment = 0, space = 0; + size_t len = 0; for (;;) { int c = get_next_char(); + if (len >= sizeof(value) - 1) return NULL; if (c == '\n') { @@ -353,13 +355,13 @@ int perf_config_string(const char **dest, const char *var, const char *value) return 0; } -static int perf_default_core_config(const char *var, const char *value) +static int perf_default_core_config(const char *var __used, const char *value __used) { /* Add other config variables here and to Documentation/config.txt. */ return 0; } -int perf_default_config(const char *var, const char *value, void *dummy) +int perf_default_config(const char *var, const char *value, void *dummy __used) { if (!prefixcmp(var, "core.")) return perf_default_core_config(var, value); @@ -471,10 +473,10 @@ static int matches(const char* key, const char* value) !regexec(store.value_regex, value, 0, NULL, 0))); } -static int store_aux(const char* key, const char* value, void *cb) +static int store_aux(const char* key, const char* value, void *cb __used) { + int section_len; const char *ep; - size_t section_len; switch (store.state) { case KEY_SEEN: @@ -551,7 +553,7 @@ static int store_write_section(int fd, const char* key) strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); } - success = write_in_full(fd, sb.buf, sb.len) == sb.len; + success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); strbuf_release(&sb); return success; @@ -599,7 +601,7 @@ static int store_write_pair(int fd, const char* key, const char* value) } strbuf_addf(&sb, "%s\n", quote); - success = write_in_full(fd, sb.buf, sb.len) == sb.len; + success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); strbuf_release(&sb); return success; @@ -741,7 +743,7 @@ int perf_config_set_multivar(const char* key, const char* value, } else { struct stat st; char* contents; - size_t contents_sz, copy_begin, copy_end; + ssize_t contents_sz, copy_begin, copy_end; int i, new_line = 0; if (value_regex == NULL) diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c index d3929226315..34a35286738 100644 --- a/tools/perf/util/exec_cmd.c +++ b/tools/perf/util/exec_cmd.c @@ -1,6 +1,9 @@ #include "cache.h" #include "exec_cmd.h" #include "quote.h" + +#include <string.h> + #define MAX_ARGS 32 extern char **environ; @@ -51,7 +54,7 @@ const char *perf_extract_argv0_path(const char *argv0) slash--; if (slash >= argv0) { - argv0_path = strndup(argv0, slash - argv0); + argv0_path = xstrndup(argv0, slash - argv0); return slash + 1; } diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 17a00e0df2c..fbb00978b2e 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -26,7 +26,7 @@ static int term_columns(void) return 80; } -void add_cmdname(struct cmdnames *cmds, const char *name, int len) +void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { struct cmdname *ent = malloc(sizeof(*ent) + len + 1); @@ -40,7 +40,8 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len) static void clean_cmdnames(struct cmdnames *cmds) { - int i; + unsigned int i; + for (i = 0; i < cmds->cnt; ++i) free(cmds->names[i]); free(cmds->names); @@ -57,7 +58,7 @@ static int cmdname_compare(const void *a_, const void *b_) static void uniq(struct cmdnames *cmds) { - int i, j; + unsigned int i, j; if (!cmds->cnt) return; @@ -71,7 +72,7 @@ static void uniq(struct cmdnames *cmds) void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) { - int ci, cj, ei; + size_t ci, cj, ei; int cmp; ci = cj = ei = 0; @@ -106,8 +107,9 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest) printf(" "); for (j = 0; j < cols; j++) { - int n = j * rows + i; - int size = space; + unsigned int n = j * rows + i; + unsigned int size = space; + if (n >= cmds->cnt) break; if (j == cols-1 || n + rows >= cmds->cnt) @@ -208,7 +210,7 @@ void load_command_list(const char *prefix, void list_commands(const char *title, struct cmdnames *main_cmds, struct cmdnames *other_cmds) { - int i, longest = 0; + unsigned int i, longest = 0; for (i = 0; i < main_cmds->cnt; i++) if (longest < main_cmds->names[i]->len) @@ -239,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds, int is_in_cmdlist(struct cmdnames *c, const char *s) { - int i; + unsigned int i; + for (i = 0; i < c->cnt; i++) if (!strcmp(s, c->names[i]->name)) return 1; @@ -271,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2) static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) { - int i; + unsigned int i; + ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); for (i = 0; i < old->cnt; i++) @@ -283,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) const char *help_unknown_cmd(const char *cmd) { - int i, n = 0, best_similarity = 0; + unsigned int i, n = 0, best_similarity = 0; struct cmdnames main_cmds, other_cmds; memset(&main_cmds, 0, sizeof(main_cmds)); @@ -345,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd) exit(1); } -int cmd_version(int argc, const char **argv, const char *prefix) +int cmd_version(int argc __used, const char **argv __used, const char *prefix __used) { printf("perf version %s\n", perf_version_string); return 0; diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h index 56bc15406ff..7128783637b 100644 --- a/tools/perf/util/help.h +++ b/tools/perf/util/help.h @@ -2,8 +2,8 @@ #define HELP_H struct cmdnames { - int alloc; - int cnt; + size_t alloc; + size_t cnt; struct cmdname { size_t len; /* also used for similarity index in help.c */ char name[FLEX_ARRAY]; @@ -19,7 +19,7 @@ static inline void mput_char(char c, unsigned int num) void load_command_list(const char *prefix, struct cmdnames *main_cmds, struct cmdnames *other_cmds); -void add_cmdname(struct cmdnames *cmds, const char *name, int len); +void add_cmdname(struct cmdnames *cmds, const char *name, size_t len); /* Here we require that excludes is a sorted list. */ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); int is_in_cmdlist(struct cmdnames *c, const char *s); diff --git a/tools/perf/util/include/asm/system.h b/tools/perf/util/include/asm/system.h new file mode 100644 index 00000000000..710cecca972 --- /dev/null +++ b/tools/perf/util/include/asm/system.h @@ -0,0 +1 @@ +/* Empty */ diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h new file mode 100644 index 00000000000..99c1b3d1edd --- /dev/null +++ b/tools/perf/util/include/linux/kernel.h @@ -0,0 +1,21 @@ +#ifndef PERF_LINUX_KERNEL_H_ +#define PERF_LINUX_KERNEL_H_ + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) * __mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) +#endif + +#endif diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h new file mode 100644 index 00000000000..dbe4b814382 --- /dev/null +++ b/tools/perf/util/include/linux/list.h @@ -0,0 +1,18 @@ +#include "../../../../include/linux/list.h" + +#ifndef PERF_LIST_H +#define PERF_LIST_H +/** + * list_del_range - deletes range of entries from list. + * @begin: first element in the range to delete from the list. + * @end: last element in the range to delete from the list. + * Note: list_empty on the range of entries does not return true after this, + * the entries is in an undefined state. + */ +static inline void list_del_range(struct list_head *begin, + struct list_head *end) +{ + begin->prev->next = end->next; + end->next->prev = begin->prev; +} +#endif diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/module.h new file mode 100644 index 00000000000..b43e2dc21e0 --- /dev/null +++ b/tools/perf/util/include/linux/module.h @@ -0,0 +1,6 @@ +#ifndef PERF_LINUX_MODULE_H +#define PERF_LINUX_MODULE_H + +#define EXPORT_SYMBOL(name) + +#endif diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h new file mode 100644 index 00000000000..fef6dbc9ce1 --- /dev/null +++ b/tools/perf/util/include/linux/poison.h @@ -0,0 +1 @@ +#include "../../../../include/linux/poison.h" diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h new file mode 100644 index 00000000000..7841e485d8c --- /dev/null +++ b/tools/perf/util/include/linux/prefetch.h @@ -0,0 +1,6 @@ +#ifndef PERF_LINUX_PREFETCH_H +#define PERF_LINUX_PREFETCH_H + +static inline void prefetch(void *a __attribute__((unused))) { } + +#endif diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h new file mode 100644 index 00000000000..7a243a14303 --- /dev/null +++ b/tools/perf/util/include/linux/rbtree.h @@ -0,0 +1 @@ +#include "../../../../include/linux/rbtree.h" diff --git a/tools/perf/util/list.h b/tools/perf/util/list.h deleted file mode 100644 index e2548e8072c..00000000000 --- a/tools/perf/util/list.h +++ /dev/null @@ -1,603 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H -/* - Copyright (C) Cast of dozens, comes from the Linux kernel - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. -*/ - -#include <stddef.h> - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *)0x00100100) -#define LIST_POISON2 ((void *)0x00200200) - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_range - deletes range of entries from list. - * @beging: first element in the range to delete from the list. - * @beging: first element in the range to delete from the list. - * Note: list_empty on the range of entries does not return true after this, - * the entries is in an undefined state. - */ -static inline void list_del_range(struct list_head *begin, - struct list_head *end) -{ - begin->prev->next = end->next; - end->next->prev = begin->prev; -} - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * Note: if 'old' was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) -{ - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, - struct list_head *new) -{ - list_replace(old, new); - INIT_LIST_HEAD(old); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_is_last - tests whether @list is the last entry in list @head - * @list: the entry to test - * @head: the head of the list - */ -static inline int list_is_last(const struct list_head *list, - const struct list_head *head) -{ - return list->next == head; -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @head: the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member) \ - for (; &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_continue - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_from - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member) \ - for (n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_reverse - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - n = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, typeof(*n), member)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -static inline void INIT_HLIST_NODE(struct hlist_node *h) -{ - h->next = NULL; - h->pprev = NULL; -} - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (!hlist_unhashed(n)) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos; \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -#endif diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c new file mode 100644 index 00000000000..ddabe925d65 --- /dev/null +++ b/tools/perf/util/module.c @@ -0,0 +1,509 @@ +#include "util.h" +#include "../perf.h" +#include "string.h" +#include "module.h" + +#include <libelf.h> +#include <gelf.h> +#include <elf.h> +#include <dirent.h> +#include <sys/utsname.h> + +static unsigned int crc32(const char *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} + +/* module section methods */ + +struct sec_dso *sec_dso__new_dso(const char *name) +{ + struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1); + + if (self != NULL) { + strcpy(self->name, name); + self->secs = RB_ROOT; + self->find_section = sec_dso__find_section; + } + + return self; +} + +static void sec_dso__delete_section(struct section *self) +{ + free(((void *)self)); +} + +void sec_dso__delete_sections(struct sec_dso *self) +{ + struct section *pos; + struct rb_node *next = rb_first(&self->secs); + + while (next) { + pos = rb_entry(next, struct section, rb_node); + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, &self->secs); + sec_dso__delete_section(pos); + } +} + +void sec_dso__delete_self(struct sec_dso *self) +{ + sec_dso__delete_sections(self); + free(self); +} + +static void sec_dso__insert_section(struct sec_dso *self, struct section *sec) +{ + struct rb_node **p = &self->secs.rb_node; + struct rb_node *parent = NULL; + const u64 hash = sec->hash; + struct section *s; + + while (*p != NULL) { + parent = *p; + s = rb_entry(parent, struct section, rb_node); + if (hash < s->hash) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&sec->rb_node, parent, p); + rb_insert_color(&sec->rb_node, &self->secs); +} + +struct section *sec_dso__find_section(struct sec_dso *self, const char *name) +{ + struct rb_node *n; + u64 hash; + int len; + + if (self == NULL) + return NULL; + + len = strlen(name); + hash = crc32(name, len); + + n = self->secs.rb_node; + + while (n) { + struct section *s = rb_entry(n, struct section, rb_node); + + if (hash < s->hash) + n = n->rb_left; + else if (hash > s->hash) + n = n->rb_right; + else { + if (!strcmp(name, s->name)) + return s; + else + n = rb_next(&s->rb_node); + } + } + + return NULL; +} + +static size_t sec_dso__fprintf_section(struct section *self, FILE *fp) +{ + return fprintf(fp, "name:%s vma:%llx path:%s\n", + self->name, self->vma, self->path); +} + +size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp) +{ + size_t ret = fprintf(fp, "dso: %s\n", self->name); + + struct rb_node *nd; + for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) { + struct section *pos = rb_entry(nd, struct section, rb_node); + ret += sec_dso__fprintf_section(pos, fp); + } + + return ret; +} + +static struct section *section__new(const char *name, const char *path) +{ + struct section *self = calloc(1, sizeof(*self)); + + if (!self) + goto out_failure; + + self->name = calloc(1, strlen(name) + 1); + if (!self->name) + goto out_failure; + + self->path = calloc(1, strlen(path) + 1); + if (!self->path) + goto out_failure; + + strcpy(self->name, name); + strcpy(self->path, path); + self->hash = crc32(self->name, strlen(name)); + + return self; + +out_failure: + if (self) { + if (self->name) + free(self->name); + if (self->path) + free(self->path); + free(self); + } + + return NULL; +} + +/* module methods */ + +struct mod_dso *mod_dso__new_dso(const char *name) +{ + struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1); + + if (self != NULL) { + strcpy(self->name, name); + self->mods = RB_ROOT; + self->find_module = mod_dso__find_module; + } + + return self; +} + +static void mod_dso__delete_module(struct module *self) +{ + free(((void *)self)); +} + +void mod_dso__delete_modules(struct mod_dso *self) +{ + struct module *pos; + struct rb_node *next = rb_first(&self->mods); + + while (next) { + pos = rb_entry(next, struct module, rb_node); + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, &self->mods); + mod_dso__delete_module(pos); + } +} + +void mod_dso__delete_self(struct mod_dso *self) +{ + mod_dso__delete_modules(self); + free(self); +} + +static void mod_dso__insert_module(struct mod_dso *self, struct module *mod) +{ + struct rb_node **p = &self->mods.rb_node; + struct rb_node *parent = NULL; + const u64 hash = mod->hash; + struct module *m; + + while (*p != NULL) { + parent = *p; + m = rb_entry(parent, struct module, rb_node); + if (hash < m->hash) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&mod->rb_node, parent, p); + rb_insert_color(&mod->rb_node, &self->mods); +} + +struct module *mod_dso__find_module(struct mod_dso *self, const char *name) +{ + struct rb_node *n; + u64 hash; + int len; + + if (self == NULL) + return NULL; + + len = strlen(name); + hash = crc32(name, len); + + n = self->mods.rb_node; + + while (n) { + struct module *m = rb_entry(n, struct module, rb_node); + + if (hash < m->hash) + n = n->rb_left; + else if (hash > m->hash) + n = n->rb_right; + else { + if (!strcmp(name, m->name)) + return m; + else + n = rb_next(&m->rb_node); + } + } + + return NULL; +} + +static size_t mod_dso__fprintf_module(struct module *self, FILE *fp) +{ + return fprintf(fp, "name:%s path:%s\n", self->name, self->path); +} + +size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp) +{ + struct rb_node *nd; + size_t ret; + + ret = fprintf(fp, "dso: %s\n", self->name); + + for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) { + struct module *pos = rb_entry(nd, struct module, rb_node); + + ret += mod_dso__fprintf_module(pos, fp); + } + + return ret; +} + +static struct module *module__new(const char *name, const char *path) +{ + struct module *self = calloc(1, sizeof(*self)); + + if (!self) + goto out_failure; + + self->name = calloc(1, strlen(name) + 1); + if (!self->name) + goto out_failure; + + self->path = calloc(1, strlen(path) + 1); + if (!self->path) + goto out_failure; + + strcpy(self->name, name); + strcpy(self->path, path); + self->hash = crc32(self->name, strlen(name)); + + return self; + +out_failure: + if (self) { + if (self->name) + free(self->name); + if (self->path) + free(self->path); + free(self); + } + + return NULL; +} + +static int mod_dso__load_sections(struct module *mod) +{ + int count = 0, path_len; + struct dirent *entry; + char *line = NULL; + char *dir_path; + DIR *dir; + size_t n; + + path_len = strlen("/sys/module/"); + path_len += strlen(mod->name); + path_len += strlen("/sections/"); + + dir_path = calloc(1, path_len + 1); + if (dir_path == NULL) + goto out_failure; + + strcat(dir_path, "/sys/module/"); + strcat(dir_path, mod->name); + strcat(dir_path, "/sections/"); + + dir = opendir(dir_path); + if (dir == NULL) + goto out_free; + + while ((entry = readdir(dir))) { + struct section *section; + char *path, *vma; + int line_len; + FILE *file; + + if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) + continue; + + path = calloc(1, path_len + strlen(entry->d_name) + 1); + if (path == NULL) + break; + strcat(path, dir_path); + strcat(path, entry->d_name); + + file = fopen(path, "r"); + if (file == NULL) { + free(path); + break; + } + + line_len = getline(&line, &n, file); + if (line_len < 0) { + free(path); + fclose(file); + break; + } + + if (!line) { + free(path); + fclose(file); + break; + } + + line[--line_len] = '\0'; /* \n */ + + vma = strstr(line, "0x"); + if (!vma) { + free(path); + fclose(file); + break; + } + vma += 2; + + section = section__new(entry->d_name, path); + if (!section) { + fprintf(stderr, "load_sections: allocation error\n"); + free(path); + fclose(file); + break; + } + + hex2u64(vma, §ion->vma); + sec_dso__insert_section(mod->sections, section); + + free(path); + fclose(file); + count++; + } + + closedir(dir); + free(line); + free(dir_path); + + return count; + +out_free: + free(dir_path); + +out_failure: + return count; +} + +static int mod_dso__load_module_paths(struct mod_dso *self) +{ + struct utsname uts; + int count = 0, len; + char *line = NULL; + FILE *file; + char *path; + size_t n; + + if (uname(&uts) < 0) + goto out_failure; + + len = strlen("/lib/modules/"); + len += strlen(uts.release); + len += strlen("/modules.dep"); + + path = calloc(1, len); + if (path == NULL) + goto out_failure; + + strcat(path, "/lib/modules/"); + strcat(path, uts.release); + strcat(path, "/modules.dep"); + + file = fopen(path, "r"); + free(path); + if (file == NULL) + goto out_failure; + + while (!feof(file)) { + char *path, *name, *tmp; + struct module *module; + int line_len, len; + + line_len = getline(&line, &n, file); + if (line_len < 0) + break; + + if (!line) + goto out_failure; + + line[--line_len] = '\0'; /* \n */ + + path = strtok(line, ":"); + if (!path) + goto out_failure; + + name = strdup(path); + name = strtok(name, "/"); + + tmp = name; + + while (tmp) { + tmp = strtok(NULL, "/"); + if (tmp) + name = tmp; + } + name = strsep(&name, "."); + + /* Quirk: replace '-' with '_' in sound modules */ + for (len = strlen(name); len; len--) { + if (*(name+len) == '-') + *(name+len) = '_'; + } + + module = module__new(name, path); + if (!module) { + fprintf(stderr, "load_module_paths: allocation error\n"); + goto out_failure; + } + mod_dso__insert_module(self, module); + + module->sections = sec_dso__new_dso("sections"); + if (!module->sections) { + fprintf(stderr, "load_module_paths: allocation error\n"); + goto out_failure; + } + + module->active = mod_dso__load_sections(module); + + if (module->active > 0) + count++; + } + + free(line); + fclose(file); + + return count; + +out_failure: + return -1; +} + +int mod_dso__load_modules(struct mod_dso *dso) +{ + int err; + + err = mod_dso__load_module_paths(dso); + + return err; +} diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h new file mode 100644 index 00000000000..8a592ef641c --- /dev/null +++ b/tools/perf/util/module.h @@ -0,0 +1,53 @@ +#ifndef _PERF_MODULE_ +#define _PERF_MODULE_ 1 + +#include <linux/types.h> +#include "../types.h" +#include <linux/list.h> +#include <linux/rbtree.h> + +struct section { + struct rb_node rb_node; + u64 hash; + u64 vma; + char *name; + char *path; +}; + +struct sec_dso { + struct list_head node; + struct rb_root secs; + struct section *(*find_section)(struct sec_dso *, const char *name); + char name[0]; +}; + +struct module { + struct rb_node rb_node; + u64 hash; + char *name; + char *path; + struct sec_dso *sections; + int active; +}; + +struct mod_dso { + struct list_head node; + struct rb_root mods; + struct module *(*find_module)(struct mod_dso *, const char *name); + char name[0]; +}; + +struct sec_dso *sec_dso__new_dso(const char *name); +void sec_dso__delete_sections(struct sec_dso *self); +void sec_dso__delete_self(struct sec_dso *self); +size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp); +struct section *sec_dso__find_section(struct sec_dso *self, const char *name); + +struct mod_dso *mod_dso__new_dso(const char *name); +void mod_dso__delete_modules(struct mod_dso *self); +void mod_dso__delete_self(struct mod_dso *self); +size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp); +struct module *mod_dso__find_module(struct mod_dso *self, const char *name); +int mod_dso__load_modules(struct mod_dso *dso); + +#endif /* _PERF_MODULE_ */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4d042f104cd..5184959e061 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -184,16 +184,20 @@ char *event_name(int counter) return "unknown"; } -static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) +static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) { int i, j; + int n, longest = -1; for (i = 0; i < size; i++) { - for (j = 0; j < MAX_ALIASES; j++) { - if (!names[i][j]) - break; - if (strcasestr(str, names[i][j])) - return i; + for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { + n = strlen(names[i][j]); + if (n > longest && !strncasecmp(*str, names[i][j], n)) + longest = n; + } + if (longest > 0) { + *str += longest; + return i; } } @@ -201,30 +205,53 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) } static int -parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) +parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) { - int cache_type = -1, cache_op = 0, cache_result = 0; + const char *s = *str; + int cache_type = -1, cache_op = -1, cache_result = -1; - cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); + cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); /* * No fallback - if we cannot get a clear cache type * then bail out: */ if (cache_type == -1) - return -EINVAL; + return 0; + + while ((cache_op == -1 || cache_result == -1) && *s == '-') { + ++s; + + if (cache_op == -1) { + cache_op = parse_aliases(&s, hw_cache_op, + PERF_COUNT_HW_CACHE_OP_MAX); + if (cache_op >= 0) { + if (!is_cache_op_valid(cache_type, cache_op)) + return 0; + continue; + } + } + + if (cache_result == -1) { + cache_result = parse_aliases(&s, hw_cache_result, + PERF_COUNT_HW_CACHE_RESULT_MAX); + if (cache_result >= 0) + continue; + } + + /* + * Can't parse this as a cache op or result, so back up + * to the '-'. + */ + --s; + break; + } - cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX); /* * Fall back to reads: */ if (cache_op == -1) cache_op = PERF_COUNT_HW_CACHE_OP_READ; - if (!is_cache_op_valid(cache_type, cache_op)) - return -EINVAL; - - cache_result = parse_aliases(str, hw_cache_result, - PERF_COUNT_HW_CACHE_RESULT_MAX); /* * Fall back to accesses: */ @@ -234,93 +261,154 @@ parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) attr->config = cache_type | (cache_op << 8) | (cache_result << 16); attr->type = PERF_TYPE_HW_CACHE; - return 0; + *str = s; + return 1; } static int check_events(const char *str, unsigned int i) { - if (!strncmp(str, event_symbols[i].symbol, - strlen(event_symbols[i].symbol))) - return 1; + int n; - if (strlen(event_symbols[i].alias)) - if (!strncmp(str, event_symbols[i].alias, - strlen(event_symbols[i].alias))) - return 1; + n = strlen(event_symbols[i].symbol); + if (!strncmp(str, event_symbols[i].symbol, n)) + return n; + + n = strlen(event_symbols[i].alias); + if (n) + if (!strncmp(str, event_symbols[i].alias, n)) + return n; return 0; } -/* - * Each event can have multiple symbolic names. - * Symbolic names are (almost) exactly matched. - */ -static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) +static int +parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) { - u64 config, id; - int type; + const char *str = *strp; unsigned int i; - const char *sep, *pstr; + int n; - if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { - attr->type = PERF_TYPE_RAW; - attr->config = config; + for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { + n = check_events(str, i); + if (n > 0) { + attr->type = event_symbols[i].type; + attr->config = event_symbols[i].config; + *strp = str + n; + return 1; + } + } + return 0; +} +static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + u64 config; + int n; + + if (*str != 'r') return 0; + n = hex2u64(str + 1, &config); + if (n > 0) { + *strp = str + n + 1; + attr->type = PERF_TYPE_RAW; + attr->config = config; + return 1; } + return 0; +} - pstr = str; - sep = strchr(pstr, ':'); - if (sep) { - type = atoi(pstr); - pstr = sep + 1; - id = atoi(pstr); - sep = strchr(pstr, ':'); - if (sep) { - pstr = sep + 1; - if (strchr(pstr, 'k')) - attr->exclude_user = 1; - if (strchr(pstr, 'u')) - attr->exclude_kernel = 1; +static int +parse_numeric_event(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + char *endp; + unsigned long type; + u64 config; + + type = strtoul(str, &endp, 0); + if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { + str = endp + 1; + config = strtoul(str, &endp, 0); + if (endp > str) { + attr->type = type; + attr->config = config; + *strp = endp; + return 1; } - attr->type = type; - attr->config = id; + } + return 0; +} +static int +parse_event_modifier(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + int eu = 1, ek = 1, eh = 1; + + if (*str++ != ':') return 0; + while (*str) { + if (*str == 'u') + eu = 0; + else if (*str == 'k') + ek = 0; + else if (*str == 'h') + eh = 0; + else + break; + ++str; } + if (str >= *strp + 2) { + *strp = str; + attr->exclude_user = eu; + attr->exclude_kernel = ek; + attr->exclude_hv = eh; + return 1; + } + return 0; +} - for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { - if (check_events(str, i)) { - attr->type = event_symbols[i].type; - attr->config = event_symbols[i].config; +/* + * Each event can have multiple symbolic names. + * Symbolic names are (almost) exactly matched. + */ +static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) +{ + if (!(parse_raw_event(str, attr) || + parse_numeric_event(str, attr) || + parse_symbolic_event(str, attr) || + parse_generic_hw_event(str, attr))) + return 0; - return 0; - } - } + parse_event_modifier(str, attr); - return parse_generic_hw_symbols(str, attr); + return 1; } -int parse_events(const struct option *opt, const char *str, int unset) +int parse_events(const struct option *opt __used, const char *str, int unset __used) { struct perf_counter_attr attr; - int ret; - memset(&attr, 0, sizeof(attr)); -again: - if (nr_counters == MAX_COUNTERS) - return -1; + for (;;) { + if (nr_counters == MAX_COUNTERS) + return -1; + + memset(&attr, 0, sizeof(attr)); + if (!parse_event_symbols(&str, &attr)) + return -1; - ret = parse_event_symbols(str, &attr); - if (ret < 0) - return ret; + if (!(*str == 0 || *str == ',' || isspace(*str))) + return -1; - attrs[nr_counters] = attr; - nr_counters++; + attrs[nr_counters] = attr; + nr_counters++; - str = strstr(str, ","); - if (str) { - str++; - goto again; + if (*str == 0) + break; + if (*str == ',') + ++str; + while (isspace(*str)) + ++str; } return 0; @@ -340,7 +428,7 @@ static const char * const event_type_descriptors[] = { void print_events(void) { struct event_symbol *syms = event_symbols; - unsigned int i, type, prev_type = -1; + unsigned int i, type, op, prev_type = -1; char name[40]; fprintf(stderr, "\n"); @@ -365,6 +453,21 @@ void print_events(void) } fprintf(stderr, "\n"); + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + fprintf(stderr, " %-40s [%s]\n", + event_cache_name(type, op, i), + event_type_descriptors[4]); + } + } + } + + fprintf(stderr, "\n"); fprintf(stderr, " %-40s [raw hardware event descriptor]\n", "rNNN"); fprintf(stderr, "\n"); diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index b3affb1658d..1bf67190c82 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -20,7 +20,8 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, if (p->opt) { *arg = p->opt; p->opt = NULL; - } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) { + } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || + **(p->argv + 1) == '-')) { *arg = (const char *)opt->defval; } else if (p->argc > 1) { p->argc--; @@ -485,7 +486,7 @@ int parse_options_usage(const char * const *usagestr, } -int parse_opt_verbosity_cb(const struct option *opt, const char *arg, +int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, int unset) { int *target = opt->value; diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index a1039a6ce0e..8aa3464c709 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -90,21 +90,22 @@ struct option { intptr_t defval; }; -#define OPT_END() { OPTION_END } -#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) } -#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } -#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } -#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } -#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) } -#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } -#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } -#define OPT_LONG(s, l, v, h) { OPTION_LONG, (s), (l), (v), NULL, (h) } -#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_END() { .type = OPTION_END } +#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } +#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } +#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } +#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } +#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } +#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } #define OPT_DATE(s, l, v, h) \ - { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ - parse_opt_approxidate_cb } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ - { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } +#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } /* parse_options() will filter out the processed options and leave the * non-option argments in argv[]. diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c index f18c5212bc9..c6e5dc0dc82 100644 --- a/tools/perf/util/quote.c +++ b/tools/perf/util/quote.c @@ -162,12 +162,16 @@ static inline int sq_must_quote(char c) return sq_lookup[(unsigned char)c] + quote_path_fully > 0; } -/* returns the longest prefix not needing a quote up to maxlen if positive. - This stops at the first \0 because it's marked as a character needing an - escape */ -static size_t next_quote_pos(const char *s, ssize_t maxlen) +/* + * Returns the longest prefix not needing a quote up to maxlen if + * positive. + * This stops at the first \0 because it's marked as a character + * needing an escape. + */ +static ssize_t next_quote_pos(const char *s, ssize_t maxlen) { - size_t len; + ssize_t len; + if (maxlen < 0) { for (len = 0; !sq_must_quote(s[len]); len++); } else { @@ -192,22 +196,22 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen) static size_t quote_c_style_counted(const char *name, ssize_t maxlen, struct strbuf *sb, FILE *fp, int no_dq) { -#undef EMIT -#define EMIT(c) \ - do { \ - if (sb) strbuf_addch(sb, (c)); \ - if (fp) fputc((c), fp); \ - count++; \ +#define EMIT(c) \ + do { \ + if (sb) strbuf_addch(sb, (c)); \ + if (fp) fputc((c), fp); \ + count++; \ } while (0) -#define EMITBUF(s, l) \ - do { \ - int __ret; \ - if (sb) strbuf_add(sb, (s), (l)); \ - if (fp) __ret = fwrite((s), (l), 1, fp); \ - count += (l); \ + +#define EMITBUF(s, l) \ + do { \ + int __ret; \ + if (sb) strbuf_add(sb, (s), (l)); \ + if (fp) __ret = fwrite((s), (l), 1, fp); \ + count += (l); \ } while (0) - size_t len, count = 0; + ssize_t len, count = 0; const char *p = name; for (;;) { @@ -273,8 +277,8 @@ void write_name_quoted(const char *name, FILE *fp, int terminator) fputc(terminator, fp); } -extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, - const char *name, FILE *fp, int terminator) +void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, + const char *name, FILE *fp, int terminator) { int needquote = 0; @@ -306,7 +310,7 @@ char *quote_path_relative(const char *in, int len, len = strlen(in); /* "../" prefix itself does not need quoting, but "in" might. */ - needquote = next_quote_pos(in, len) < len; + needquote = (next_quote_pos(in, len) < len); strbuf_setlen(out, 0); strbuf_grow(out, len); diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index 5dfad89816d..a5454a1d1c1 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h @@ -53,7 +53,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); extern void write_name_quoted(const char *name, FILE *, int terminator); -extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, +extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, const char *name, FILE *, int terminator); /* quote path as relative to the given prefix */ diff --git a/tools/perf/util/rbtree.c b/tools/perf/util/rbtree.c deleted file mode 100644 index b15ba9c7cb3..00000000000 --- a/tools/perf/util/rbtree.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli <andrea@suse.de> - (C) 2002 David Woodhouse <dwmw2@infradead.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -*/ - -#include "rbtree.h" - -static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *right = node->rb_right; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_right = right->rb_left)) - rb_set_parent(right->rb_left, node); - right->rb_left = node; - - rb_set_parent(right, parent); - - if (parent) - { - if (node == parent->rb_left) - parent->rb_left = right; - else - parent->rb_right = right; - } - else - root->rb_node = right; - rb_set_parent(node, right); -} - -static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *left = node->rb_left; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_left = left->rb_right)) - rb_set_parent(left->rb_right, node); - left->rb_right = node; - - rb_set_parent(left, parent); - - if (parent) - { - if (node == parent->rb_right) - parent->rb_right = left; - else - parent->rb_left = left; - } - else - root->rb_node = left; - rb_set_parent(node, left); -} - -void rb_insert_color(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *parent, *gparent; - - while ((parent = rb_parent(node)) && rb_is_red(parent)) - { - gparent = rb_parent(parent); - - if (parent == gparent->rb_left) - { - { - register struct rb_node *uncle = gparent->rb_right; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_right == node) - { - register struct rb_node *tmp; - __rb_rotate_left(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_right(gparent, root); - } else { - { - register struct rb_node *uncle = gparent->rb_left; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_left == node) - { - register struct rb_node *tmp; - __rb_rotate_right(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_left(gparent, root); - } - } - - rb_set_black(root->rb_node); -} - -static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, - struct rb_root *root) -{ - struct rb_node *other; - - while ((!node || rb_is_black(node)) && node != root->rb_node) - { - if (parent->rb_left == node) - { - other = parent->rb_right; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_left(parent, root); - other = parent->rb_right; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_right || rb_is_black(other->rb_right)) - { - rb_set_black(other->rb_left); - rb_set_red(other); - __rb_rotate_right(other, root); - other = parent->rb_right; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - rb_set_black(other->rb_right); - __rb_rotate_left(parent, root); - node = root->rb_node; - break; - } - } - else - { - other = parent->rb_left; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_right(parent, root); - other = parent->rb_left; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_left || rb_is_black(other->rb_left)) - { - rb_set_black(other->rb_right); - rb_set_red(other); - __rb_rotate_left(other, root); - other = parent->rb_left; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - rb_set_black(other->rb_left); - __rb_rotate_right(parent, root); - node = root->rb_node; - break; - } - } - } - if (node) - rb_set_black(node); -} - -void rb_erase(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *child, *parent; - int color; - - if (!node->rb_left) - child = node->rb_right; - else if (!node->rb_right) - child = node->rb_left; - else - { - struct rb_node *old = node, *left; - - node = node->rb_right; - while ((left = node->rb_left) != NULL) - node = left; - child = node->rb_right; - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent == old) { - parent->rb_right = child; - parent = node; - } else - parent->rb_left = child; - - node->rb_parent_color = old->rb_parent_color; - node->rb_right = old->rb_right; - node->rb_left = old->rb_left; - - if (rb_parent(old)) - { - if (rb_parent(old)->rb_left == old) - rb_parent(old)->rb_left = node; - else - rb_parent(old)->rb_right = node; - } else - root->rb_node = node; - - rb_set_parent(old->rb_left, node); - if (old->rb_right) - rb_set_parent(old->rb_right, node); - goto color; - } - - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - color: - if (color == RB_BLACK) - __rb_erase_color(child, parent, root); -} - -/* - * This function returns the first node (in sort order) of the tree. - */ -struct rb_node *rb_first(const struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_left) - n = n->rb_left; - return n; -} - -struct rb_node *rb_last(const struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_right) - n = n->rb_right; - return n; -} - -struct rb_node *rb_next(const struct rb_node *node) -{ - struct rb_node *parent; - - if (rb_parent(node) == node) - return NULL; - - /* If we have a right-hand child, go down and then left as far - as we can. */ - if (node->rb_right) { - node = node->rb_right; - while (node->rb_left) - node=node->rb_left; - return (struct rb_node *)node; - } - - /* No right-hand children. Everything down and left is - smaller than us, so any 'next' node must be in the general - direction of our parent. Go up the tree; any time the - ancestor is a right-hand child of its parent, keep going - up. First time it's a left-hand child of its parent, said - parent is our 'next' node. */ - while ((parent = rb_parent(node)) && node == parent->rb_right) - node = parent; - - return parent; -} - -struct rb_node *rb_prev(const struct rb_node *node) -{ - struct rb_node *parent; - - if (rb_parent(node) == node) - return NULL; - - /* If we have a left-hand child, go down and then right as far - as we can. */ - if (node->rb_left) { - node = node->rb_left; - while (node->rb_right) - node=node->rb_right; - return (struct rb_node *)node; - } - - /* No left-hand children. Go up till we find an ancestor which - is a right-hand child of its parent */ - while ((parent = rb_parent(node)) && node == parent->rb_left) - node = parent; - - return parent; -} - -void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root) -{ - struct rb_node *parent = rb_parent(victim); - - /* Set the surrounding nodes to point to the replacement */ - if (parent) { - if (victim == parent->rb_left) - parent->rb_left = new; - else - parent->rb_right = new; - } else { - root->rb_node = new; - } - if (victim->rb_left) - rb_set_parent(victim->rb_left, new); - if (victim->rb_right) - rb_set_parent(victim->rb_right, new); - - /* Copy the pointers/colour from the victim to the replacement */ - *new = *victim; -} diff --git a/tools/perf/util/rbtree.h b/tools/perf/util/rbtree.h deleted file mode 100644 index 6bdc488a47f..00000000000 --- a/tools/perf/util/rbtree.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli <andrea@suse.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/include/linux/rbtree.h - - To use rbtrees you'll have to implement your own insert and search cores. - This will avoid us to use callbacks and to drop drammatically performances. - I know it's not the cleaner way, but in C (not in C++) to get - performances and genericity... - - Some example of insert and search follows here. The search is a plain - normal search over an ordered tree. The insert instead must be implemented - int two steps: as first thing the code must insert the element in - order as a red leaf in the tree, then the support library function - rb_insert_color() must be called. Such function will do the - not trivial work to rebalance the rbtree if necessary. - ------------------------------------------------------------------------ -static inline struct page * rb_search_page_cache(struct inode * inode, - unsigned long offset) -{ - struct rb_node * n = inode->i_rb_page_cache.rb_node; - struct page * page; - - while (n) - { - page = rb_entry(n, struct page, rb_page_cache); - - if (offset < page->offset) - n = n->rb_left; - else if (offset > page->offset) - n = n->rb_right; - else - return page; - } - return NULL; -} - -static inline struct page * __rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct rb_node ** p = &inode->i_rb_page_cache.rb_node; - struct rb_node * parent = NULL; - struct page * page; - - while (*p) - { - parent = *p; - page = rb_entry(parent, struct page, rb_page_cache); - - if (offset < page->offset) - p = &(*p)->rb_left; - else if (offset > page->offset) - p = &(*p)->rb_right; - else - return page; - } - - rb_link_node(node, parent, p); - - return NULL; -} - -static inline struct page * rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct page * ret; - if ((ret = __rb_insert_page_cache(inode, offset, node))) - goto out; - rb_insert_color(node, &inode->i_rb_page_cache); - out: - return ret; -} ------------------------------------------------------------------------ -*/ - -#ifndef _LINUX_RBTREE_H -#define _LINUX_RBTREE_H - -#include <stddef.h> - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -struct rb_node -{ - unsigned long rb_parent_color; -#define RB_RED 0 -#define RB_BLACK 1 - struct rb_node *rb_right; - struct rb_node *rb_left; -} __attribute__((aligned(sizeof(long)))); - /* The alignment might seem pointless, but allegedly CRIS needs it */ - -struct rb_root -{ - struct rb_node *rb_node; -}; - - -#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) -#define rb_color(r) ((r)->rb_parent_color & 1) -#define rb_is_red(r) (!rb_color(r)) -#define rb_is_black(r) rb_color(r) -#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) -#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) - -static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) -{ - rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; -} -static inline void rb_set_color(struct rb_node *rb, int color) -{ - rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; -} - -#define RB_ROOT (struct rb_root) { NULL, } -#define rb_entry(ptr, type, member) container_of(ptr, type, member) - -#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) -#define RB_EMPTY_NODE(node) (rb_parent(node) == node) -#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) - -extern void rb_insert_color(struct rb_node *, struct rb_root *); -extern void rb_erase(struct rb_node *, struct rb_root *); - -/* Find logical next and previous nodes in a tree */ -extern struct rb_node *rb_next(const struct rb_node *); -extern struct rb_node *rb_prev(const struct rb_node *); -extern struct rb_node *rb_first(const struct rb_root *); -extern struct rb_node *rb_last(const struct rb_root *); - -/* Fast replacement of a single node without remove/rebalance/add/rebalance */ -extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root); - -static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, - struct rb_node ** rb_link) -{ - node->rb_parent_color = (unsigned long )parent; - node->rb_left = node->rb_right = NULL; - - *rb_link = node; -} - -#endif /* _LINUX_RBTREE_H */ diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 464e7ca898c..5249d5a1b0c 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -16,7 +16,7 @@ int prefixcmp(const char *str, const char *prefix) */ char strbuf_slopbuf[1]; -void strbuf_init(struct strbuf *sb, size_t hint) +void strbuf_init(struct strbuf *sb, ssize_t hint) { sb->alloc = sb->len = 0; sb->buf = strbuf_slopbuf; @@ -92,7 +92,8 @@ void strbuf_ltrim(struct strbuf *sb) void strbuf_tolower(struct strbuf *sb) { - int i; + unsigned int i; + for (i = 0; i < sb->len; i++) sb->buf[i] = tolower(sb->buf[i]); } @@ -264,7 +265,7 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) return res; } -ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) +ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) { size_t oldlen = sb->len; size_t oldalloc = sb->alloc; @@ -293,7 +294,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) #define STRBUF_MAXLINK (2*PATH_MAX) -int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) +int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint) { size_t oldalloc = sb->alloc; @@ -301,7 +302,7 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) hint = 32; while (hint < STRBUF_MAXLINK) { - int len; + ssize_t len; strbuf_grow(sb, hint); len = readlink(path, sb->buf, hint); @@ -343,7 +344,7 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term) return 0; } -int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) +int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint) { int fd, len; diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 9ee908a3ec5..d2aa86c014c 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h @@ -50,7 +50,7 @@ struct strbuf { #define STRBUF_INIT { 0, 0, strbuf_slopbuf } /*----- strbuf life cycle -----*/ -extern void strbuf_init(struct strbuf *, size_t); +extern void strbuf_init(struct strbuf *buf, ssize_t hint); extern void strbuf_release(struct strbuf *); extern char *strbuf_detach(struct strbuf *, size_t *); extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); @@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { } /*----- strbuf size related -----*/ -static inline size_t strbuf_avail(const struct strbuf *sb) { +static inline ssize_t strbuf_avail(const struct strbuf *sb) { return sb->alloc ? sb->alloc - sb->len - 1 : 0; } @@ -122,9 +122,9 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); /* XXX: if read fails, any partial read is undone */ -extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); -extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint); -extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint); +extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); +extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint); +extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint); extern int strbuf_getline(struct strbuf *, FILE *, int); diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index 2fb117fb4b6..2fdcfee8758 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h @@ -1,7 +1,7 @@ #ifndef STRLIST_H_ #define STRLIST_H_ -#include "rbtree.h" +#include <linux/rbtree.h> #include <stdbool.h> struct str_node { diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 78c2efde01b..4683b67b5ee 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -35,7 +35,7 @@ static struct symbol *symbol__new(u64 start, u64 len, self = ((void *)self) + priv_size; } self->start = start; - self->end = start + len - 1; + self->end = len ? start + len - 1 : start; memcpy(self->name, name, namelen); return self; @@ -48,8 +48,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size) static size_t symbol__fprintf(struct symbol *self, FILE *fp) { - return fprintf(fp, " %llx-%llx %s\n", + if (!self->module) + return fprintf(fp, " %llx-%llx %s\n", self->start, self->end, self->name); + else + return fprintf(fp, " %llx-%llx %s \t[%s]\n", + self->start, self->end, self->name, self->module->name); } struct dso *dso__new(const char *name, unsigned int sym_priv_size) @@ -146,6 +150,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb char *line = NULL; size_t n; FILE *file = fopen("/proc/kallsyms", "r"); + int count = 0; if (file == NULL) goto out_failure; @@ -188,8 +193,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb if (filter && filter(self, sym)) symbol__delete(sym, self->sym_priv_size); - else + else { dso__insert_symbol(self, sym); + count++; + } } /* @@ -212,7 +219,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb free(line); fclose(file); - return 0; + return count; out_delete_line: free(line); @@ -307,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym) sym->st_size != 0; } +static inline int elf_sym__is_label(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_NOTYPE && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF && + sym->st_shndx != SHN_ABS; +} + +static inline const char *elf_sec__name(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return secstrs->d_buf + shdr->sh_name; +} + +static inline int elf_sec__is_text(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; +} + static inline const char *elf_sym__name(const GElf_Sym *sym, const Elf_Data *symstrs) { @@ -448,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, } static int dso__load_sym(struct dso *self, int fd, const char *name, - symbol_filter_t filter, int verbose) + symbol_filter_t filter, int verbose, struct module *mod) { - Elf_Data *symstrs; + Elf_Data *symstrs, *secstrs; uint32_t nr_syms; int err = -1; uint32_t index; @@ -458,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, GElf_Shdr shdr; Elf_Data *syms; GElf_Sym sym; - Elf_Scn *sec, *sec_dynsym; + Elf_Scn *sec, *sec_dynsym, *sec_strndx; Elf *elf; size_t dynsym_idx; int nr = 0; @@ -517,17 +544,29 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, if (symstrs == NULL) goto out_elf_end; + sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); + if (sec_strndx == NULL) + goto out_elf_end; + + secstrs = elf_getdata(sec_strndx, NULL); + if (symstrs == NULL) + goto out_elf_end; + nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); - self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, - ".gnu.prelink_undo", - NULL) != NULL; + self->adjust_symbols = (ehdr.e_type == ET_EXEC || + elf_section_by_name(elf, &ehdr, &shdr, + ".gnu.prelink_undo", + NULL) != NULL); elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { struct symbol *f; u64 obj_start; + struct section *section = NULL; + int is_label = elf_sym__is_label(&sym); + const char *section_name; - if (!elf_sym__is_function(&sym)) + if (!is_label && !elf_sym__is_function(&sym)) continue; sec = elf_getscn(elf, sym.st_shndx); @@ -535,9 +574,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, goto out_elf_end; gelf_getshdr(sec, &shdr); + + if (is_label && !elf_sec__is_text(&shdr, secstrs)) + continue; + + section_name = elf_sec__name(&shdr, secstrs); obj_start = sym.st_value; - if (self->prelinked) { + if (self->adjust_symbols) { if (verbose >= 2) printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); @@ -545,6 +589,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, sym.st_value -= shdr.sh_addr - shdr.sh_offset; } + if (mod) { + section = mod->sections->find_section(mod->sections, section_name); + if (section) + sym.st_value += section->vma; + else { + fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n", + mod->name, section_name); + goto out_elf_end; + } + } + f = symbol__new(sym.st_value, sym.st_size, elf_sym__name(&sym, symstrs), self->sym_priv_size, obj_start, verbose); @@ -554,6 +609,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, if (filter && filter(self, f)) symbol__delete(f, self->sym_priv_size); else { + f->module = mod; dso__insert_symbol(self, f); nr++; } @@ -577,7 +633,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) if (!name) return -1; - self->prelinked = 0; + self->adjust_symbols = 0; if (strncmp(self->name, "/tmp/perf-", 10) == 0) return dso__load_perf_map(self, filter, verbose); @@ -603,7 +659,7 @@ more: fd = open(name, O_RDONLY); } while (fd < 0); - ret = dso__load_sym(self, fd, name, filter, verbose); + ret = dso__load_sym(self, fd, name, filter, verbose, NULL); close(fd); /* @@ -617,6 +673,86 @@ out: return ret; } +static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, + symbol_filter_t filter, int verbose) +{ + struct module *mod = mod_dso__find_module(mods, name); + int err = 0, fd; + + if (mod == NULL || !mod->active) + return err; + + fd = open(mod->path, O_RDONLY); + + if (fd < 0) + return err; + + err = dso__load_sym(self, fd, name, filter, verbose, mod); + close(fd); + + return err; +} + +int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) +{ + struct mod_dso *mods = mod_dso__new_dso("modules"); + struct module *pos; + struct rb_node *next; + int err; + + err = mod_dso__load_modules(mods); + + if (err <= 0) + return err; + + /* + * Iterate over modules, and load active symbols. + */ + next = rb_first(&mods->mods); + while (next) { + pos = rb_entry(next, struct module, rb_node); + err = dso__load_module(self, mods, pos->name, filter, verbose); + + if (err < 0) + break; + + next = rb_next(&pos->rb_node); + } + + if (err < 0) { + mod_dso__delete_modules(mods); + mod_dso__delete_self(mods); + } + + return err; +} + +static inline void dso__fill_symbol_holes(struct dso *self) +{ + struct symbol *prev = NULL; + struct rb_node *nd; + + for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { + struct symbol *pos = rb_entry(nd, struct symbol, rb_node); + + if (prev) { + u64 hole = 0; + int alias = pos->start == prev->start; + + if (!alias) + hole = prev->start - pos->end - 1; + + if (hole || alias) { + if (alias) + pos->end = prev->end; + else if (hole) + pos->end = prev->start - 1; + } + } + prev = pos; + } +} + static int dso__load_vmlinux(struct dso *self, const char *vmlinux, symbol_filter_t filter, int verbose) { @@ -625,21 +761,28 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux, if (fd < 0) return -1; - err = dso__load_sym(self, fd, vmlinux, filter, verbose); + err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); + + if (err > 0) + dso__fill_symbol_holes(self); + close(fd); return err; } int dso__load_kernel(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int verbose) + symbol_filter_t filter, int verbose, int modules) { int err = -1; - if (vmlinux) + if (vmlinux) { err = dso__load_vmlinux(self, vmlinux, filter, verbose); + if (err > 0 && modules) + err = dso__load_modules(self, filter, verbose); + } - if (err < 0) + if (err <= 0) err = dso__load_kallsyms(self, filter, verbose); return err; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2c48ace8203..7918cffb23c 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -3,8 +3,9 @@ #include <linux/types.h> #include "types.h" -#include "list.h" -#include "rbtree.h" +#include <linux/list.h> +#include <linux/rbtree.h> +#include "module.h" struct symbol { struct rb_node rb_node; @@ -13,6 +14,7 @@ struct symbol { u64 obj_start; u64 hist_sum; u64 *hist; + struct module *module; void *priv; char name[0]; }; @@ -22,7 +24,7 @@ struct dso { struct rb_root syms; struct symbol *(*find_symbol)(struct dso *, u64 ip); unsigned int sym_priv_size; - unsigned char prelinked; + unsigned char adjust_symbols; char name[0]; }; @@ -41,7 +43,8 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym) struct symbol *dso__find_symbol(struct dso *self, u64 ip); int dso__load_kernel(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int verbose); + symbol_filter_t filter, int verbose, int modules); +int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); int dso__load(struct dso *self, symbol_filter_t filter, int verbose); size_t dso__fprintf(struct dso *self, FILE *fp); diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c index 6350d65f6d9..4574ac28396 100644 --- a/tools/perf/util/wrapper.c +++ b/tools/perf/util/wrapper.c @@ -7,7 +7,7 @@ * There's no pack memory to release - but stay close to the Git * version so wrap this away: */ -static inline void release_pack_memory(size_t size, int flag) +static inline void release_pack_memory(size_t size __used, int flag __used) { } @@ -59,7 +59,8 @@ void *xmemdupz(const void *data, size_t len) char *xstrndup(const char *str, size_t len) { char *p = memchr(str, '\0', len); - return xmemdupz(str, p ? p - str : len); + + return xmemdupz(str, p ? (size_t)(p - str) : len); } void *xrealloc(void *ptr, size_t size) |