summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/binfmt_misc.txt50
-rw-r--r--Documentation/devicetree/bindings/i2c/ti,bq32k.txt18
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt1
-rw-r--r--Documentation/devicetree/bindings/rtc/dallas,ds1339.txt18
-rw-r--r--Documentation/devicetree/bindings/rtc/s3c-rtc.txt3
-rw-r--r--Documentation/filesystems/autofs4.txt520
-rw-r--r--Documentation/printk-formats.txt32
-rw-r--r--Documentation/sysctl/kernel.txt2
-rw-r--r--MAINTAINERS32
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi2
-rw-r--r--arch/arm/mach-pxa/lpd270.c12
-rw-r--r--arch/frv/mm/extable.c2
-rw-r--r--arch/ia64/include/asm/sections.h2
-rw-r--r--arch/x86/kernel/cpu/common.c4
-rw-r--r--arch/x86/kernel/crash.c10
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c15
-rw-r--r--arch/x86/kernel/kvm.c8
-rw-r--r--arch/x86/mm/ioremap.c20
-rw-r--r--arch/x86/mm/numa.c89
-rw-r--r--arch/x86/purgatory/Makefile3
-rw-r--r--drivers/base/dma-coherent.c151
-rw-r--r--drivers/base/dma-contiguous.c66
-rw-r--r--drivers/clk/Kconfig9
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-rk808.c170
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c2
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c2
-rw-r--r--drivers/memstick/host/r592.c2
-rw-r--r--drivers/misc/altera-stapl/altera.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c5
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c22
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c270
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c65
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c16
-rw-r--r--drivers/net/wireless/libertas/cfg.c8
-rw-r--r--drivers/net/wireless/libertas/mesh.c7
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c4
-rw-r--r--drivers/pnp/interface.c24
-rw-r--r--drivers/rtc/Kconfig31
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-bq32k.c62
-rw-r--r--drivers/rtc/rtc-cmos.c5
-rw-r--r--drivers/rtc/rtc-ds1307.c67
-rw-r--r--drivers/rtc/rtc-isl12022.c2
-rw-r--r--drivers/rtc/rtc-max77686.c140
-rw-r--r--drivers/rtc/rtc-max77802.c502
-rw-r--r--drivers/rtc/rtc-mpc5121.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c4
-rw-r--r--drivers/rtc/rtc-pcf8583.c18
-rw-r--r--drivers/rtc/rtc-rk808.c414
-rw-r--r--drivers/rtc/rtc-rs5c372.c11
-rw-r--r--drivers/rtc/rtc-s3c.c851
-rw-r--r--drivers/s390/cio/chp.c4
-rw-r--r--drivers/scsi/ips.c2
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/staging/rtl8188eu/os_dep/rtw_android.c2
-rw-r--r--drivers/staging/rtl8192e/rtllib.h14
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h14
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c28
-rw-r--r--drivers/thermal/thermal_core.c8
-rw-r--r--drivers/video/fbdev/pvr2fb.c2
-rw-r--r--drivers/video/fbdev/s3c2410fb.c8
-rw-r--r--drivers/video/fbdev/sis/sis_main.c66
-rw-r--r--drivers/video/fbdev/sm501fb.c4
-rw-r--r--fs/affs/amigaffs.c2
-rw-r--r--fs/affs/file.c39
-rw-r--r--fs/affs/inode.c3
-rw-r--r--fs/affs/super.c6
-rw-r--r--fs/autofs4/autofs_i.h6
-rw-r--r--fs/autofs4/dev-ioctl.c2
-rw-r--r--fs/autofs4/expire.c210
-rw-r--r--fs/autofs4/root.c62
-rw-r--r--fs/befs/btree.c53
-rw-r--r--fs/binfmt_misc.c23
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/cifs/cifs_dfs_ref.c6
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/coredump.c8
-rw-r--r--fs/fat/misc.c2
-rw-r--r--fs/hfs/hfs_fs.h2
-rw-r--r--fs/isofs/inode.c2
-rw-r--r--fs/ncpfs/dir.c3
-rw-r--r--fs/nilfs2/file.c8
-rw-r--r--fs/nilfs2/inode.c13
-rw-r--r--fs/nilfs2/ioctl.c8
-rw-r--r--fs/nilfs2/nilfs.h14
-rw-r--r--fs/nilfs2/segment.c7
-rw-r--r--fs/nilfs2/super.c6
-rw-r--r--fs/nilfs2/the_nilfs.h22
-rw-r--r--fs/ocfs2/cluster/heartbeat.c2
-rw-r--r--fs/ocfs2/cluster/masklog.c6
-rw-r--r--fs/omfs/inode.c10
-rw-r--r--fs/omfs/omfs_fs.h1
-rw-r--r--fs/proc/task_mmu.c19
-rw-r--r--fs/reiserfs/journal.c8
-rw-r--r--fs/ufs/balloc.c3
-rw-r--r--include/asm-generic/pgtable.h14
-rw-r--r--include/linux/cma.h3
-rw-r--r--include/linux/compiler-gcc5.h66
-rw-r--r--include/linux/kernel.h4
-rw-r--r--include/linux/kexec.h1
-rw-r--r--include/linux/list.h1
-rw-r--r--include/linux/mm.h6
-rw-r--r--include/linux/moduleparam.h2
-rw-r--r--include/linux/nmi.h13
-rw-r--r--include/linux/prio_heap.h58
-rw-r--r--include/linux/rbtree_augmented.h10
-rw-r--r--include/linux/signal.h29
-rw-r--r--include/linux/string.h2
-rw-r--r--include/linux/string_helpers.h65
-rw-r--r--include/net/lib80211.h5
-rw-r--r--init/Kconfig1
-rw-r--r--init/initramfs.c34
-rw-r--r--init/main.c2
-rw-r--r--ipc/compat.c92
-rw-r--r--ipc/ipc_sysctl.c3
-rw-r--r--ipc/shm.c7
-rw-r--r--ipc/util.c20
-rw-r--r--kernel/debug/kdb/kdb_bp.c6
-rw-r--r--kernel/kallsyms.c11
-rw-r--r--kernel/kexec.c32
-rw-r--r--kernel/params.c7
-rw-r--r--kernel/printk/printk.c14
-rw-r--r--kernel/resource.c36
-rw-r--r--kernel/watchdog.c50
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--lib/Makefile4
-rw-r--r--lib/dynamic_debug.c17
-rw-r--r--lib/prio_heap.c70
-rw-r--r--lib/string.c28
-rw-r--r--lib/string_helpers.c312
-rw-r--r--lib/test-string_helpers.c277
-rw-r--r--lib/textsearch.c4
-rw-r--r--lib/vsprintf.c71
-rw-r--r--mm/cma.c66
-rw-r--r--mm/memory.c3
-rw-r--r--mm/mmap.c45
-rw-r--r--mm/mprotect.c20
-rw-r--r--mm/slab.c2
-rw-r--r--net/batman-adv/gateway_common.c8
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c6
-rw-r--r--net/netfilter/nf_conntrack_ftp.c4
-rw-r--r--net/netfilter/nf_conntrack_sip.c22
-rw-r--r--net/netfilter/nf_log.c2
-rw-r--r--net/netfilter/nf_nat_sip.c2
-rw-r--r--net/wireless/lib80211.c32
-rwxr-xr-xscripts/checkpatch.pl107
-rw-r--r--scripts/headers_install.sh4
-rw-r--r--scripts/sortextable.h2
-rw-r--r--scripts/spelling.txt1042
150 files changed, 5589 insertions, 1657 deletions
diff --git a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt
index c1ed6948ba80..6b1de7058371 100644
--- a/Documentation/binfmt_misc.txt
+++ b/Documentation/binfmt_misc.txt
@@ -15,39 +15,50 @@ First you must mount binfmt_misc:
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon
-your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
+:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
+upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
+
Here is what the fields mean:
- 'name' is an identifier string. A new /proc file will be created with this
- name below /proc/sys/fs/binfmt_misc
+ name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
+ reasons.
- 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
- 'offset' is the offset of the magic/mask in the file, counted in bytes. This
- defaults to 0 if you omit it (i.e. you write ':name:type::magic...')
+ defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
+ when using filename extension matching.
- 'magic' is the byte sequence binfmt_misc is matching for. The magic string
- may contain hex-encoded characters like \x0a or \xA4. In a shell environment
- you will have to write \\x0a to prevent the shell from eating your \.
+ may contain hex-encoded characters like \x0a or \xA4. Note that you must
+ escape any NUL bytes; parsing halts at the first one. In a shell environment
+ you might have to write \\x0a to prevent the shell from eating your \.
If you chose filename extension matching, this is the extension to be
recognised (without the '.', the \x0a specials are not allowed). Extension
- matching is case sensitive!
+ matching is case sensitive, and slashes '/' are not allowed!
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
bits from matching by supplying a string like magic and as long as magic.
- The mask is anded with the byte sequence of the file.
+ The mask is anded with the byte sequence of the file. Note that you must
+ escape any NUL bytes; parsing halts at the first one. Ignored when using
+ filename extension matching.
- 'interpreter' is the program that should be invoked with the binary as first
argument (specify the full path)
- 'flags' is an optional field that controls several aspects of the invocation
- of the interpreter. It is a string of capital letters, each controls a certain
- aspect. The following flags are supported -
- 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the
- original argv[0] with the full path to the binary. When this flag is
- included, binfmt_misc will add an argument to the argument vector for
- this purpose, thus preserving the original argv[0].
+ of the interpreter. It is a string of capital letters, each controls a
+ certain aspect. The following flags are supported -
+ 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
+ the original argv[0] with the full path to the binary. When this
+ flag is included, binfmt_misc will add an argument to the argument
+ vector for this purpose, thus preserving the original argv[0].
+ e.g. If your interp is set to /bin/foo and you run `blah` (which is
+ in /usr/local/bin), then the kernel will execute /bin/foo with
+ argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"]. The
+ interp has to be aware of this so it can execute /usr/local/bin/blah
+ with argv[] set to ["blah"].
'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
of the binary to the interpreter as an argument. When this flag is
included, binfmt_misc will open the file for reading and pass its
descriptor as an argument, instead of the full path, thus allowing
- the interpreter to execute non-readable binaries. This feature should
- be used with care - the interpreter has to be trusted not to emit
- the contents of the non-readable binary.
+ the interpreter to execute non-readable binaries. This feature
+ should be used with care - the interpreter has to be trusted not to
+ emit the contents of the non-readable binary.
'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
the credentials and security token of the new process according to
the interpreter. When this flag is included, these attributes are
@@ -58,7 +69,7 @@ Here is what the fields mean:
There are some restrictions:
- - the whole register string may not exceed 255 characters
+ - the whole register string may not exceed 1920 characters
- the magic must reside in the first 128 bytes of the file, i.e.
offset+size(magic) has to be less than 128
- the interpreter string may not exceed 127 characters
@@ -110,7 +121,4 @@ passes it the full filename (or the file descriptor) to use. Using $PATH can
cause unexpected behaviour and can be a security hazard.
-There is a web page about binfmt_misc at
-http://www.tat.physik.uni-tuebingen.de
-
Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
diff --git a/Documentation/devicetree/bindings/i2c/ti,bq32k.txt b/Documentation/devicetree/bindings/i2c/ti,bq32k.txt
new file mode 100644
index 000000000000..e204906b9ad3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/ti,bq32k.txt
@@ -0,0 +1,18 @@
+* TI BQ32000 I2C Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "ti,bq32000".
+- reg: I2C address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+ Values usable are 1120 and 20180
+ Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+ Should be given if internal trickle charger diode should be disabled
+Example:
+ bq32000: rtc@68 {
+ compatible = "ti,bq32000";
+ trickle-resistor-ohms = <1120>;
+ reg = <0x68>;
+ };
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 5af3d9df6ecb..fbde415078e6 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -35,7 +35,6 @@ catalyst,24c32 i2c serial eeprom
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
dallas,ds1338 I2C RTC with 56-Byte NV RAM
-dallas,ds1339 I2C Serial Real-Time Clock
dallas,ds1340 I2C RTC with Trickle Charger
dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
dallas,ds1631 High-Precision Digital Thermometer
diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt
new file mode 100644
index 000000000000..916f57601a8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt
@@ -0,0 +1,18 @@
+* Dallas DS1339 I2C Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "dallas,ds1339".
+- reg: I2C address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+ Values usable for ds1339 are 250, 2000, 4000
+ Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+ Should be given if internal trickle charger diode should be disabled
+Example:
+ ds1339: rtc@68 {
+ compatible = "dallas,ds1339";
+ trickle-resistor-ohms = <250>;
+ reg = <0x68>;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
index 7ac7259fe9ea..ab757b84daa7 100644
--- a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
@@ -3,7 +3,10 @@
Required properties:
- compatible: should be one of the following.
* "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc.
+ * "samsung,s3c2416-rtc" - for controllers compatible with s3c2416 rtc.
+ * "samsung,s3c2443-rtc" - for controllers compatible with s3c2443 rtc.
* "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
+ * "samsung,exynos3250-rtc" - for controllers compatible with exynos3250 rtc.
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: Two interrupt numbers to the cpu should be specified. First
diff --git a/Documentation/filesystems/autofs4.txt b/Documentation/filesystems/autofs4.txt
new file mode 100644
index 000000000000..39d02e19fb62
--- /dev/null
+++ b/Documentation/filesystems/autofs4.txt
@@ -0,0 +1,520 @@
+<head>
+<style> p { max-width:50em} ol, ul {max-width: 40em}</style>
+</head>
+
+autofs - how it works
+=====================
+
+Purpose
+-------
+
+The goal of autofs is to provide on-demand mounting and race free
+automatic unmounting of various other filesystems. This provides two
+key advantages:
+
+1. There is no need to delay boot until all filesystems that
+ might be needed are mounted. Processes that try to access those
+ slow filesystems might be delayed but other processes can
+ continue freely. This is particularly important for
+ network filesystems (e.g. NFS) or filesystems stored on
+ media with a media-changing robot.
+
+2. The names and locations of filesystems can be stored in
+ a remote database and can change at any time. The content
+ in that data base at the time of access will be used to provide
+ a target for the access. The interpretation of names in the
+ filesystem can even be programmatic rather than database-backed,
+ allowing wildcards for example, and can vary based on the user who
+ first accessed a name.
+
+Context
+-------
+
+The "autofs4" filesystem module is only one part of an autofs system.
+There also needs to be a user-space program which looks up names
+and mounts filesystems. This will often be the "automount" program,
+though other tools including "systemd" can make use of "autofs4".
+This document describes only the kernel module and the interactions
+required with any user-space program. Subsequent text refers to this
+as the "automount daemon" or simply "the daemon".
+
+"autofs4" is a Linux kernel module with provides the "autofs"
+filesystem type. Several "autofs" filesystems can be mounted and they
+can each be managed separately, or all managed by the same daemon.
+
+Content
+-------
+
+An autofs filesystem can contain 3 sorts of objects: directories,
+symbolic links and mount traps. Mount traps are directories with
+extra properties as described in the next section.
+
+Objects can only be created by the automount daemon: symlinks are
+created with a regular `symlink` system call, while directories and
+mount traps are created with `mkdir`. The determination of whether a
+directory should be a mount trap or not is quite _ad hoc_, largely for
+historical reasons, and is determined in part by the
+*direct*/*indirect*/*offset* mount options, and the *maxproto* mount option.
+
+If neither the *direct* or *offset* mount options are given (so the
+mount is considered to be *indirect*), then the root directory is
+always a regular directory, otherwise it is a mount trap when it is
+empty and a regular directory when not empty. Note that *direct* and
+*offset* are treated identically so a concise summary is that the root
+directory is a mount trap only if the filesystem is mounted *direct*
+and the root is empty.
+
+Directories created in the root directory are mount traps only if the
+filesystem is mounted *indirect* and they are empty.
+
+Directories further down the tree depend on the *maxproto* mount
+option and particularly whether it is less than five or not.
+When *maxproto* is five, no directories further down the
+tree are ever mount traps, they are always regular directories. When
+the *maxproto* is four (or three), these directories are mount traps
+precisely when they are empty.
+
+So: non-empty (i.e. non-leaf) directories are never mount traps. Empty
+directories are sometimes mount traps, and sometimes not depending on
+where in the tree they are (root, top level, or lower), the *maxproto*,
+and whether the mount was *indirect* or not.
+
+Mount Traps
+---------------
+
+A core element of the implementation of autofs is the Mount Traps
+which are provided by the Linux VFS. Any directory provided by a
+filesystem can be designated as a trap. This involves two separate
+features that work together to allow autofs to do its job.
+
+**DCACHE_NEED_AUTOMOUNT**
+
+If a dentry has the DCACHE_NEED_AUTOMOUNT flag set (which gets set if
+the inode has S_AUTOMOUNT set, or can be set directly) then it is
+(potentially) a mount trap. Any access to this directory beyond a
+"`stat`" will (normally) cause the `d_op->d_automount()` dentry operation
+to be called. The task of this method is to find the filesystem that
+should be mounted on the directory and to return it. The VFS is
+responsible for actually mounting the root of this filesystem on the
+directory.
+
+autofs doesn't find the filesystem itself but sends a message to the
+automount daemon asking it to find and mount the filesystem. The
+autofs `d_automount` method then waits for the daemon to report that
+everything is ready. It will then return "`NULL`" indicating that the
+mount has already happened. The VFS doesn't try to mount anything but
+follows down the mount that is already there.
+
+This functionality is sufficient for some users of mount traps such
+as NFS which creates traps so that mountpoints on the server can be
+reflected on the client. However it is not sufficient for autofs. As
+mounting onto a directory is considered to be "beyond a `stat`", the
+automount daemon would not be able to mount a filesystem on the 'trap'
+directory without some way to avoid getting caught in the trap. For
+that purpose there is another flag.
+
+**DCACHE_MANAGE_TRANSIT**
+
+If a dentry has DCACHE_MANAGE_TRANSIT set then two very different but
+related behaviors are invoked, both using the `d_op->d_manage()`
+dentry operation.
+
+Firstly, before checking to see if any filesystem is mounted on the
+directory, d_manage() will be called with the `rcu_walk` parameter set
+to `false`. It may return one of three things:
+
+- A return value of zero indicates that there is nothing special
+ about this dentry and normal checks for mounts and automounts
+ should proceed.
+
+ autofs normally returns zero, but first waits for any
+ expiry (automatic unmounting of the mounted filesystem) to
+ complete. This avoids races.
+
+- A return value of `-EISDIR` tells the VFS to ignore any mounts
+ on the directory and to not consider calling `->d_automount()`.
+ This effectively disables the **DCACHE_NEED_AUTOMOUNT** flag
+ causing the directory not be a mount trap after all.
+
+ autofs returns this if it detects that the process performing the
+ lookup is the automount daemon and that the mount has been
+ requested but has not yet completed. How it determines this is
+ discussed later. This allows the automount daemon not to get
+ caught in the mount trap.
+
+ There is a subtlety here. It is possible that a second autofs
+ filesystem can be mounted below the first and for both of them to
+ be managed by the same daemon. For the daemon to be able to mount
+ something on the second it must be able to "walk" down past the
+ first. This means that d_manage cannot *always* return -EISDIR for
+ the automount daemon. It must only return it when a mount has
+ been requested, but has not yet completed.
+
+ `d_manage` also returns `-EISDIR` if the dentry shouldn't be a
+ mount trap, either because it is a symbolic link or because it is
+ not empty.
+
+- Any other negative value is treated as an error and returned
+ to the caller.
+
+ autofs can return
+
+ - -ENOENT if the automount daemon failed to mount anything,
+ - -ENOMEM if it ran out of memory,
+ - -EINTR if a signal arrived while waiting for expiry to
+ complete
+ - or any other error sent down by the automount daemon.
+
+
+The second use case only occurs during an "RCU-walk" and so `rcu_walk`
+will be set.
+
+An RCU-walk is a fast and lightweight process for walking down a
+filename path (i.e. it is like running on tip-toes). RCU-walk cannot
+cope with all situations so when it finds a difficulty it falls back
+to "REF-walk", which is slower but more robust.
+
+RCU-walk will never call `->d_automount`; the filesystems must already
+be mounted or RCU-walk cannot handle the path.
+To determine if a mount-trap is safe for RCU-walk mode it calls
+`->d_manage()` with `rcu_walk` set to `true`.
+
+In this case `d_manage()` must avoid blocking and should avoid taking
+spinlocks if at all possible. Its sole purpose is to determine if it
+would be safe to follow down into any mounted directory and the only
+reason that it might not be is if an expiry of the mount is
+underway.
+
+In the `rcu_walk` case, `d_manage()` cannot return -EISDIR to tell the
+VFS that this is a directory that doesn't require d_automount. If
+`rcu_walk` sees a dentry with DCACHE_NEED_AUTOMOUNT set but nothing
+mounted, it *will* fall back to REF-walk. `d_manage()` cannot make the
+VFS remain in RCU-walk mode, but can only tell it to get out of
+RCU-walk mode by returning `-ECHILD`.
+
+So `d_manage()`, when called with `rcu_walk` set, should either return
+-ECHILD if there is any reason to believe it is unsafe to end the
+mounted filesystem, and otherwise should return 0.
+
+autofs will return `-ECHILD` if an expiry of the filesystem has been
+initiated or is being considered, otherwise it returns 0.
+
+
+Mountpoint expiry
+-----------------
+
+The VFS has a mechansim for automatically expiring unused mounts,
+much as it can expire any unused dentry information from the dcache.
+This is guided by the MNT_SHRINKABLE flag. This only applies to
+mounts that were created by `d_automount()` returning a filesystem to be
+mounted. As autofs doesn't return such a filesystem but leaves the
+mounting to the automount daemon, it must involve the automount daemon
+in unmounting as well. This also means that autofs has more control
+of expiry.
+
+The VFS also supports "expiry" of mounts using the MNT_EXPIRE flag to
+the `umount` system call. Unmounting with MNT_EXPIRE will fail unless
+a previous attempt had been made, and the filesystem has been inactive
+and untouched since that previous attempt. autofs4 does not depend on
+this but has its own internal tracking of whether filesystems were
+recently used. This allows individual names in the autofs directory
+to expire separately.
+
+With version 4 of the protocol, the automount daemon can try to
+unmount any filesystems mounted on the autofs filesystem or remove any
+symbolic links or empty directories any time it likes. If the unmount
+or removal is successful the filesystem will be returned to the state
+it was before the mount or creation, so that any access of the name
+will trigger normal auto-mount processing. In particlar, `rmdir` and
+`unlink` do not leave negative entries in the dcache as a normal
+filesystem would, so an attempt to access a recently-removed object is
+passed to autofs for handling.
+
+With version 5, this is not safe except for unmounting from top-level
+directories. As lower-level directories are never mount traps, other
+processes will see an empty directory as soon as the filesystem is
+unmounted. So it is generally safest to use the autofs expiry
+protocol described below.
+
+Normally the daemon only wants to remove entries which haven't been
+used for a while. For this purpose autofs maintains a "`last_used`"
+time stamp on each directory or symlink. For symlinks it genuinely
+does record the last time the symlink was "used" or followed to find
+out where it points to. For directories the field is a slight
+misnomer. It actually records the last time that autofs checked if
+the directory or one of its descendents was busy and found that it
+was. This is just as useful and doesn't require updating the field so
+often.
+
+The daemon is able to ask autofs if anything is due to be expired,
+using an `ioctl` as discussed later. For a *direct* mount, autofs
+considers if the entire mount-tree can be unmounted or not. For an
+*indirect* mount, autofs considers each of the names in the top level
+directory to determine if any of those can be unmounted and cleaned
+up.
+
+There is an option with indirect mounts to consider each of the leaves
+that has been mounted on instead of considering the top-level names.
+This is intended for compatability with version 4 of autofs and should
+be considered as deprecated.
+
+When autofs considers a directory it checks the `last_used` time and
+compares it with the "timeout" value set when the filesystem was
+mounted, though this check is ignored in some cases. It also checks if
+the directory or anything below it is in use. For symbolic links,
+only the `last_used` time is ever considered.
+
+If both appear to support expiring the directory or symlink, an action
+is taken.
+
+There are two ways to ask autofs to consider expiry. The first is to
+use the **AUTOFS_IOC_EXPIRE** ioctl. This only works for indirect
+mounts. If it finds something in the root directory to expire it will
+return the name of that thing. Once a name has been returned the
+automount daemon needs to unmount any filesystems mounted below the
+name normally. As described above, this is unsafe for non-toplevel
+mounts in a version-5 autofs. For this reason the current `automountd`
+does not use this ioctl.
+
+The second mechanism uses either the **AUTOFS_DEV_IOCTL_EXPIRE_CMD** or
+the **AUTOFS_IOC_EXPIRE_MULTI** ioctl. This will work for both direct and
+indirect mounts. If it selects an object to expire, it will notify
+the daemon using the notification mechanism described below. This
+will block until the daemon acknowledges the expiry notification.
+This implies that the "`EXPIRE`" ioctl must be sent from a different
+thread than the one which handles notification.
+
+While the ioctl is blocking, the entry is marked as "expiring" and
+`d_manage` will block until the daemon affirms that the unmount has
+completed (together with removing any directories that might have been
+necessary), or has been aborted.
+
+Communicating with autofs: detecting the daemon
+-----------------------------------------------
+
+There are several forms of communication between the automount daemon
+and the filesystem. As we have already seen, the daemon can create and
+remove directories and symlinks using normal filesystem operations.
+autofs knows whether a process requesting some operation is the daemon
+or not based on its process-group id number (see getpgid(1)).
+
+When an autofs filesystem it mounted the pgid of the mounting
+processes is recorded unless the "pgrp=" option is given, in which
+case that number is recorded instead. Any request arriving from a
+process in that process group is considered to come from the daemon.
+If the daemon ever has to be stopped and restarted a new pgid can be
+provided through an ioctl as will be described below.
+
+Communicating with autofs: the event pipe
+-----------------------------------------
+
+When an autofs filesystem is mounted, the 'write' end of a pipe must
+be passed using the 'fd=' mount option. autofs will write
+notification messages to this pipe for the daemon to respond to.
+For version 5, the format of the message is:
+
+ struct autofs_v5_packet {
+ int proto_version; /* Protocol version */
+ int type; /* Type of packet */
+ autofs_wqt_t wait_queue_token;
+ __u32 dev;
+ __u64 ino;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+ __u32 tgid;
+ __u32 len;
+ char name[NAME_MAX+1];
+ };
+
+where the type is one of
+
+ autofs_ptype_missing_indirect
+ autofs_ptype_expire_indirect
+ autofs_ptype_missing_direct
+ autofs_ptype_expire_direct
+
+so messages can indicate that a name is missing (something tried to
+access it but it isn't there) or that it has been selected for expiry.
+
+The pipe will be set to "packet mode" (equivalent to passing
+`O_DIRECT`) to _pipe2(2)_ so that a read from the pipe will return at
+most one packet, and any unread portion of a packet will be discarded.
+
+The `wait_queue_token` is a unique number which can identify a
+particular request to be acknowledged. When a message is sent over
+the pipe the affected dentry is marked as either "active" or
+"expiring" and other accesses to it block until the message is
+acknowledged using one of the ioctls below and the relevant
+`wait_queue_token`.
+
+Communicating with autofs: root directory ioctls
+------------------------------------------------
+
+The root directory of an autofs filesystem will respond to a number of
+ioctls. The process issuing the ioctl must have the CAP_SYS_ADMIN
+capability, or must be the automount daemon.
+
+The available ioctl commands are:
+
+- **AUTOFS_IOC_READY**: a notification has been handled. The argument
+ to the ioctl command is the "wait_queue_token" number
+ corresponding to the notification being acknowledged.
+- **AUTOFS_IOC_FAIL**: similar to above, but indicates failure with
+ the error code `ENOENT`.
+- **AUTOFS_IOC_CATATONIC**: Causes the autofs to enter "catatonic"
+ mode meaning that it stops sending notifications to the daemon.
+ This mode is also entered if a write to the pipe fails.
+- **AUTOFS_IOC_PROTOVER**: This returns the protocol version in use.
+- **AUTOFS_IOC_PROTOSUBVER**: Returns the protocol sub-version which
+ is really a version number for the implementation. It is
+ currently 2.
+- **AUTOFS_IOC_SETTIMEOUT**: This passes a pointer to an unsigned
+ long. The value is used to set the timeout for expiry, and
+ the current timeout value is stored back through the pointer.
+- **AUTOFS_IOC_ASKUMOUNT**: Returns, in the pointed-to `int`, 1 if
+ the filesystem could be unmounted. This is only a hint as
+ the situation could change at any instant. This call can be
+ use to avoid a more expensive full unmount attempt.
+- **AUTOFS_IOC_EXPIRE**: as described above, this asks if there is
+ anything suitable to expire. A pointer to a packet:
+
+ struct autofs_packet_expire_multi {
+ int proto_version; /* Protocol version */
+ int type; /* Type of packet */
+ autofs_wqt_t wait_queue_token;
+ int len;
+ char name[NAME_MAX+1];
+ };
+
+ is required. This is filled in with the name of something
+ that can be unmounted or removed. If nothing can be expired,
+ `errno` is set to `EAGAIN`. Even though a `wait_queue_token`
+ is present in the structure, no "wait queue" is established
+ and no acknowledgment is needed.
+- **AUTOFS_IOC_EXPIRE_MULTI**: This is similar to
+ **AUTOFS_IOC_EXPIRE** except that it causes notification to be
+ sent to the daemon, and it blocks until the daemon acknowledges.
+ The argument is an integer which can contain two different flags.
+
+ **AUTOFS_EXP_IMMEDIATE** causes `last_used` time to be ignored
+ and objects are expired if the are not in use.
+
+ **AUTOFS_EXP_LEAVES** will select a leaf rather than a top-level
+ name to expire. This is only safe when *maxproto* is 4.
+
+Communicating with autofs: char-device ioctls
+---------------------------------------------
+
+It is not always possible to open the root of an autofs filesystem,
+particularly a *direct* mounted filesystem. If the automount daemon
+is restarted there is no way for it to regain control of existing
+mounts using any of the above communication channels. To address this
+need there is a "miscellaneous" character device (major 10, minor 235)
+which can be used to communicate directly with the autofs filesystem.
+It requires CAP_SYS_ADMIN for access.
+
+The `ioctl`s that can be used on this device are described in a separate
+document `autofs4-mount-control.txt`, and are summarized briefly here.
+Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:
+
+ struct autofs_dev_ioctl {
+ __u32 ver_major;
+ __u32 ver_minor;
+ __u32 size; /* total size of data passed in
+ * including this struct */
+ __s32 ioctlfd; /* automount command fd */
+
+ __u32 arg1; /* Command parameters */
+ __u32 arg2;
+
+ char path[0];
+ };
+
+For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target
+filesystem is identified by the `path`. All other commands identify
+the filesystem by the `ioctlfd` which is a file descriptor open on the
+root, and which can be returned by **OPEN_MOUNT**.
+
+The `ver_major` and `ver_minor` are in/out parameters which check that
+the requested version is supported, and report the maximum version
+that the kernel module can support.
+
+Commands are:
+
+- **AUTOFS_DEV_IOCTL_VERSION_CMD**: does nothing, except validate and
+ set version numbers.
+- **AUTOFS_DEV_IOCTL_OPENMOUNT_CMD**: return an open file descriptor
+ on the root of an autofs filesystem. The filesystem is identified
+ by name and device number, which is stored in `arg1`. Device
+ numbers for existing filesystems can be found in
+ `/proc/self/mountinfo`.
+- **AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD**: same as `close(ioctlfd)`.
+- **AUTOFS_DEV_IOCTL_SETPIPEFD_CMD**: if the filesystem is in
+ catatonic mode, this can provide the write end of a new pipe
+ in `arg1` to re-establish communication with a daemon. The
+ process group of the calling process is used to identify the
+ daemon.
+- **AUTOFS_DEV_IOCTL_REQUESTER_CMD**: `path` should be a
+ name within the filesystem that has been auto-mounted on.
+ arg1 is the dev number of the underlying autofs. On successful
+ return, `arg1` and `arg2` will be the UID and GID of the process
+ which triggered that mount.
+
+- **AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD**: Check if path is a
+ mountpoint of a particular type - see separate documentation for
+ details.
+
+- **AUTOFS_DEV_IOCTL_PROTOVER_CMD**:
+- **AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD**:
+- **AUTOFS_DEV_IOCTL_READY_CMD**:
+- **AUTOFS_DEV_IOCTL_FAIL_CMD**:
+- **AUTOFS_DEV_IOCTL_CATATONIC_CMD**:
+- **AUTOFS_DEV_IOCTL_TIMEOUT_CMD**:
+- **AUTOFS_DEV_IOCTL_EXPIRE_CMD**:
+- **AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD**: These all have the same
+ function as the similarly named **AUTOFS_IOC** ioctls, except
+ that **FAIL** can be given an explicit error number in `arg1`
+ instead of assuming `ENOENT`, and this **EXPIRE** command
+ corresponds to **AUTOFS_IOC_EXPIRE_MULTI**.
+
+Catatonic mode
+--------------
+
+As mentioned, an autofs mount can enter "catatonic" mode. This
+happens if a write to the notification pipe fails, or if it is
+explicitly requested by an `ioctl`.
+
+When entering catatonic mode, the pipe is closed and any pending
+notifications are acknowledged with the error `ENOENT`.
+
+Once in catatonic mode attempts to access non-existing names will
+result in `ENOENT` while attempts to access existing directories will
+be treated in the same way as if they came from the daemon, so mount
+traps will not fire.
+
+When the filesystem is mounted a _uid_ and _gid_ can be given which
+set the ownership of directories and symbolic links. When the
+filesystem is in catatonic mode, any process with a matching UID can
+create directories or symlinks in the root directory, but not in other
+directories.
+
+Catatonic mode can only be left via the
+**AUTOFS_DEV_IOCTL_OPENMOUNT_CMD** ioctl on the `/dev/autofs`.
+
+autofs, name spaces, and shared mounts
+--------------------------------------
+
+With bind mounts and name spaces it is possible for an autofs
+filesystem to appear at multiple places in one or more filesystem
+name spaces. For this to work sensibly, the autofs filesystem should
+always be mounted "shared". e.g.
+
+> `mount --make-shared /autofs/mount/point`
+
+The automount daemon is only able to mange a single mount location for
+an autofs filesystem and if mounts on that are not 'shared', other
+locations will not behave as expected. In particular access to those
+other locations will likely result in the `ELOOP` error
+
+> Too many levels of symbolic links
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index b4498218c474..5a615c14f75d 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -70,6 +70,38 @@ DMA addresses types dma_addr_t:
For printing a dma_addr_t type which can vary based on build options,
regardless of the width of the CPU data path. Passed by reference.
+Raw buffer as an escaped string:
+
+ %*pE[achnops]
+
+ For printing raw buffer as an escaped string. For the following buffer
+
+ 1b 62 20 5c 43 07 22 90 0d 5d
+
+ few examples show how the conversion would be done (the result string
+ without surrounding quotes):
+
+ %*pE "\eb \C\a"\220\r]"
+ %*pEhp "\x1bb \C\x07"\x90\x0d]"
+ %*pEa "\e\142\040\\\103\a\042\220\r\135"
+
+ The conversion rules are applied according to an optional combination
+ of flags (see string_escape_mem() kernel documentation for the
+ details):
+ a - ESCAPE_ANY
+ c - ESCAPE_SPECIAL
+ h - ESCAPE_HEX
+ n - ESCAPE_NULL
+ o - ESCAPE_OCTAL
+ p - ESCAPE_NP
+ s - ESCAPE_SPACE
+ By default ESCAPE_ANY_NP is used.
+
+ ESCAPE_ANY_NP is the sane choice for many cases, in particularly for
+ printing SSIDs.
+
+ If field width is omitted the 1 byte only will be escaped.
+
Raw buffer as a hex string:
%*ph 00 01 02 ... 3f
%*phC 00:01:02: ... :3f
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index f79eb9666379..57baff5bdb80 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -190,6 +190,8 @@ core_pattern is used to specify a core dumpfile pattern name.
%% output one '%'
%p pid
%P global pid (init PID namespace)
+ %i tid
+ %I global tid (init PID namespace)
%u uid
%g gid
%d dump mode, matches PR_SET_DUMPABLE and
diff --git a/MAINTAINERS b/MAINTAINERS
index f413abff3807..c52367997fb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1338,8 +1338,7 @@ ARM/SAMSUNG MOBILE MACHINE SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: arch/arm/mach-s5pv210/mach-aquila.c
-F: arch/arm/mach-s5pv210/mach-goni.c
+F: arch/arm/mach-s5pv210/
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com>
@@ -1550,6 +1549,7 @@ T: git git://git.xilinx.com/linux-xlnx.git
S: Supported
F: arch/arm/mach-zynq/
F: drivers/cpuidle/cpuidle-zynq.c
+F: drivers/block/xsysace.c
N: zynq
N: xilinx
F: drivers/clocksource/cadence_ttc_timer.c
@@ -1738,6 +1738,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/net/ethernet/cadence/
+ATMEL NAND DRIVER
+M: Josh Wu <josh.wu@atmel.com>
+L: linux-mtd@lists.infradead.org
+S: Supported
+F: drivers/mtd/nand/atmel_nand*
+
ATMEL SPI DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
@@ -3048,7 +3054,7 @@ M: Sumit Semwal <sumit.semwal@linaro.org>
S: Maintained
L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org
-L: linaro-mm-sig@lists.linaro.org
+L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
F: drivers/dma-buf/
F: include/linux/dma-buf*
F: include/linux/reservation.h
@@ -4297,9 +4303,8 @@ S: Maintained
F: drivers/media/dvb-frontends/hd29l2*
HEWLETT-PACKARD SMART2 RAID DRIVER
-M: Chirag Kantharia <chirag.kantharia@hp.com>
L: iss_storagedev@hp.com
-S: Maintained
+S: Orphan
F: Documentation/blockdev/cpqarray.txt
F: drivers/block/cpqarray.*
@@ -5300,6 +5305,13 @@ F: include/linux/lockd/
F: include/linux/sunrpc/
F: include/uapi/linux/sunrpc/
+KERNEL SELFTEST FRAMEWORK
+M: Shuah Khan <shuahkh@osg.samsung.com>
+L: linux-api@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/shuah/linux-kselftest
+S: Maintained
+F: tools/testing/selftests
+
KERNEL VIRTUAL MACHINE (KVM)
M: Gleb Natapov <gleb@kernel.org>
M: Paolo Bonzini <pbonzini@redhat.com>
@@ -5746,11 +5758,8 @@ T: git git://github.com/linux-test-project/ltp.git
S: Maintained
M32R ARCHITECTURE
-M: Hirokazu Takata <takata@linux-m32r.org>
-L: linux-m32r@ml.linux-m32r.org (moderated for non-subscribers)
-L: linux-m32r-ja@ml.linux-m32r.org (in Japanese)
W: http://www.linux-m32r.org/
-S: Maintained
+S: Orphan
F: arch/m32r/
M68K ARCHITECTURE
@@ -7974,7 +7983,6 @@ S: Supported
F: drivers/mfd/sec*.c
F: drivers/regulator/s2m*.c
F: drivers/regulator/s5m*.c
-F: drivers/rtc/rtc-sec.c
F: include/linux/mfd/samsung/
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
@@ -10315,10 +10323,6 @@ M: John Linn <John.Linn@xilinx.com>
S: Maintained
F: drivers/net/ethernet/xilinx/xilinx_axienet*
-XILINX SYSTEMACE DRIVER
-S: Orphan
-F: drivers/block/xsysace.c
-
XILINX UARTLITE SERIAL DRIVER
M: Peter Korsgaard <jacmet@sunsite.dk>
L: linux-serial@vger.kernel.org
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 1d52de6370d5..429a6c6cfcf9 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -164,7 +164,7 @@
};
rtc: rtc@10070000 {
- compatible = "samsung,s3c6410-rtc";
+ compatible = "samsung,exynos3250-rtc";
reg = <0x10070000 0x100>;
interrupts = <0 73 0>, <0 74 0>;
status = "disabled";
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 9f6ec167902a..ad777b353bd5 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -416,17 +416,17 @@ static struct pxafb_mach_info *lpd270_lcd_to_use;
static int __init lpd270_set_lcd(char *str)
{
- if (!strnicmp(str, "lq057q3dc02", 11)) {
+ if (!strncasecmp(str, "lq057q3dc02", 11)) {
lpd270_lcd_to_use = &sharp_lq057q3dc02;
- } else if (!strnicmp(str, "lq121s1dg31", 11)) {
+ } else if (!strncasecmp(str, "lq121s1dg31", 11)) {
lpd270_lcd_to_use = &sharp_lq121s1dg31;
- } else if (!strnicmp(str, "lq036q1da01", 11)) {
+ } else if (!strncasecmp(str, "lq036q1da01", 11)) {
lpd270_lcd_to_use = &sharp_lq036q1da01;
- } else if (!strnicmp(str, "lq64d343", 8)) {
+ } else if (!strncasecmp(str, "lq64d343", 8)) {
lpd270_lcd_to_use = &sharp_lq64d343;
- } else if (!strnicmp(str, "lq10d368", 8)) {
+ } else if (!strncasecmp(str, "lq10d368", 8)) {
lpd270_lcd_to_use = &sharp_lq10d368;
- } else if (!strnicmp(str, "lq035q7db02-20", 14)) {
+ } else if (!strncasecmp(str, "lq035q7db02-20", 14)) {
lpd270_lcd_to_use = &sharp_lq035q7db02_20;
} else {
printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str);
diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c
index 6aea124f574d..2fb9b3ab57b9 100644
--- a/arch/frv/mm/extable.c
+++ b/arch/frv/mm/extable.c
@@ -6,8 +6,6 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
-extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
-extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
extern spinlock_t modlist_lock;
diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h
index 1a873b36a4a1..2ab2003698ef 100644
--- a/arch/ia64/include/asm/sections.h
+++ b/arch/ia64/include/asm/sections.h
@@ -10,7 +10,7 @@
#include <linux/uaccess.h>
#include <asm-generic/sections.h>
-extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
+extern char __phys_per_cpu_start[];
#ifdef CONFIG_SMP
extern char __cpu0_per_cpu[];
#endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 700f958652f8..3eff36f719fb 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -964,6 +964,7 @@ static void vgetcpu_set_mode(void)
vgetcpu_mode = VGETCPU_LSL;
}
+#ifdef CONFIG_IA32_EMULATION
/* May not be __init: called during resume */
static void syscall32_cpu_init(void)
{
@@ -975,7 +976,8 @@ static void syscall32_cpu_init(void)
wrmsrl(MSR_CSTAR, ia32_cstar_target);
}
-#endif
+#endif /* CONFIG_IA32_EMULATION */
+#endif /* CONFIG_X86_64 */
#ifdef CONFIG_X86_32
void enable_sep_cpu(void)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index a618fcd2c07d..f5ab56d14287 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -237,7 +237,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
ced->max_nr_ranges++;
/* If crashk_low_res is not 0, another range split possible */
- if (crashk_low_res.end != 0)
+ if (crashk_low_res.end)
ced->max_nr_ranges++;
}
@@ -335,9 +335,11 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
if (ret)
return ret;
- ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
- if (ret)
- return ret;
+ if (crashk_low_res.end) {
+ ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
+ if (ret)
+ return ret;
+ }
/* Exclude GART region */
if (ced->gart_end) {
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 9642b9b33655..ca05f86481aa 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -26,6 +26,7 @@
#include <asm/setup.h>
#include <asm/crash.h>
#include <asm/efi.h>
+#include <asm/kexec-bzimage64.h>
#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
@@ -267,7 +268,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
return ret;
}
-int bzImage64_probe(const char *buf, unsigned long len)
+static int bzImage64_probe(const char *buf, unsigned long len)
{
int ret = -ENOEXEC;
struct setup_header *header;
@@ -325,10 +326,10 @@ int bzImage64_probe(const char *buf, unsigned long len)
return ret;
}
-void *bzImage64_load(struct kimage *image, char *kernel,
- unsigned long kernel_len, char *initrd,
- unsigned long initrd_len, char *cmdline,
- unsigned long cmdline_len)
+static void *bzImage64_load(struct kimage *image, char *kernel,
+ unsigned long kernel_len, char *initrd,
+ unsigned long initrd_len, char *cmdline,
+ unsigned long cmdline_len)
{
struct setup_header *header;
@@ -514,7 +515,7 @@ out_free_params:
}
/* This cleanup function is called after various segments have been loaded */
-int bzImage64_cleanup(void *loader_data)
+static int bzImage64_cleanup(void *loader_data)
{
struct bzimage64_data *ldata = loader_data;
@@ -528,7 +529,7 @@ int bzImage64_cleanup(void *loader_data)
}
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
-int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
+static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
{
bool trusted;
int ret;
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 3dd8e2c4d74a..95c3cb16af3e 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/kprobes.h>
#include <linux/debugfs.h>
+#include <linux/nmi.h>
#include <asm/timer.h>
#include <asm/cpu.h>
#include <asm/traps.h>
@@ -499,6 +500,13 @@ void __init kvm_guest_init(void)
#else
kvm_guest_cpu_init();
#endif
+
+ /*
+ * Hard lockup detection is enabled by default. Disable it, as guests
+ * can get false positives too easily, for example if the host is
+ * overcommitted.
+ */
+ watchdog_enable_hardlockup_detector(false);
}
static noinline uint32_t __kvm_cpuid_base(void)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da354e0..af78e50ca6ce 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -86,6 +86,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
pgprot_t prot;
int retval;
void __iomem *ret_addr;
+ int ram_region;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -108,12 +109,23 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
- pfn = phys_addr >> PAGE_SHIFT;
- last_pfn = last_addr >> PAGE_SHIFT;
- if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
- __ioremap_check_ram) == 1)
+ /* First check if whole region can be identified as RAM or not */
+ ram_region = region_is_ram(phys_addr, size);
+ if (ram_region > 0) {
+ WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n",
+ (unsigned long int)phys_addr,
+ (unsigned long int)last_addr);
return NULL;
+ }
+ /* If could not be identified(-1), check page by page */
+ if (ram_region < 0) {
+ pfn = phys_addr >> PAGE_SHIFT;
+ last_pfn = last_addr >> PAGE_SHIFT;
+ if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
+ __ioremap_check_ram) == 1)
+ return NULL;
+ }
/*
* Mappings have to be page-aligned
*/
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index d221374d5ce8..1a883705a12a 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -463,6 +463,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
return true;
}
+static void __init numa_clear_kernel_node_hotplug(void)
+{
+ int i, nid;
+ nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
+ unsigned long start, end;
+ struct memblock_region *r;
+
+ /*
+ * At this time, all memory regions reserved by memblock are
+ * used by the kernel. Set the nid in memblock.reserved will
+ * mark out all the nodes the kernel resides in.
+ */
+ for (i = 0; i < numa_meminfo.nr_blks; i++) {
+ struct numa_memblk *mb = &numa_meminfo.blk[i];
+
+ memblock_set_node(mb->start, mb->end - mb->start,
+ &memblock.reserved, mb->nid);
+ }
+
+ /* Mark all kernel nodes. */
+ for_each_memblock(reserved, r)
+ node_set(r->nid, numa_kernel_nodes);
+
+ /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
+ for (i = 0; i < numa_meminfo.nr_blks; i++) {
+ nid = numa_meminfo.blk[i].nid;
+ if (!node_isset(nid, numa_kernel_nodes))
+ continue;
+
+ start = numa_meminfo.blk[i].start;
+ end = numa_meminfo.blk[i].end;
+
+ memblock_clear_hotplug(start, end - start);
+ }
+}
+
static int __init numa_register_memblks(struct numa_meminfo *mi)
{
unsigned long uninitialized_var(pfn_align);
@@ -481,6 +517,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
}
/*
+ * At very early time, the kernel have to use some memory such as
+ * loading the kernel image. We cannot prevent this anyway. So any
+ * node the kernel resides in should be un-hotpluggable.
+ *
+ * And when we come here, alloc node data won't fail.
+ */
+ numa_clear_kernel_node_hotplug();
+
+ /*
* If sections array is gonna be used for pfn -> nid mapping, check
* whether its granularity is fine enough.
*/
@@ -548,41 +593,6 @@ static void __init numa_init_array(void)
}
}
-static void __init numa_clear_kernel_node_hotplug(void)
-{
- int i, nid;
- nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
- unsigned long start, end;
- struct memblock_region *r;
-
- /*
- * At this time, all memory regions reserved by memblock are
- * used by the kernel. Set the nid in memblock.reserved will
- * mark out all the nodes the kernel resides in.
- */
- for (i = 0; i < numa_meminfo.nr_blks; i++) {
- struct numa_memblk *mb = &numa_meminfo.blk[i];
- memblock_set_node(mb->start, mb->end - mb->start,
- &memblock.reserved, mb->nid);
- }
-
- /* Mark all kernel nodes. */
- for_each_memblock(reserved, r)
- node_set(r->nid, numa_kernel_nodes);
-
- /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
- for (i = 0; i < numa_meminfo.nr_blks; i++) {
- nid = numa_meminfo.blk[i].nid;
- if (!node_isset(nid, numa_kernel_nodes))
- continue;
-
- start = numa_meminfo.blk[i].start;
- end = numa_meminfo.blk[i].end;
-
- memblock_clear_hotplug(start, end - start);
- }
-}
-
static int __init numa_init(int (*init_func)(void))
{
int i;
@@ -637,15 +647,6 @@ static int __init numa_init(int (*init_func)(void))
}
numa_init_array();
- /*
- * At very early time, the kernel have to use some memory such as
- * loading the kernel image. We cannot prevent this anyway. So any
- * node the kernel resides in should be un-hotpluggable.
- *
- * And when we come here, numa_init() won't fail.
- */
- numa_clear_kernel_node_hotplug();
-
return 0;
}
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 899dd2454256..f52e033557c9 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -18,8 +18,9 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
targets += kexec-purgatory.c
+CMD_BIN2C = $(objtree)/scripts/basic/bin2c
quiet_cmd_bin2c = BIN2C $@
- cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c
+ cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
$(call if_changed,bin2c)
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index 7d6e84a51424..55b83983a9c0 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -14,11 +14,14 @@ struct dma_coherent_mem {
int size;
int flags;
unsigned long *bitmap;
+ spinlock_t spinlock;
};
-int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
- dma_addr_t device_addr, size_t size, int flags)
+static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr,
+ size_t size, int flags,
+ struct dma_coherent_mem **mem)
{
+ struct dma_coherent_mem *dma_mem = NULL;
void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
@@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
goto out;
if (!size)
goto out;
- if (dev->dma_mem)
- goto out;
-
- /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(phys_addr, size);
if (!mem_base)
goto out;
- dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
- if (!dev->dma_mem)
+ dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+ if (!dma_mem)
goto out;
- dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!dev->dma_mem->bitmap)
- goto free1_out;
+ dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!dma_mem->bitmap)
+ goto out;
+
+ dma_mem->virt_base = mem_base;
+ dma_mem->device_base = device_addr;
+ dma_mem->pfn_base = PFN_DOWN(phys_addr);
+ dma_mem->size = pages;
+ dma_mem->flags = flags;
+ spin_lock_init(&dma_mem->spinlock);
- dev->dma_mem->virt_base = mem_base;
- dev->dma_mem->device_base = device_addr;
- dev->dma_mem->pfn_base = PFN_DOWN(phys_addr);
- dev->dma_mem->size = pages;
- dev->dma_mem->flags = flags;
+ *mem = dma_mem;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
- free1_out:
- kfree(dev->dma_mem);
- out:
+out:
+ kfree(dma_mem);
if (mem_base)
iounmap(mem_base);
return 0;
}
+
+static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
+{
+ if (!mem)
+ return;
+ iounmap(mem->virt_base);
+ kfree(mem->bitmap);
+ kfree(mem);
+}
+
+static int dma_assign_coherent_memory(struct device *dev,
+ struct dma_coherent_mem *mem)
+{
+ if (dev->dma_mem)
+ return -EBUSY;
+
+ dev->dma_mem = mem;
+ /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+ return 0;
+}
+
+int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
+ dma_addr_t device_addr, size_t size, int flags)
+{
+ struct dma_coherent_mem *mem;
+ int ret;
+
+ ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags,
+ &mem);
+ if (ret == 0)
+ return 0;
+
+ if (dma_assign_coherent_memory(dev, mem) == 0)
+ return ret;
+
+ dma_release_coherent_memory(mem);
+ return 0;
+}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
@@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev)
if (!mem)
return;
+ dma_release_coherent_memory(mem);
dev->dma_mem = NULL;
- iounmap(mem->virt_base);
- kfree(mem->bitmap);
- kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
@@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
+ unsigned long flags;
int pos, err;
size += device_addr & ~PAGE_MASK;
@@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
if (!mem)
return ERR_PTR(-EINVAL);
+ spin_lock_irqsave(&mem->spinlock, flags);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
+ spin_unlock_irqrestore(&mem->spinlock, flags);
+
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
@@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
{
struct dma_coherent_mem *mem;
int order = get_order(size);
+ unsigned long flags;
int pageno;
if (!dev)
@@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
return 0;
*ret = NULL;
+ spin_lock_irqsave(&mem->spinlock, flags);
if (unlikely(size > (mem->size << PAGE_SHIFT)))
goto err;
@@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
*ret = mem->virt_base + (pageno << PAGE_SHIFT);
memset(*ret, 0, size);
+ spin_unlock_irqrestore(&mem->spinlock, flags);
return 1;
err:
+ spin_unlock_irqrestore(&mem->spinlock, flags);
/*
* In the case where the allocation can not be satisfied from the
* per-device area, try to fall back to generic memory if the
@@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
if (mem && vaddr >= mem->virt_base && vaddr <
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+ unsigned long flags;
+ spin_lock_irqsave(&mem->spinlock, flags);
bitmap_release_region(mem->bitmap, page, order);
+ spin_unlock_irqrestore(&mem->spinlock, flags);
return 1;
}
return 0;
@@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
return 0;
}
EXPORT_SYMBOL(dma_mmap_from_coherent);
+
+/*
+ * Support for reserved memory regions defined in device tree
+ */
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+ struct dma_coherent_mem *mem = rmem->priv;
+
+ if (!mem &&
+ dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
+ DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE,
+ &mem) != DMA_MEMORY_MAP) {
+ pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
+ &rmem->base, (unsigned long)rmem->size / SZ_1M);
+ return -ENODEV;
+ }
+ rmem->priv = mem;
+ dma_assign_coherent_memory(dev, mem);
+ return 0;
+}
+
+static void rmem_dma_device_release(struct reserved_mem *rmem,
+ struct device *dev)
+{
+ dev->dma_mem = NULL;
+}
+
+static const struct reserved_mem_ops rmem_dma_ops = {
+ .device_init = rmem_dma_device_init,
+ .device_release = rmem_dma_device_release,
+};
+
+static int __init rmem_dma_setup(struct reserved_mem *rmem)
+{
+ unsigned long node = rmem->fdt_node;
+
+ if (of_get_flat_dt_prop(node, "reusable", NULL))
+ return -EINVAL;
+
+#ifdef CONFIG_ARM
+ if (!of_get_flat_dt_prop(node, "no-map", NULL)) {
+ pr_err("Reserved memory: regions without no-map are not yet supported\n");
+ return -EINVAL;
+ }
+#endif
+
+ rmem->ops = &rmem_dma_ops;
+ pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n",
+ &rmem->base, (unsigned long)rmem->size / SZ_1M);
+ return 0;
+}
+RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
+#endif
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 6606abdf880c..473ff4892401 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
{
return cma_release(dev_get_cma_area(dev), pages, count);
}
+
+/*
+ * Support for reserved memory regions defined in device tree
+ */
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) fmt
+
+static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+ dev_set_cma_area(dev, rmem->priv);
+}
+
+static void rmem_cma_device_release(struct reserved_mem *rmem,
+ struct device *dev)
+{
+ dev_set_cma_area(dev, NULL);
+}
+
+static const struct reserved_mem_ops rmem_cma_ops = {
+ .device_init = rmem_cma_device_init,
+ .device_release = rmem_cma_device_release,
+};
+
+static int __init rmem_cma_setup(struct reserved_mem *rmem)
+{
+ phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+ phys_addr_t mask = align - 1;
+ unsigned long node = rmem->fdt_node;
+ struct cma *cma;
+ int err;
+
+ if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
+ of_get_flat_dt_prop(node, "no-map", NULL))
+ return -EINVAL;
+
+ if ((rmem->base & mask) || (rmem->size & mask)) {
+ pr_err("Reserved memory: incorrect alignment of CMA region\n");
+ return -EINVAL;
+ }
+
+ err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
+ if (err) {
+ pr_err("Reserved memory: unable to setup CMA region\n");
+ return err;
+ }
+ /* Architecture specific contiguous memory fixup. */
+ dma_contiguous_early_fixup(rmem->base, rmem->size);
+
+ if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
+ dma_contiguous_set_default(cma);
+
+ rmem->ops = &rmem_cma_ops;
+ rmem->priv = cma;
+
+ pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",
+ &rmem->base, (unsigned long)rmem->size / SZ_1M);
+
+ return 0;
+}
+RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);
+#endif
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index cfd3af7b2cbd..84e0590e31dc 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686
---help---
This driver supports Maxim 77686 crystal oscillator clock.
+config COMMON_CLK_RK808
+ tristate "Clock driver for RK808"
+ depends on MFD_RK808
+ ---help---
+ This driver supports RK808 crystal oscillator clock. These
+ multi-function devices have two fixed-rate oscillators,
+ clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
+ by control register.
+
config COMMON_CLK_SI5351
tristate "Clock driver for SiLabs 5351A/B/C"
depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f537a0b1f798..99f53d5f8766 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c
new file mode 100644
index 000000000000..83902b9cd49e
--- /dev/null
+++ b/drivers/clk/clk-rk808.c
@@ -0,0 +1,170 @@
+/*
+ * Clkout driver for Rockchip RK808
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author:Chris Zhong <zyw@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/rk808.h>
+#include <linux/i2c.h>
+
+#define RK808_NR_OUTPUT 2
+
+struct rk808_clkout {
+ struct rk808 *rk808;
+ struct clk_onecell_data clk_data;
+ struct clk_hw clkout1_hw;
+ struct clk_hw clkout2_hw;
+};
+
+static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return 32768;
+}
+
+static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
+{
+ struct rk808_clkout *rk808_clkout = container_of(hw,
+ struct rk808_clkout,
+ clkout2_hw);
+ struct rk808 *rk808 = rk808_clkout->rk808;
+
+ return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
+ CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
+}
+
+static int rk808_clkout2_prepare(struct clk_hw *hw)
+{
+ return rk808_clkout2_enable(hw, true);
+}
+
+static void rk808_clkout2_unprepare(struct clk_hw *hw)
+{
+ rk808_clkout2_enable(hw, false);
+}
+
+static int rk808_clkout2_is_prepared(struct clk_hw *hw)
+{
+ struct rk808_clkout *rk808_clkout = container_of(hw,
+ struct rk808_clkout,
+ clkout2_hw);
+ struct rk808 *rk808 = rk808_clkout->rk808;
+ uint32_t val;
+
+ int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
+
+ if (ret < 0)
+ return ret;
+
+ return (val & CLK32KOUT2_EN) ? 1 : 0;
+}
+
+static const struct clk_ops rk808_clkout1_ops = {
+ .recalc_rate = rk808_clkout_recalc_rate,
+};
+
+static const struct clk_ops rk808_clkout2_ops = {
+ .prepare = rk808_clkout2_prepare,
+ .unprepare = rk808_clkout2_unprepare,
+ .is_prepared = rk808_clkout2_is_prepared,
+ .recalc_rate = rk808_clkout_recalc_rate,
+};
+
+static int rk808_clkout_probe(struct platform_device *pdev)
+{
+ struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+ struct i2c_client *client = rk808->i2c;
+ struct device_node *node = client->dev.of_node;
+ struct clk_init_data init = {};
+ struct clk **clk_table;
+ struct rk808_clkout *rk808_clkout;
+
+ rk808_clkout = devm_kzalloc(&client->dev,
+ sizeof(*rk808_clkout), GFP_KERNEL);
+ if (!rk808_clkout)
+ return -ENOMEM;
+
+ rk808_clkout->rk808 = rk808;
+
+ clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT,
+ sizeof(struct clk *), GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ init.flags = CLK_IS_ROOT;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ init.name = "rk808-clkout1";
+ init.ops = &rk808_clkout1_ops;
+ rk808_clkout->clkout1_hw.init = &init;
+
+ /* optional override of the clockname */
+ of_property_read_string_index(node, "clock-output-names",
+ 0, &init.name);
+
+ clk_table[0] = devm_clk_register(&client->dev,
+ &rk808_clkout->clkout1_hw);
+ if (IS_ERR(clk_table[0]))
+ return PTR_ERR(clk_table[0]);
+
+ init.name = "rk808-clkout2";
+ init.ops = &rk808_clkout2_ops;
+ rk808_clkout->clkout2_hw.init = &init;
+
+ /* optional override of the clockname */
+ of_property_read_string_index(node, "clock-output-names",
+ 1, &init.name);
+
+ clk_table[1] = devm_clk_register(&client->dev,
+ &rk808_clkout->clkout2_hw);
+ if (IS_ERR(clk_table[1]))
+ return PTR_ERR(clk_table[1]);
+
+ rk808_clkout->clk_data.clks = clk_table;
+ rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get,
+ &rk808_clkout->clk_data);
+}
+
+static int rk808_clkout_remove(struct platform_device *pdev)
+{
+ struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+ struct i2c_client *client = rk808->i2c;
+ struct device_node *node = client->dev.of_node;
+
+ of_clk_del_provider(node);
+
+ return 0;
+}
+
+static struct platform_driver rk808_clkout_driver = {
+ .probe = rk808_clkout_probe,
+ .remove = rk808_clkout_remove,
+ .driver = {
+ .name = "rk808-clkout",
+ },
+};
+
+module_platform_driver(rk808_clkout_driver);
+
+MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk808-clkout");
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index d28a8c284da9..7206547c13ce 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
int ret, rc;
p = name;
- if (strnicmp(p, "0x", 2) == 0)
+ if (strncasecmp(p, "0x", 2) == 0)
p += 2;
ret = -EINVAL;
len = strlen(p);
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 8857d5b9be71..ee3434f1e949 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
/* if we find something consistent, stay with that assumption
* at least M09 won't send 3 bytes here
*/
- if (!(strnicmp(rdbuf + 1, "EP0", 3))) {
+ if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
tsdata->version = M06;
/* remove last '$' end marker */
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
index 31727bf285d0..e2a4f5f415b2 100644
--- a/drivers/memstick/host/r592.c
+++ b/drivers/memstick/host/r592.c
@@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev)
r592_set_mode(dev, dev->parallel_mode);
}
+#ifdef CONFIG_PM_SLEEP
/* Disable all hardware interrupts */
static void r592_clear_interrupts(struct r592_device *dev)
{
@@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev)
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK);
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK);
}
+#endif
/* Tests if there is an CRC error */
static int r592_test_io_error(struct r592_device *dev)
diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c
index 24272e022bec..bca2630d006f 100644
--- a/drivers/misc/altera-stapl/altera.c
+++ b/drivers/misc/altera-stapl/altera.c
@@ -454,7 +454,7 @@ exit_done:
name = &p[str_table + name_id];
- if (strnicmp(aconf->action, name, strlen(name)) == 0) {
+ if (strncasecmp(aconf->action, name, strlen(name)) == 0) {
action_found = 1;
current_proc =
get_unaligned_be32(&p[action_table +
@@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size,
key_ptr = &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])];
- if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) &&
+ if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) &&
(key != NULL)) {
status = 0;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index 8efd17c52f65..dd84557cf957 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
local_info_t *local = m->private;
struct list_head *ptr = v;
struct hostap_bss_info *bss;
- int i;
if (ptr == &local->bss_list) {
seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
bss->bssid, bss->last_update,
bss->count, bss->capab_info);
- for (i = 0; i < bss->ssid_len; i++)
- seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
- bss->ssid[i] : '_');
+ seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid);
seq_putc(m, '\t');
seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid);
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index c3d726f334e3..6fabea0309dd 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
u32 chan;
char *txratename;
u8 bssid[ETH_ALEN];
- DECLARE_SSID_BUF(ssid);
/*
* TBD: BSSID is usually 00:00:00:00:00:00 here and not
@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
break;
}
- IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
- priv->net_dev->name, print_ssid(ssid, essid, essid_len),
+ IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n",
+ priv->net_dev->name, essid_len, essid,
txratename, chan, bssid);
/* now we copy read ssid into dev */
@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
.host_command_length = ssid_len
};
int err;
- DECLARE_SSID_BUF(ssid);
- IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
+ IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid);
if (ssid_len)
memcpy(cmd.host_command_parameters, essid, ssid_len);
@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
{
- DECLARE_SSID_BUF(ssid);
-
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
- "disassociated: '%s' %pM\n",
- print_ssid(ssid, priv->essid, priv->essid_len),
+ "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid,
priv->bssid);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
char *essid = ""; /* ANY */
int length = 0;
int err = 0;
- DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
goto done;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
- print_ssid(ssid, essid, length), length);
+ IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length);
priv->essid_len = length;
memcpy(priv->essid, essid, priv->essid_len);
@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
*/
struct ipw2100_priv *priv = libipw_priv(dev);
- DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
- IPW_DEBUG_WX("Getting essid: '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+ priv->essid_len, priv->essid);
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index f0c3c77a48d3..edc344334a75 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv)
static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
- DECLARE_SSID_BUF(ssid);
u16 size = le16_to_cpu(notif->size);
IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
@@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case CMAS_ASSOCIATED:{
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "associated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "associated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
switch (priv->ieee->iw_mode) {
@@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF |
IPW_DL_STATE |
IPW_DL_ASSOC,
- "deauthenticated: '%s' "
- "%pM"
- ": (0x%04X) - %s\n",
- print_ssid(ssid,
- priv->
- essid,
- priv->
- essid_len),
+ "deauthenticated: '%*pE' %pM: (0x%04X) - %s\n",
+ priv->essid_len,
+ priv->essid,
priv->bssid,
le16_to_cpu(auth->status),
ipw_get_status_code
@@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "authenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "authenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
break;
}
@@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "disassociated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "disassociated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status &=
@@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
switch (auth->state) {
case CMAS_AUTHENTICATED:
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
- "authenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "authenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status |= STATUS_AUTH;
break;
@@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "deauthenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "deauthenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status &= ~(STATUS_ASSOCIATING |
@@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
- "capability mismatch.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of non-network ESSID.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
((network->ssid_len != priv->essid_len) ||
memcmp(network->ssid, priv->essid,
min(network->ssid_len, priv->essid_len)))) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-
- strlcpy(escaped,
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of ESSID mismatch: '%s'.\n",
- escaped, network->bssid,
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->essid_len,
+ priv->essid);
return 0;
}
}
@@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
* testing everything else. */
if (network->time_stamp[0] < match->network->time_stamp[0]) {
- IPW_DEBUG_MERGE("Network '%s excluded because newer than "
- "current network.\n",
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len));
+ IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+ match->network->ssid_len, match->network->ssid);
return 0;
} else if (network->time_stamp[1] < match->network->time_stamp[1]) {
- IPW_DEBUG_MERGE("Network '%s excluded because newer than "
- "current network.\n",
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len));
+ IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+ match->network->ssid_len, match->network->ssid);
return 0;
}
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of age: %ums.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
@@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of channel mismatch: %d != %d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+ network->ssid_len, network->ssid,
network->bssid,
network->channel, priv->channel);
return 0;
@@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Verify privacy compatibility */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of privacy mismatch: %s != %s.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+ network->ssid_len, network->ssid,
network->bssid,
priv->
capability & CAP_PRIVACY_ON ? "on" : "off",
@@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
}
if (ether_addr_equal(network->bssid, priv->bssid)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of the same BSSID match: %pM"
- ".\n", print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid,
- priv->bssid);
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of invalid frequency/mode "
- "combination.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because configured rate mask excludes "
- "AP mandatory rate.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of no compatible rates.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Set up 'new' AP to this network */
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
- print_ssid(ssid, network->ssid, network->ssid_len),
- network->bssid);
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n",
+ network->ssid_len, network->ssid, network->bssid);
return 1;
}
static void ipw_merge_adhoc_network(struct work_struct *work)
{
- DECLARE_SSID_BUF(ssid);
struct ipw_priv *priv =
container_of(work, struct ipw_priv, merge_networks);
struct libipw_network *network = NULL;
@@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work)
mutex_lock(&priv->mutex);
if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
- IPW_DEBUG_MERGE("remove network %s\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_MERGE("remove network %*pE\n",
+ priv->essid_len, priv->essid);
ipw_remove_current_network(priv);
}
@@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv,
struct libipw_network *network, int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
@@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv,
!(network->capability & WLAN_CAPABILITY_ESS)) ||
(priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
- "capability mismatch.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of non-network ESSID.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv,
((network->ssid_len != priv->essid_len) ||
memcmp(network->ssid, priv->essid,
min(network->ssid_len, priv->essid_len)))) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- strlcpy(escaped,
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of ESSID mismatch: '%s'.\n",
- escaped, network->bssid,
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->essid_len,
+ priv->essid);
return 0;
}
}
@@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv,
/* If the old network rate is better than this one, don't bother
* testing everything else. */
if (match->network && match->network->stats.rssi > network->stats.rssi) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- strlcpy(escaped,
- print_ssid(ssid, network->ssid, network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
- "'%s (%pM)' has a stronger signal.\n",
- escaped, network->bssid,
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len),
- match->network->bssid);
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, match->network->ssid_len,
+ match->network->ssid, match->network->bssid);
return 0;
}
@@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv,
* last 3 seconds, do not try and associate again... */
if (network->last_associate &&
time_after(network->last_associate + (HZ * 3UL), jiffies)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of storming (%ums since last "
- "assoc attempt).\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_associate));
@@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of age: %ums.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
@@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of channel mismatch: %d != %d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+ network->ssid_len, network->ssid,
network->bssid,
network->channel, priv->channel);
return 0;
@@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Verify privacy compatibility */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of privacy mismatch: %s != %s.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+ network->ssid_len, network->ssid,
network->bssid,
priv->capability & CAP_PRIVACY_ON ? "on" :
"off",
@@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_BSSID) &&
!ether_addr_equal(network->bssid, priv->bssid)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of BSSID mismatch: %pM.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n",
+ network->ssid_len, network->ssid,
network->bssid, priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of invalid frequency/mode "
- "combination.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
/* Filter out invalid channel in current GEO */
if (!libipw_is_valid_channel(priv->ieee, network->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of invalid channel in current GEO\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because configured rate mask excludes "
- "AP mandatory rate.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of no compatible rates.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv,
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
- print_ssid(ssid, network->ssid, network->ssid_len),
- network->bssid);
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n",
+ network->ssid_len, network->ssid, network->bssid);
return 1;
}
@@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work)
static void ipw_debug_config(struct ipw_priv *priv)
{
- DECLARE_SSID_BUF(ssid);
IPW_DEBUG_INFO("Scan completed, no valid APs matched "
"[CFG 0x%08X]\n", priv->config);
if (priv->config & CFG_STATIC_CHANNEL)
@@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv)
else
IPW_DEBUG_INFO("Channel unlocked.\n");
if (priv->config & CFG_STATIC_ESSID)
- IPW_DEBUG_INFO("ESSID locked to '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_INFO("ESSID locked to '%*pE'\n",
+ priv->essid_len, priv->essid);
else
IPW_DEBUG_INFO("ESSID unlocked.\n");
if (priv->config & CFG_STATIC_BSSID)
@@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
struct ipw_supported_rates *rates, int roaming)
{
int err;
- DECLARE_SSID_BUF(ssid);
if (priv->config & CFG_FIXED_RATE)
ipw_set_fixed_rate(priv, network->mode);
@@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
priv->assoc_request.capability &=
~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
- IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, "
- "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
+ IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
roaming ? "Rea" : "A",
- print_ssid(ssid, priv->essid, priv->essid_len),
+ priv->essid_len, priv->essid,
network->channel,
ipw_modes[priv->assoc_request.ieee_mode],
rates->num_rates,
@@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv,
return err;
}
- IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n",
- print_ssid(ssid, priv->essid, priv->essid_len),
- priv->bssid);
+ IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n",
+ priv->essid_len, priv->essid, priv->bssid);
return 0;
}
@@ -7645,7 +7555,6 @@ static int ipw_associate(void *data)
struct ipw_supported_rates *rates;
struct list_head *element;
unsigned long flags;
- DECLARE_SSID_BUF(ssid);
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
@@ -7704,10 +7613,8 @@ static int ipw_associate(void *data)
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
- "network list.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
+ IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n",
+ target->ssid_len, target->ssid,
target->bssid);
list_add_tail(&target->list,
&priv->ieee->network_free_list);
@@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
{
struct ipw_priv *priv = libipw_priv(dev);
int length;
- DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->mutex);
@@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
return 0;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
- print_ssid(ssid, extra, length), length);
+ IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length);
priv->essid_len = length;
memcpy(priv->essid, extra, priv->essid_len);
@@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = libipw_priv(dev);
- DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
mutex_lock(&priv->mutex);
if (priv->config & CFG_STATIC_ESSID ||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
- IPW_DEBUG_WX("Getting essid: '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+ priv->essid_len, priv->essid);
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index a586a85bfcfe..2d66984079bb 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element
*info_element, u16 length,
struct libipw_network *network)
{
- DECLARE_SSID_BUF(ssid);
u8 i;
#ifdef CONFIG_LIBIPW_DEBUG
char rates_str[64];
@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element
memset(network->ssid + network->ssid_len, 0,
IW_ESSID_MAX_SIZE - network->ssid_len);
- LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->ssid_len);
+ LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n",
+ network->ssid_len, network->ssid,
+ network->ssid_len);
break;
case WLAN_EID_SUPP_RATES:
@@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
struct libipw_network *network,
struct libipw_rx_stats *stats)
{
- DECLARE_SSID_BUF(ssid);
-
network->qos_data.active = 0;
network->qos_data.supported = 0;
network->qos_data.param_count = 0;
@@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
}
if (network->mode == 0) {
- LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' "
- "network.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid);
+ LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n",
+ network->ssid_len, network->ssid,
+ network->bssid);
return 1;
}
@@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device
struct libipw_info_element *info_element = beacon->info_element;
#endif
unsigned long flags;
- DECLARE_SSID_BUF(ssid);
- LIBIPW_DEBUG_SCAN("'%s' (%pM"
- "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
- print_ssid(ssid, info_element->data, info_element->len),
+ LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ info_element->len, info_element->data,
beacon->header.addr3,
(beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
(beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
@@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device
(beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
if (libipw_network_init(ieee, beacon, &network, stats)) {
- LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
- print_ssid(ssid, info_element->data,
- info_element->len),
- beacon->header.addr3,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n",
+ info_element->len, info_element->data,
+ beacon->header.addr3,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
return;
}
@@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from "
- "network list.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
- target->bssid);
+ LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
+ target->ssid_len, target->ssid,
+ target->bssid);
libipw_network_reset(target);
} else {
/* Otherwise just pull from the free list */
@@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device
}
#ifdef CONFIG_LIBIPW_DEBUG
- LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
- print_ssid(ssid, network.ssid,
- network.ssid_len),
- network.bssid,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n",
+ network.ssid_len, network.ssid,
+ network.bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
#endif
memcpy(target, &network, sizeof(*target));
network.ibss_dfs = NULL;
list_add_tail(&target->list, &ieee->network_list);
} else {
- LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
- target->bssid,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
+ target->ssid_len, target->ssid,
+ target->bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
update_network(target, &network);
network.ibss_dfs = NULL;
}
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index 54aba4744438..dd29f46d086b 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
char *ev = extra;
char *stop = ev + wrqu->data.length;
int i = 0;
- DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("Getting scan\n");
@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
ev = libipw_translate_scan(ieee, ev, stop, network,
info);
else {
- LIBIPW_DEBUG_SCAN("Not showing network '%s ("
- "%pM)' due to age (%ums).\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid,
- elapsed_jiffies_msecs(
+ LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
+ network->ssid_len, network->ssid,
+ network->bssid,
+ elapsed_jiffies_msecs(
network->last_scanned));
}
}
@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
int i, key, key_provided, len;
struct lib80211_crypt_data **crypt;
int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
- DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("SET_ENCODE\n");
@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
if (len > erq->length)
memset(sec.keys[key] + erq->length, 0,
len - erq->length);
- LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
- key, print_ssid(ssid, sec.keys[key], len),
+ LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
+ key, len, sec.keys[key],
erq->length, len);
sec.key_sizes[key] = len;
if (*crypt)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 818b1edaaa9a..34f09ef90bb3 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
int chan_no = -1;
const u8 *ssid = NULL;
u8 ssid_len = 0;
- DECLARE_SSID_BUF(ssid_buf);
int len = get_unaligned_le16(pos);
pos += 2;
@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
struct ieee80211_channel *channel =
ieee80211_get_channel(wiphy, freq);
- lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
- "%d dBm\n",
- bssid, capa, chan_no,
- print_ssid(ssid_buf, ssid, ssid_len),
+ lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n",
+ bssid, capa, chan_no, ssid_len, ssid,
LBS_SCAN_RSSI_TO_MBM(rssi)/100);
if (channel &&
@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0;
struct cfg80211_bss *bss;
- DECLARE_SSID_BUF(ssid_buf);
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 01a67f62696f..d0c881dd5846 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
{
struct cmd_ds_mesh_config cmd;
struct mrvl_meshie *ie;
- DECLARE_SSID_BUF(ssid);
memset(&cmd, 0, sizeof(cmd));
cmd.channel = cpu_to_le16(chan);
@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
default:
return -1;
}
- lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
- action, priv->mesh_tlv, chan,
- print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+ lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
+ action, priv->mesh_tlv, chan, priv->mesh_ssid_len,
+ priv->mesh_ssid);
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index f959978c7aac..cf0f89364d44 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data(
}
s = dmi_get_system_info(DMI_PRODUCT_VERSION);
- if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) {
+ if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
tp->model_str = kstrdup(s, GFP_KERNEL);
if (!tp->model_str)
return -ENOMEM;
} else {
s = dmi_get_system_info(DMI_BIOS_VENDOR);
- if (s && !(strnicmp(s, "Lenovo", 6))) {
+ if (s && !(strncasecmp(s, "Lenovo", 6))) {
tp->model_str = kstrdup(s, GFP_KERNEL);
if (!tp->model_str)
return -ENOMEM;
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index e6c403be09a9..4b6808ff0e5d 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev,
}
buf = skip_spaces(buf);
- if (!strnicmp(buf, "disable", 7)) {
+ if (!strncasecmp(buf, "disable", 7)) {
retval = pnp_disable_dev(dev);
goto done;
}
- if (!strnicmp(buf, "activate", 8)) {
+ if (!strncasecmp(buf, "activate", 8)) {
retval = pnp_activate_dev(dev);
goto done;
}
- if (!strnicmp(buf, "fill", 4)) {
+ if (!strncasecmp(buf, "fill", 4)) {
if (dev->active)
goto done;
retval = pnp_auto_config_dev(dev);
goto done;
}
- if (!strnicmp(buf, "auto", 4)) {
+ if (!strncasecmp(buf, "auto", 4)) {
if (dev->active)
goto done;
pnp_init_resources(dev);
retval = pnp_auto_config_dev(dev);
goto done;
}
- if (!strnicmp(buf, "clear", 5)) {
+ if (!strncasecmp(buf, "clear", 5)) {
if (dev->active)
goto done;
pnp_init_resources(dev);
goto done;
}
- if (!strnicmp(buf, "get", 3)) {
+ if (!strncasecmp(buf, "get", 3)) {
mutex_lock(&pnp_res_mutex);
if (pnp_can_read(dev))
dev->protocol->get(dev);
mutex_unlock(&pnp_res_mutex);
goto done;
}
- if (!strnicmp(buf, "set", 3)) {
+ if (!strncasecmp(buf, "set", 3)) {
resource_size_t start;
resource_size_t end;
unsigned long flags;
@@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev,
mutex_lock(&pnp_res_mutex);
while (1) {
buf = skip_spaces(buf);
- if (!strnicmp(buf, "io", 2)) {
+ if (!strncasecmp(buf, "io", 2)) {
buf = pnp_get_resource_value(buf + 2,
IORESOURCE_IO,
&start, &end,
&flags);
pnp_add_io_resource(dev, start, end, flags);
- } else if (!strnicmp(buf, "mem", 3)) {
+ } else if (!strncasecmp(buf, "mem", 3)) {
buf = pnp_get_resource_value(buf + 3,
IORESOURCE_MEM,
&start, &end,
&flags);
pnp_add_mem_resource(dev, start, end, flags);
- } else if (!strnicmp(buf, "irq", 3)) {
+ } else if (!strncasecmp(buf, "irq", 3)) {
buf = pnp_get_resource_value(buf + 3,
IORESOURCE_IRQ,
&start, NULL,
&flags);
pnp_add_irq_resource(dev, start, flags);
- } else if (!strnicmp(buf, "dma", 3)) {
+ } else if (!strncasecmp(buf, "dma", 3)) {
buf = pnp_get_resource_value(buf + 3,
IORESOURCE_DMA,
&start, NULL,
&flags);
pnp_add_dma_resource(dev, start, flags);
- } else if (!strnicmp(buf, "bus", 3)) {
+ } else if (!strncasecmp(buf, "bus", 3)) {
buf = pnp_get_resource_value(buf + 3,
IORESOURCE_BUS,
&start, &end,
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 1bea0fc43464..8cd0beebdc3f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -288,6 +288,26 @@ config RTC_DRV_MAX77686
This driver can also be built as a module. If so, the module
will be called rtc-max77686.
+config RTC_DRV_RK808
+ tristate "Rockchip RK808 RTC"
+ depends on MFD_RK808
+ help
+ If you say yes here you will get support for the
+ RTC of RK808 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called rk808-rtc.
+
+config RTC_DRV_MAX77802
+ tristate "Maxim 77802 RTC"
+ depends on MFD_MAX77686
+ help
+ If you say yes here you will get support for the
+ RTC of Maxim MAX77802 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-max77802.
+
config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help
@@ -732,6 +752,7 @@ config RTC_DRV_DS1216
config RTC_DRV_DS1286
tristate "Dallas DS1286"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the Dallas DS1286 RTC chips.
@@ -743,6 +764,7 @@ config RTC_DRV_DS1302
config RTC_DRV_DS1511
tristate "Dallas DS1511"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the
Dallas DS1511 timekeeping/watchdog chip.
@@ -752,6 +774,7 @@ config RTC_DRV_DS1511
config RTC_DRV_DS1553
tristate "Maxim/Dallas DS1553"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the
Maxim/Dallas DS1553 timekeeping chip.
@@ -761,6 +784,7 @@ config RTC_DRV_DS1553
config RTC_DRV_DS1742
tristate "Maxim/Dallas DS1742/1743"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the
Maxim/Dallas DS1742/1743 timekeeping chip.
@@ -816,6 +840,7 @@ config RTC_DRV_EFI
config RTC_DRV_STK17TA8
tristate "Simtek STK17TA8"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the
Simtek STK17TA8 timekeeping chip.
@@ -834,6 +859,7 @@ config RTC_DRV_M48T86
config RTC_DRV_M48T35
tristate "ST M48T35"
+ depends on HAS_IOMEM
help
If you say Y here you will get support for the
ST M48T35 RTC chip.
@@ -843,6 +869,7 @@ config RTC_DRV_M48T35
config RTC_DRV_M48T59
tristate "ST M48T59/M48T08/M48T02"
+ depends on HAS_IOMEM
help
If you say Y here you will get support for the
ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
@@ -855,6 +882,7 @@ config RTC_DRV_M48T59
config RTC_DRV_MSM6242
tristate "Oki MSM6242"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the Oki MSM6242
timekeeping chip. It is used in some Amiga models (e.g. A2000).
@@ -864,6 +892,7 @@ config RTC_DRV_MSM6242
config RTC_DRV_BQ4802
tristate "TI BQ4802"
+ depends on HAS_IOMEM
help
If you say Y here you will get support for the TI
BQ4802 RTC chip.
@@ -873,6 +902,7 @@ config RTC_DRV_BQ4802
config RTC_DRV_RP5C01
tristate "Ricoh RP5C01"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the Ricoh RP5C01
timekeeping chip. It is used in some Amiga models (e.g. A3000
@@ -1374,6 +1404,7 @@ config RTC_DRV_MOXART
config RTC_DRV_XGENE
tristate "APM X-Gene RTC"
+ depends on HAS_IOMEM
help
If you say yes here you get support for the APM X-Gene SoC real time
clock.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 9055b7dd3dc5..b188323c096a 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
+obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o
obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
@@ -109,6 +110,7 @@ obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o
+obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o
obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index c74bf0dc52cc..314129e66d6e 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -2,10 +2,14 @@
* Driver for TI BQ32000 RTC.
*
* Copyright (C) 2009 Semihalf.
+ * Copyright (C) 2014 Pavel Machek <pavel@denx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
+ *
+ * You can get hardware description at
+ * http://www.ti.com/lit/ds/symlink/bq32000.pdf
*/
#include <linux/module.h>
@@ -27,6 +31,10 @@
#define BQ32K_CENT 0x40 /* Century flag */
#define BQ32K_CENT_EN 0x80 /* Century flag enable bit */
+#define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */
+#define BQ32K_TCH2 0x08 /* Trickle charge enable */
+#define BQ32K_CFG2 0x09 /* Trickle charger control */
+
struct bq32k_regs {
uint8_t seconds;
uint8_t minutes;
@@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = {
.set_time = bq32k_rtc_set_time,
};
+static int trickle_charger_of_init(struct device *dev, struct device_node *node)
+{
+ unsigned char reg;
+ int error;
+ u32 ohms = 0;
+
+ if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
+ return 0;
+
+ switch (ohms) {
+ case 180+940:
+ /*
+ * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
+ * over diode and 940ohm resistor)
+ */
+
+ if (of_property_read_bool(node, "trickle-diode-disable")) {
+ dev_err(dev, "diode and resistor mismatch\n");
+ return -EINVAL;
+ }
+ reg = 0x05;
+ break;
+
+ case 180+20000:
+ /* diode disabled */
+
+ if (!of_property_read_bool(node, "trickle-diode-disable")) {
+ dev_err(dev, "bq32k: diode and resistor mismatch\n");
+ return -EINVAL;
+ }
+ reg = 0x25;
+ break;
+
+ default:
+ dev_err(dev, "invalid resistor value (%d)\n", ohms);
+ return -EINVAL;
+ }
+
+ error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
+ if (error)
+ return error;
+
+ reg = 0x20;
+ error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
+ if (error)
+ return error;
+
+ dev_info(dev, "Enabled trickle RTC battery charge.\n");
+ return 0;
+}
+
static int bq32k_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client,
if (error)
return error;
+ if (client && client->dev.of_node)
+ trickle_charger_of_init(dev, client->dev.of_node);
+
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
&bq32k_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index b0e4a3eb33c7..5b2e76159b41 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev)
cmos->dev = NULL;
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int cmos_suspend(struct device *dev)
{
@@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev)
return cmos_suspend(dev);
}
+#ifdef CONFIG_PM_SLEEP
+
static int cmos_resume(struct device *dev)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev)
return 0;
}
+#endif
#else
static inline int cmos_poweroff(struct device *dev)
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index f03d5ba96db1..bb43cf703efc 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -126,9 +126,14 @@ struct chip_desc {
u16 nvram_offset;
u16 nvram_size;
u16 trickle_charger_reg;
+ u8 trickle_charger_setup;
+ u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
};
-static const struct chip_desc chips[last_ds_type] = {
+static u8 do_trickle_setup_ds1339(struct i2c_client *,
+ uint32_t ohms, bool diode);
+
+static struct chip_desc chips[last_ds_type] = {
[ds_1307] = {
.nvram_offset = 8,
.nvram_size = 56,
@@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = {
[ds_1339] = {
.alarm = 1,
.trickle_charger_reg = 0x10,
+ .do_trickle_setup = &do_trickle_setup_ds1339,
},
[ds_1340] = {
.trickle_charger_reg = 0x08,
@@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
return count;
}
+
/*----------------------------------------------------------------------*/
+static u8 do_trickle_setup_ds1339(struct i2c_client *client,
+ uint32_t ohms, bool diode)
+{
+ u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
+ DS1307_TRICKLE_CHARGER_NO_DIODE;
+
+ switch (ohms) {
+ case 250:
+ setup |= DS1307_TRICKLE_CHARGER_250_OHM;
+ break;
+ case 2000:
+ setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
+ break;
+ case 4000:
+ setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
+ break;
+ default:
+ dev_warn(&client->dev,
+ "Unsupported ohm value %u in dt\n", ohms);
+ return 0;
+ }
+ return setup;
+}
+
+static void ds1307_trickle_of_init(struct i2c_client *client,
+ struct chip_desc *chip)
+{
+ uint32_t ohms = 0;
+ bool diode = true;
+
+ if (!chip->do_trickle_setup)
+ goto out;
+ if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms))
+ goto out;
+ if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
+ diode = false;
+ chip->trickle_charger_setup = chip->do_trickle_setup(client,
+ ohms, diode);
+out:
+ return;
+}
+
static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ds1307 *ds1307;
int err = -ENODEV;
int tmp;
- const struct chip_desc *chip = &chips[id->driver_data];
+ struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
unsigned char *buf;
@@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->client = client;
ds1307->type = id->driver_data;
- if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
+ if (!pdata && client->dev.of_node)
+ ds1307_trickle_of_init(client, chip);
+ else if (pdata && pdata->trickle_charger_setup)
+ chip->trickle_charger_setup = pdata->trickle_charger_setup;
+
+ if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
+ dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
+ DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
+ chip->trickle_charger_reg);
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
- DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
+ DS13XX_TRICKLE_CHARGER_MAGIC |
+ chip->trickle_charger_setup);
+ }
buf = ds1307->regs;
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index aa55f081c505..ee3ba7e6b45e 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client,
}
#ifdef CONFIG_OF
-static struct of_device_id isl12022_dt_match[] = {
+static const struct of_device_id isl12022_dt_match[] = {
{ .compatible = "isl,isl12022" },
{ },
};
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index d20a7f0786eb..cf73e969c8cc 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -32,15 +32,6 @@
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
#define RTC_RBUDR_SHIFT 4
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
-/* WTSR and SMPL Register */
-#define WTSRT_SHIFT 0
-#define SMPLT_SHIFT 2
-#define WTSR_EN_SHIFT 6
-#define SMPL_EN_SHIFT 7
-#define WTSRT_MASK (3 << WTSRT_SHIFT)
-#define SMPLT_MASK (3 << SMPLT_SHIFT)
-#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT)
-#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT)
/* RTC Hour register */
#define HOUR_PM_SHIFT 6
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
@@ -49,7 +40,6 @@
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
#define MAX77686_RTC_UPDATE_DELAY 16
-#undef MAX77686_RTC_WTSR_SMPL
enum {
RTC_SEC = 0,
@@ -80,16 +70,6 @@ enum MAX77686_RTC_OP {
MAX77686_RTC_READ,
};
-static inline int max77686_rtc_calculate_wday(u8 shifted)
-{
- int counter = -1;
- while (shifted) {
- shifted >>= 1;
- counter++;
- }
- return counter;
-}
-
static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
@@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
tm->tm_hour += 12;
}
- tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f);
+ /* Only a single bit is set in data[], so fls() would be equivalent */
+ tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
tm->tm_mday = data[RTC_DATE] & 0x1f;
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
@@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = {
.alarm_irq_enable = max77686_rtc_alarm_irq_enable,
};
-#ifdef MAX77686_RTC_WTSR_SMPL
-static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable)
-{
- int ret;
- unsigned int val, mask;
-
- if (enable)
- val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT);
- else
- val = 0;
-
- mask = WTSR_EN_MASK | WTSRT_MASK;
-
- dev_info(info->dev, "%s: %s WTSR\n", __func__,
- enable ? "enable" : "disable");
-
- ret = regmap_update_bits(info->max77686->rtc_regmap,
- MAX77686_WTSR_SMPL_CNTL, mask, val);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
- __func__, ret);
- return;
- }
-
- max77686_rtc_update(info, MAX77686_RTC_WRITE);
-}
-
-static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable)
-{
- int ret;
- unsigned int val, mask;
-
- if (enable)
- val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT);
- else
- val = 0;
-
- mask = SMPL_EN_MASK | SMPLT_MASK;
-
- dev_info(info->dev, "%s: %s SMPL\n", __func__,
- enable ? "enable" : "disable");
-
- ret = regmap_update_bits(info->max77686->rtc_regmap,
- MAX77686_WTSR_SMPL_CNTL, mask, val);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
- __func__, ret);
- return;
- }
-
- max77686_rtc_update(info, MAX77686_RTC_WRITE);
-
- val = 0;
- regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
- dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val);
-}
-#endif /* MAX77686_RTC_WTSR_SMPL */
-
static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
{
u8 data[2];
@@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
goto err_rtc;
}
-#ifdef MAX77686_RTC_WTSR_SMPL
- max77686_rtc_enable_wtsr(info, true);
- max77686_rtc_enable_smpl(info, true);
-#endif
-
device_init_wakeup(&pdev->dev, 1);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
&max77686_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc_dev)) {
- dev_info(&pdev->dev, "%s: fail\n", __func__);
-
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
if (ret == 0)
@@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
goto err_rtc;
}
+ if (!max77686->rtc_irq_data) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
+ goto err_rtc;
+ }
+
info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
MAX77686_RTCIRQ_RTCA1);
if (!info->virq) {
@@ -556,33 +478,33 @@ err_rtc:
return ret;
}
-static void max77686_rtc_shutdown(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static int max77686_rtc_suspend(struct device *dev)
{
-#ifdef MAX77686_RTC_WTSR_SMPL
- struct max77686_rtc_info *info = platform_get_drvdata(pdev);
- int i;
- u8 val = 0;
-
- for (i = 0; i < 3; i++) {
- max77686_rtc_enable_wtsr(info, false);
- regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
- dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__,
- val);
- if (val & WTSR_EN_MASK) {
- dev_emerg(info->dev, "%s: fail to disable WTSR\n",
- __func__);
- } else {
- dev_info(info->dev, "%s: success to disable WTSR\n",
- __func__);
- break;
- }
+ if (device_may_wakeup(dev)) {
+ struct max77686_rtc_info *info = dev_get_drvdata(dev);
+
+ return enable_irq_wake(info->virq);
}
- /* Disable SMPL when power off */
- max77686_rtc_enable_smpl(info, false);
-#endif /* MAX77686_RTC_WTSR_SMPL */
+ return 0;
}
+static int max77686_rtc_resume(struct device *dev)
+{
+ if (device_may_wakeup(dev)) {
+ struct max77686_rtc_info *info = dev_get_drvdata(dev);
+
+ return disable_irq_wake(info->virq);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
+ max77686_rtc_suspend, max77686_rtc_resume);
+
static const struct platform_device_id rtc_id[] = {
{ "max77686-rtc", 0 },
{},
@@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = {
.driver = {
.name = "max77686-rtc",
.owner = THIS_MODULE,
+ .pm = &max77686_rtc_pm_ops,
},
.probe = max77686_rtc_probe,
- .shutdown = max77686_rtc_shutdown,
.id_table = rtc_id,
};
diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c
new file mode 100644
index 000000000000..566471335b33
--- /dev/null
+++ b/drivers/rtc/rtc-max77802.c
@@ -0,0 +1,502 @@
+/*
+ * RTC driver for Maxim MAX77802
+ *
+ * Copyright (C) 2013 Google, Inc
+ *
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ *
+ * based on rtc-max8997.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max77686-private.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+/* RTC Control Register */
+#define BCD_EN_SHIFT 0
+#define BCD_EN_MASK (1 << BCD_EN_SHIFT)
+#define MODEL24_SHIFT 1
+#define MODEL24_MASK (1 << MODEL24_SHIFT)
+/* RTC Update Register1 */
+#define RTC_UDR_SHIFT 0
+#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
+#define RTC_RBUDR_SHIFT 4
+#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
+/* RTC Hour register */
+#define HOUR_PM_SHIFT 6
+#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
+/* RTC Alarm Enable */
+#define ALARM_ENABLE_SHIFT 7
+#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
+
+/* For the RTCAE1 register, we write this value to enable the alarm */
+#define ALARM_ENABLE_VALUE 0x77
+
+#define MAX77802_RTC_UPDATE_DELAY_US 200
+
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WEEKDAY,
+ RTC_MONTH,
+ RTC_YEAR,
+ RTC_DATE,
+ RTC_NR_TIME
+};
+
+struct max77802_rtc_info {
+ struct device *dev;
+ struct max77686_dev *max77802;
+ struct i2c_client *rtc;
+ struct rtc_device *rtc_dev;
+ struct mutex lock;
+
+ struct regmap *regmap;
+
+ int virq;
+ int rtc_24hr_mode;
+};
+
+enum MAX77802_RTC_OP {
+ MAX77802_RTC_WRITE,
+ MAX77802_RTC_READ,
+};
+
+static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
+ int rtc_24hr_mode)
+{
+ tm->tm_sec = data[RTC_SEC] & 0xff;
+ tm->tm_min = data[RTC_MIN] & 0xff;
+ if (rtc_24hr_mode)
+ tm->tm_hour = data[RTC_HOUR] & 0x1f;
+ else {
+ tm->tm_hour = data[RTC_HOUR] & 0x0f;
+ if (data[RTC_HOUR] & HOUR_PM_MASK)
+ tm->tm_hour += 12;
+ }
+
+ /* Only a single bit is set in data[], so fls() would be equivalent */
+ tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
+ tm->tm_mday = data[RTC_DATE] & 0x1f;
+ tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
+
+ tm->tm_year = data[RTC_YEAR] & 0xff;
+ tm->tm_yday = 0;
+ tm->tm_isdst = 0;
+}
+
+static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+ data[RTC_SEC] = tm->tm_sec;
+ data[RTC_MIN] = tm->tm_min;
+ data[RTC_HOUR] = tm->tm_hour;
+ data[RTC_WEEKDAY] = 1 << tm->tm_wday;
+ data[RTC_DATE] = tm->tm_mday;
+ data[RTC_MONTH] = tm->tm_mon + 1;
+ data[RTC_YEAR] = tm->tm_year;
+
+ return 0;
+}
+
+static int max77802_rtc_update(struct max77802_rtc_info *info,
+ enum MAX77802_RTC_OP op)
+{
+ int ret;
+ unsigned int data;
+
+ if (op == MAX77802_RTC_WRITE)
+ data = 1 << RTC_UDR_SHIFT;
+ else
+ data = 1 << RTC_RBUDR_SHIFT;
+
+ ret = regmap_update_bits(info->max77802->regmap,
+ MAX77802_RTC_UPDATE0, data, data);
+ if (ret < 0)
+ dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
+ __func__, ret, data);
+ else {
+ /* Minimum delay required before RTC update. */
+ usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
+ MAX77802_RTC_UPDATE_DELAY_US * 2);
+ }
+
+ return ret;
+}
+
+static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ int ret;
+
+ mutex_lock(&info->lock);
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_bulk_read(info->max77802->regmap,
+ MAX77802_RTC_SEC, data, RTC_NR_TIME);
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
+ ret);
+ goto out;
+ }
+
+ max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
+
+ ret = rtc_valid_tm(tm);
+
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ int ret;
+
+ ret = max77802_rtc_tm_to_data(tm, data);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&info->lock);
+
+ ret = regmap_bulk_write(info->max77802->regmap,
+ MAX77802_RTC_SEC, data, RTC_NR_TIME);
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
+ ret);
+ goto out;
+ }
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ unsigned int val;
+ int ret;
+
+ mutex_lock(&info->lock);
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_bulk_read(info->max77802->regmap,
+ MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
+ if (ret < 0) {
+ dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
+ __func__, __LINE__, ret);
+ goto out;
+ }
+
+ max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+
+ alrm->enabled = 0;
+ ret = regmap_read(info->max77802->regmap,
+ MAX77802_RTC_AE1, &val);
+ if (ret < 0) {
+ dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
+ __func__, __LINE__, ret);
+ goto out;
+ }
+ if (val)
+ alrm->enabled = 1;
+
+ alrm->pending = 0;
+ ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
+ if (ret < 0) {
+ dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
+ __func__, __LINE__, ret);
+ goto out;
+ }
+
+ if (val & (1 << 2)) /* RTCA1 */
+ alrm->pending = 1;
+
+out:
+ mutex_unlock(&info->lock);
+ return 0;
+}
+
+static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
+{
+ int ret;
+
+ if (!mutex_is_locked(&info->lock))
+ dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_write(info->max77802->regmap,
+ MAX77802_RTC_AE1, 0);
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
+ __func__, ret);
+ goto out;
+ }
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+out:
+ return ret;
+}
+
+static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
+{
+ int ret;
+
+ if (!mutex_is_locked(&info->lock))
+ dev_warn(info->dev, "%s: should have mutex locked\n",
+ __func__);
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_write(info->max77802->regmap,
+ MAX77802_RTC_AE1,
+ ALARM_ENABLE_VALUE);
+
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
+ __func__, ret);
+ goto out;
+ }
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+out:
+ return ret;
+}
+
+static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ int ret;
+
+ ret = max77802_rtc_tm_to_data(&alrm->time, data);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&info->lock);
+
+ ret = max77802_rtc_stop_alarm(info);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_bulk_write(info->max77802->regmap,
+ MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
+
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
+ __func__, ret);
+ goto out;
+ }
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+ if (ret < 0)
+ goto out;
+
+ if (alrm->enabled)
+ ret = max77802_rtc_start_alarm(info);
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int max77802_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&info->lock);
+ if (enabled)
+ ret = max77802_rtc_start_alarm(info);
+ else
+ ret = max77802_rtc_stop_alarm(info);
+ mutex_unlock(&info->lock);
+
+ return ret;
+}
+
+static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
+{
+ struct max77802_rtc_info *info = data;
+
+ dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
+
+ rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops max77802_rtc_ops = {
+ .read_time = max77802_rtc_read_time,
+ .set_time = max77802_rtc_set_time,
+ .read_alarm = max77802_rtc_read_alarm,
+ .set_alarm = max77802_rtc_set_alarm,
+ .alarm_irq_enable = max77802_rtc_alarm_irq_enable,
+};
+
+static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
+{
+ u8 data[2];
+ int ret;
+
+ max77802_rtc_update(info, MAX77802_RTC_READ);
+
+ /* Set RTC control register : Binary mode, 24hour mdoe */
+ data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+ data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+
+ info->rtc_24hr_mode = 1;
+
+ ret = regmap_bulk_write(info->max77802->regmap,
+ MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
+ if (ret < 0) {
+ dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+ return ret;
+}
+
+static int max77802_rtc_probe(struct platform_device *pdev)
+{
+ struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
+ struct max77802_rtc_info *info;
+ int ret;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ mutex_init(&info->lock);
+ info->dev = &pdev->dev;
+ info->max77802 = max77802;
+ info->rtc = max77802->i2c;
+
+ platform_set_drvdata(pdev, info);
+
+ ret = max77802_rtc_init_reg(info);
+
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
+ return ret;
+ }
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
+ &max77802_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(info->rtc_dev)) {
+ ret = PTR_ERR(info->rtc_dev);
+ dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+ if (ret == 0)
+ ret = -EINVAL;
+ return ret;
+ }
+
+ if (!max77802->rtc_irq_data) {
+ dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
+ return -EINVAL;
+ }
+
+ info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
+ MAX77686_RTCIRQ_RTCA1);
+
+ if (info->virq <= 0) {
+ dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
+ MAX77686_RTCIRQ_RTCA1);
+ return -EINVAL;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
+ max77802_rtc_alarm_irq, 0, "rtc-alarm1",
+ info);
+ if (ret < 0)
+ dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+ info->virq, ret);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77802_rtc_suspend(struct device *dev)
+{
+ if (device_may_wakeup(dev)) {
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+
+ return enable_irq_wake(info->virq);
+ }
+
+ return 0;
+}
+
+static int max77802_rtc_resume(struct device *dev)
+{
+ if (device_may_wakeup(dev)) {
+ struct max77802_rtc_info *info = dev_get_drvdata(dev);
+
+ return disable_irq_wake(info->virq);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
+ max77802_rtc_suspend, max77802_rtc_resume);
+
+static const struct platform_device_id rtc_id[] = {
+ { "max77802-rtc", 0 },
+ {},
+};
+
+static struct platform_driver max77802_rtc_driver = {
+ .driver = {
+ .name = "max77802-rtc",
+ .owner = THIS_MODULE,
+ .pm = &max77802_rtc_pm_ops,
+ },
+ .probe = max77802_rtc_probe,
+ .id_table = rtc_id,
+};
+
+module_platform_driver(max77802_rtc_driver);
+
+MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
+MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index dc4f14255cc3..3b965ad6f4d5 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op)
}
#ifdef CONFIG_OF
-static struct of_device_id mpc5121_rtc_match[] = {
+static const struct of_device_id mpc5121_rtc_match[] = {
{ .compatible = "fsl,mpc5121-rtc", },
{ .compatible = "fsl,mpc5200-rtc", },
{},
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 5a197d9dc7e7..c2ef0a22ee94 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -167,8 +167,8 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
char pending;
err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
- if (err < 0)
- return err;
+ if (err)
+ return IRQ_NONE;
if (pending) {
rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index c2639845186b..5911a6dca291 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char ctrl, year[2];
- struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+ struct rtc_mem mem = {
+ .loc = CMOS_YEAR,
+ .nr = sizeof(year),
+ .data = year
+ };
int real_year, year_offset, err;
/*
@@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char year[2], chk;
- struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year };
- struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+ struct rtc_mem cmos_year = {
+ .loc = CMOS_YEAR,
+ .nr = sizeof(year),
+ .data = year
+ };
+ struct rtc_mem cmos_check = {
+ .loc = CMOS_CHECKSUM,
+ .nr = 1,
+ .data = &chk
+ };
unsigned int proper_year = tm->tm_year + 1900;
int ret;
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c
new file mode 100644
index 000000000000..df42257668ac
--- /dev/null
+++ b/drivers/rtc/rtc-rk808.c
@@ -0,0 +1,414 @@
+/*
+ * RTC driver for Rockchip RK808
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ * Author: Zhang Qing <zhangqing@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/mfd/rk808.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+/* RTC_CTRL_REG bitfields */
+#define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0)
+
+/* RK808 has a shadowed register for saving a "frozen" RTC time.
+ * When user setting "GET_TIME" to 1, the time will save in this shadowed
+ * register. If set "READSEL" to 1, user read rtc time register, actually
+ * get the time of that moment. If we need the real time, clr this bit.
+ */
+#define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6)
+#define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7)
+#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M BIT(3)
+#define RTC_STATUS_MASK 0xFE
+
+#define SECONDS_REG_MSK 0x7F
+#define MINUTES_REG_MAK 0x7F
+#define HOURS_REG_MSK 0x3F
+#define DAYS_REG_MSK 0x3F
+#define MONTHS_REG_MSK 0x1F
+#define YEARS_REG_MSK 0xFF
+#define WEEKS_REG_MSK 0x7
+
+/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
+
+#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
+#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
+
+struct rk808_rtc {
+ struct rk808 *rk808;
+ struct rtc_device *rtc;
+ int irq;
+};
+
+/* Read current time and date in RTC */
+static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ u8 rtc_data[NUM_TIME_REGS];
+ int ret;
+
+ /* Force an update of the shadowed registers right now */
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+ BIT_RTC_CTRL_REG_RTC_GET_TIME,
+ 0);
+ if (ret) {
+ dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+ BIT_RTC_CTRL_REG_RTC_GET_TIME,
+ BIT_RTC_CTRL_REG_RTC_GET_TIME);
+ if (ret) {
+ dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
+ rtc_data, NUM_TIME_REGS);
+ if (ret) {
+ dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
+ return ret;
+ }
+
+ tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK);
+ tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK);
+ tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK);
+ tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK);
+ tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
+ tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
+ tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
+ dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+ 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+
+ return ret;
+}
+
+/* Set current time and date in RTC */
+static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ u8 rtc_data[NUM_TIME_REGS];
+ int ret;
+
+ rtc_data[0] = bin2bcd(tm->tm_sec);
+ rtc_data[1] = bin2bcd(tm->tm_min);
+ rtc_data[2] = bin2bcd(tm->tm_hour);
+ rtc_data[3] = bin2bcd(tm->tm_mday);
+ rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+ rtc_data[5] = bin2bcd(tm->tm_year - 100);
+ rtc_data[6] = bin2bcd(tm->tm_wday);
+ dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+ 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+
+ /* Stop RTC while updating the RTC registers */
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+ BIT_RTC_CTRL_REG_STOP_RTC_M,
+ BIT_RTC_CTRL_REG_STOP_RTC_M);
+ if (ret) {
+ dev_err(dev, "Failed to update RTC control: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
+ rtc_data, NUM_TIME_REGS);
+ if (ret) {
+ dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
+ return ret;
+ }
+ /* Start RTC again */
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+ BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
+ if (ret) {
+ dev_err(dev, "Failed to update RTC control: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+/* Read alarm time and date in RTC */
+static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ u8 alrm_data[NUM_ALARM_REGS];
+ uint32_t int_reg;
+ int ret;
+
+ ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
+ alrm_data, NUM_ALARM_REGS);
+
+ alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
+ alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
+ alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK);
+ alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
+ alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
+ alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
+
+ ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
+ if (ret) {
+ dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+ 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
+ alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
+ alrm->time.tm_min, alrm->time.tm_sec);
+
+ alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0;
+
+ return 0;
+}
+
+static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
+{
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ int ret;
+
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
+ BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
+
+ return ret;
+}
+
+static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
+{
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ int ret;
+
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
+ BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
+ BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+
+ return ret;
+}
+
+static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ u8 alrm_data[NUM_ALARM_REGS];
+ int ret;
+
+ ret = rk808_rtc_stop_alarm(rk808_rtc);
+ if (ret) {
+ dev_err(dev, "Failed to stop alarm: %d\n", ret);
+ return ret;
+ }
+ dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+ 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
+ alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
+ alrm->time.tm_min, alrm->time.tm_sec);
+
+ alrm_data[0] = bin2bcd(alrm->time.tm_sec);
+ alrm_data[1] = bin2bcd(alrm->time.tm_min);
+ alrm_data[2] = bin2bcd(alrm->time.tm_hour);
+ alrm_data[3] = bin2bcd(alrm->time.tm_mday);
+ alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
+ alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
+
+ ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
+ alrm_data, NUM_ALARM_REGS);
+ if (ret) {
+ dev_err(dev, "Failed to bulk write: %d\n", ret);
+ return ret;
+ }
+ if (alrm->enabled) {
+ ret = rk808_rtc_start_alarm(rk808_rtc);
+ if (ret) {
+ dev_err(dev, "Failed to start alarm: %d\n", ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int rk808_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+
+ if (enabled)
+ return rk808_rtc_start_alarm(rk808_rtc);
+
+ return rk808_rtc_stop_alarm(rk808_rtc);
+}
+
+/*
+ * We will just handle setting the frequency and make use the framework for
+ * reading the periodic interupts.
+ *
+ * @freq: Current periodic IRQ freq:
+ * bit 0: every second
+ * bit 1: every minute
+ * bit 2: every hour
+ * bit 3: every day
+ */
+static irqreturn_t rk808_alarm_irq(int irq, void *data)
+{
+ struct rk808_rtc *rk808_rtc = data;
+ struct rk808 *rk808 = rk808_rtc->rk808;
+ struct i2c_client *client = rk808->i2c;
+ int ret;
+
+ ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
+ RTC_STATUS_MASK);
+ if (ret) {
+ dev_err(&client->dev,
+ "%s:Failed to update RTC status: %d\n", __func__, ret);
+ return ret;
+ }
+
+ rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF);
+ dev_dbg(&client->dev,
+ "%s:irq=%d\n", __func__, irq);
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops rk808_rtc_ops = {
+ .read_time = rk808_rtc_readtime,
+ .set_time = rk808_rtc_set_time,
+ .read_alarm = rk808_rtc_readalarm,
+ .set_alarm = rk808_rtc_setalarm,
+ .alarm_irq_enable = rk808_rtc_alarm_irq_enable,
+};
+
+#ifdef CONFIG_PM_SLEEP
+/* Turn off the alarm if it should not be a wake source. */
+static int rk808_rtc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rk808_rtc->irq);
+
+ return 0;
+}
+
+/* Enable the alarm if it should be enabled (in case it was disabled to
+ * prevent use as a wake source).
+ */
+static int rk808_rtc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rk808_rtc->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
+ rk808_rtc_suspend, rk808_rtc_resume);
+
+static int rk808_rtc_probe(struct platform_device *pdev)
+{
+ struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+ struct rk808_rtc *rk808_rtc;
+ struct rtc_time tm;
+ int ret;
+
+ rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
+ if (rk808_rtc == NULL)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, rk808_rtc);
+ rk808_rtc->rk808 = rk808;
+
+ /* start rtc running by default, and use shadowed timer. */
+ ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+ BIT_RTC_CTRL_REG_STOP_RTC_M |
+ BIT_RTC_CTRL_REG_RTC_READSEL_M,
+ BIT_RTC_CTRL_REG_RTC_READSEL_M);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to update RTC control: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
+ RTC_STATUS_MASK);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to write RTC status: %d\n", ret);
+ return ret;
+ }
+
+ /* set init time */
+ ret = rk808_rtc_readtime(&pdev->dev, &tm);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to read RTC time\n");
+ return ret;
+ }
+ ret = rtc_valid_tm(&tm);
+ if (ret)
+ dev_warn(&pdev->dev, "invalid date/time\n");
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
+ &rk808_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rk808_rtc->rtc)) {
+ ret = PTR_ERR(rk808_rtc->rtc);
+ return ret;
+ }
+
+ rk808_rtc->irq = platform_get_irq(pdev, 0);
+ if (rk808_rtc->irq < 0) {
+ if (rk808_rtc->irq != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n",
+ rk808_rtc->irq);
+ return rk808_rtc->irq;
+ }
+
+ /* request alarm irq of rk808 */
+ ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL,
+ rk808_alarm_irq, 0,
+ "RTC alarm", rk808_rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
+ rk808_rtc->irq, ret);
+ }
+
+ return ret;
+}
+
+static struct platform_driver rk808_rtc_driver = {
+ .probe = rk808_rtc_probe,
+ .driver = {
+ .name = "rk808-rtc",
+ .pm = &rk808_rtc_pm_ops,
+ },
+};
+
+module_platform_driver(rk808_rtc_driver);
+
+MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk808-rtc");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index ccf54f06396b..28871cd7e3b5 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
}
dev_dbg(&client->dev,
- "%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
- "%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
- rs5c->regs[0], rs5c->regs[1], rs5c->regs[2], rs5c->regs[3],
- rs5c->regs[4], rs5c->regs[5], rs5c->regs[6], rs5c->regs[7],
- rs5c->regs[8], rs5c->regs[9], rs5c->regs[10], rs5c->regs[11],
- rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);
+ "%3ph (%02x) %3ph (%02x), %3ph, %3ph; %02x %02x\n",
+ rs5c->regs + 0, rs5c->regs[3],
+ rs5c->regs + 4, rs5c->regs[7],
+ rs5c->regs + 8, rs5c->regs + 11,
+ rs5c->regs[14], rs5c->regs[15]);
return 0;
}
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 4958a363b2c7..a6b1252c9941 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -32,155 +32,150 @@
#include <asm/irq.h>
#include "rtc-s3c.h"
-enum s3c_cpu_type {
- TYPE_S3C2410,
- TYPE_S3C2416,
- TYPE_S3C2443,
- TYPE_S3C64XX,
-};
+struct s3c_rtc {
+ struct device *dev;
+ struct rtc_device *rtc;
-struct s3c_rtc_drv_data {
- int cpu_type;
-};
+ void __iomem *base;
+ struct clk *rtc_clk;
+ struct clk *rtc_src_clk;
+ bool enabled;
+
+ struct s3c_rtc_data *data;
-/* I have yet to find an S3C implementation with more than one
- * of these rtc blocks in */
+ int irq_alarm;
+ int irq_tick;
-static struct clk *rtc_clk;
-static void __iomem *s3c_rtc_base;
-static int s3c_rtc_alarmno;
-static int s3c_rtc_tickno;
-static enum s3c_cpu_type s3c_rtc_cpu_type;
+ spinlock_t pie_lock;
+ spinlock_t alarm_clk_lock;
-static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
+ int ticnt_save, ticnt_en_save;
+ bool wake_en;
+};
+
+struct s3c_rtc_data {
+ int max_user_freq;
+ bool needs_src_clk;
+
+ void (*irq_handler) (struct s3c_rtc *info, int mask);
+ void (*set_freq) (struct s3c_rtc *info, int freq);
+ void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq);
+ void (*select_tick_clk) (struct s3c_rtc *info);
+ void (*save_tick_cnt) (struct s3c_rtc *info);
+ void (*restore_tick_cnt) (struct s3c_rtc *info);
+ void (*enable) (struct s3c_rtc *info);
+ void (*disable) (struct s3c_rtc *info);
+};
-static void s3c_rtc_alarm_clk_enable(bool enable)
+static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
{
- static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock);
- static bool alarm_clk_enabled;
unsigned long irq_flags;
- spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags);
+ spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
if (enable) {
- if (!alarm_clk_enabled) {
- clk_enable(rtc_clk);
- alarm_clk_enabled = true;
+ if (!info->enabled) {
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+ info->enabled = true;
}
} else {
- if (alarm_clk_enabled) {
- clk_disable(rtc_clk);
- alarm_clk_enabled = false;
+ if (info->enabled) {
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+ info->enabled = false;
}
}
- spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags);
+ spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
}
/* IRQ Handlers */
-
-static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
+static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
- struct rtc_device *rdev = id;
-
- clk_enable(rtc_clk);
- rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
-
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
-
- clk_disable(rtc_clk);
+ struct s3c_rtc *info = (struct s3c_rtc *)id;
- s3c_rtc_alarm_clk_enable(false);
+ if (info->data->irq_handler)
+ info->data->irq_handler(info, S3C2410_INTP_TIC);
return IRQ_HANDLED;
}
-static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
+static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
{
- struct rtc_device *rdev = id;
+ struct s3c_rtc *info = (struct s3c_rtc *)id;
- clk_enable(rtc_clk);
- rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+ if (info->data->irq_handler)
+ info->data->irq_handler(info, S3C2410_INTP_ALM);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
-
- clk_disable(rtc_clk);
return IRQ_HANDLED;
}
/* Update control registers */
static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
{
+ struct s3c_rtc *info = dev_get_drvdata(dev);
unsigned int tmp;
- dev_dbg(dev, "%s: aie=%d\n", __func__, enabled);
+ dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
- clk_enable(rtc_clk);
- tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+ tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
if (enabled)
tmp |= S3C2410_RTCALM_ALMEN;
- writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
- clk_disable(rtc_clk);
+ writeb(tmp, info->base + S3C2410_RTCALM);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
- s3c_rtc_alarm_clk_enable(enabled);
+ s3c_rtc_alarm_clk_enable(info, enabled);
return 0;
}
-static int s3c_rtc_setfreq(struct device *dev, int freq)
+/* Set RTC frequency */
+static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
- unsigned int tmp = 0;
- int val;
-
if (!is_power_of_2(freq))
return -EINVAL;
- clk_enable(rtc_clk);
- spin_lock_irq(&s3c_rtc_pie_lock);
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+ spin_lock_irq(&info->pie_lock);
- if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
- tmp = readb(s3c_rtc_base + S3C2410_TICNT);
- tmp &= S3C2410_TICNT_ENABLE;
- }
+ if (info->data->set_freq)
+ info->data->set_freq(info, freq);
- val = (rtc_dev->max_user_freq / freq) - 1;
-
- if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
- tmp |= S3C2443_TICNT_PART(val);
- writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1);
-
- if (s3c_rtc_cpu_type == TYPE_S3C2416)
- writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2);
- } else {
- tmp |= val;
- }
-
- writel(tmp, s3c_rtc_base + S3C2410_TICNT);
- spin_unlock_irq(&s3c_rtc_pie_lock);
- clk_disable(rtc_clk);
+ spin_unlock_irq(&info->pie_lock);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
return 0;
}
/* Time read/write */
-
static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
+ struct s3c_rtc *info = dev_get_drvdata(dev);
unsigned int have_retried = 0;
- void __iomem *base = s3c_rtc_base;
- clk_enable(rtc_clk);
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
retry_get_time:
- rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
- rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
- rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
- rtc_tm->tm_mon = readb(base + S3C2410_RTCMON);
- rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
- rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);
+ rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN);
+ rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
+ rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
+ rtc_tm->tm_mon = readb(info->base + S3C2410_RTCMON);
+ rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
+ rtc_tm->tm_sec = readb(info->base + S3C2410_RTCSEC);
/* the only way to work out whether the system was mid-update
* when we read it is to check the second counter, and if it
@@ -207,13 +202,16 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_mon -= 1;
- clk_disable(rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+
return rtc_valid_tm(rtc_tm);
}
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{
- void __iomem *base = s3c_rtc_base;
+ struct s3c_rtc *info = dev_get_drvdata(dev);
int year = tm->tm_year - 100;
dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
@@ -227,33 +225,42 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
- clk_enable(rtc_clk);
- writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC);
- writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN);
- writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
- writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
- writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
- writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
- clk_disable(rtc_clk);
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
+ writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC);
+ writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN);
+ writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
+ writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
+ writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
+ writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
return 0;
}
static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
+ struct s3c_rtc *info = dev_get_drvdata(dev);
struct rtc_time *alm_tm = &alrm->time;
- void __iomem *base = s3c_rtc_base;
unsigned int alm_en;
- clk_enable(rtc_clk);
- alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
- alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
- alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
- alm_tm->tm_mon = readb(base + S3C2410_ALMMON);
- alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
- alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
- alm_en = readb(base + S3C2410_RTCALM);
+ alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC);
+ alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN);
+ alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
+ alm_tm->tm_mon = readb(info->base + S3C2410_ALMMON);
+ alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE);
+ alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR);
+
+ alm_en = readb(info->base + S3C2410_RTCALM);
alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
@@ -297,65 +304,74 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
else
alm_tm->tm_year = -1;
- clk_disable(rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+
return 0;
}
static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
+ struct s3c_rtc *info = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
- void __iomem *base = s3c_rtc_base;
unsigned int alrm_en;
- clk_enable(rtc_clk);
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
- writeb(0x00, base + S3C2410_RTCALM);
+ alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
+ writeb(0x00, info->base + S3C2410_RTCALM);
if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
alrm_en |= S3C2410_RTCALM_SECEN;
- writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC);
+ writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC);
}
if (tm->tm_min < 60 && tm->tm_min >= 0) {
alrm_en |= S3C2410_RTCALM_MINEN;
- writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN);
+ writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN);
}
if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
alrm_en |= S3C2410_RTCALM_HOUREN;
- writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);
+ writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
}
dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
- writeb(alrm_en, base + S3C2410_RTCALM);
+ writeb(alrm_en, info->base + S3C2410_RTCALM);
s3c_rtc_setaie(dev, alrm->enabled);
- clk_disable(rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+
return 0;
}
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
- unsigned int ticnt;
+ struct s3c_rtc *info = dev_get_drvdata(dev);
- clk_enable(rtc_clk);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
- ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
- ticnt &= S3C64XX_RTCCON_TICEN;
- } else {
- ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
- ticnt &= S3C2410_TICNT_ENABLE;
- }
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
+ if (info->data->enable_tick)
+ info->data->enable_tick(info, seq);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
- seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
- clk_disable(rtc_clk);
return 0;
}
@@ -368,152 +384,199 @@ static const struct rtc_class_ops s3c_rtcops = {
.alarm_irq_enable = s3c_rtc_setaie,
};
-static void s3c_rtc_enable(struct platform_device *pdev, int en)
+static void s3c24xx_rtc_enable(struct s3c_rtc *info)
{
- void __iomem *base = s3c_rtc_base;
- unsigned int tmp;
+ unsigned int con, tmp;
- if (s3c_rtc_base == NULL)
- return;
-
- clk_enable(rtc_clk);
- if (!en) {
- tmp = readw(base + S3C2410_RTCCON);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- tmp &= ~S3C64XX_RTCCON_TICEN;
- tmp &= ~S3C2410_RTCCON_RTCEN;
- writew(tmp, base + S3C2410_RTCCON);
-
- if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
- tmp = readb(base + S3C2410_TICNT);
- tmp &= ~S3C2410_TICNT_ENABLE;
- writeb(tmp, base + S3C2410_TICNT);
- }
- } else {
- /* re-enable the device, and check it is ok */
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
- if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
- dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+ con = readw(info->base + S3C2410_RTCCON);
+ /* re-enable the device, and check it is ok */
+ if ((con & S3C2410_RTCCON_RTCEN) == 0) {
+ dev_info(info->dev, "rtc disabled, re-enabling\n");
- tmp = readw(base + S3C2410_RTCCON);
- writew(tmp | S3C2410_RTCCON_RTCEN,
- base + S3C2410_RTCCON);
- }
+ tmp = readw(info->base + S3C2410_RTCCON);
+ writew(tmp | S3C2410_RTCCON_RTCEN,
+ info->base + S3C2410_RTCCON);
+ }
- if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
- dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
+ if (con & S3C2410_RTCCON_CNTSEL) {
+ dev_info(info->dev, "removing RTCCON_CNTSEL\n");
- tmp = readw(base + S3C2410_RTCCON);
- writew(tmp & ~S3C2410_RTCCON_CNTSEL,
- base + S3C2410_RTCCON);
- }
+ tmp = readw(info->base + S3C2410_RTCCON);
+ writew(tmp & ~S3C2410_RTCCON_CNTSEL,
+ info->base + S3C2410_RTCCON);
+ }
- if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
- dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
+ if (con & S3C2410_RTCCON_CLKRST) {
+ dev_info(info->dev, "removing RTCCON_CLKRST\n");
- tmp = readw(base + S3C2410_RTCCON);
- writew(tmp & ~S3C2410_RTCCON_CLKRST,
- base + S3C2410_RTCCON);
- }
+ tmp = readw(info->base + S3C2410_RTCCON);
+ writew(tmp & ~S3C2410_RTCCON_CLKRST,
+ info->base + S3C2410_RTCCON);
}
- clk_disable(rtc_clk);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
}
-static int s3c_rtc_remove(struct platform_device *dev)
+static void s3c24xx_rtc_disable(struct s3c_rtc *info)
{
- s3c_rtc_setaie(&dev->dev, 0);
+ unsigned int con;
+
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
+ con = readw(info->base + S3C2410_RTCCON);
+ con &= ~S3C2410_RTCCON_RTCEN;
+ writew(con, info->base + S3C2410_RTCCON);
- clk_unprepare(rtc_clk);
- rtc_clk = NULL;
+ con = readb(info->base + S3C2410_TICNT);
+ con &= ~S3C2410_TICNT_ENABLE;
+ writeb(con, info->base + S3C2410_TICNT);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+}
+
+static void s3c6410_rtc_disable(struct s3c_rtc *info)
+{
+ unsigned int con;
+
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+
+ con = readw(info->base + S3C2410_RTCCON);
+ con &= ~S3C64XX_RTCCON_TICEN;
+ con &= ~S3C2410_RTCCON_RTCEN;
+ writew(con, info->base + S3C2410_RTCCON);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+}
+
+static int s3c_rtc_remove(struct platform_device *pdev)
+{
+ struct s3c_rtc *info = platform_get_drvdata(pdev);
+
+ s3c_rtc_setaie(info->dev, 0);
+
+ clk_unprepare(info->rtc_clk);
+ info->rtc_clk = NULL;
return 0;
}
static const struct of_device_id s3c_rtc_dt_match[];
-static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
+static struct s3c_rtc_data *s3c_rtc_get_data(struct platform_device *pdev)
{
-#ifdef CONFIG_OF
- struct s3c_rtc_drv_data *data;
- if (pdev->dev.of_node) {
- const struct of_device_id *match;
- match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
- data = (struct s3c_rtc_drv_data *) match->data;
- return data->cpu_type;
- }
-#endif
- return platform_get_device_id(pdev)->driver_data;
+ const struct of_device_id *match;
+
+ match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
+ return (struct s3c_rtc_data *)match->data;
}
static int s3c_rtc_probe(struct platform_device *pdev)
{
- struct rtc_device *rtc;
+ struct s3c_rtc *info = NULL;
struct rtc_time rtc_tm;
struct resource *res;
int ret;
- int tmp;
- dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev);
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
/* find the IRQs */
-
- s3c_rtc_tickno = platform_get_irq(pdev, 1);
- if (s3c_rtc_tickno < 0) {
+ info->irq_tick = platform_get_irq(pdev, 1);
+ if (info->irq_tick < 0) {
dev_err(&pdev->dev, "no irq for rtc tick\n");
- return s3c_rtc_tickno;
+ return info->irq_tick;
+ }
+
+ info->dev = &pdev->dev;
+ info->data = s3c_rtc_get_data(pdev);
+ if (!info->data) {
+ dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
+ return -EINVAL;
}
+ spin_lock_init(&info->pie_lock);
+ spin_lock_init(&info->alarm_clk_lock);
+
+ platform_set_drvdata(pdev, info);
- s3c_rtc_alarmno = platform_get_irq(pdev, 0);
- if (s3c_rtc_alarmno < 0) {
+ info->irq_alarm = platform_get_irq(pdev, 0);
+ if (info->irq_alarm < 0) {
dev_err(&pdev->dev, "no irq for alarm\n");
- return s3c_rtc_alarmno;
+ return info->irq_alarm;
}
dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",
- s3c_rtc_tickno, s3c_rtc_alarmno);
+ info->irq_tick, info->irq_alarm);
/* get the memory region */
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(s3c_rtc_base))
- return PTR_ERR(s3c_rtc_base);
-
- rtc_clk = devm_clk_get(&pdev->dev, "rtc");
- if (IS_ERR(rtc_clk)) {
- dev_err(&pdev->dev, "failed to find rtc clock source\n");
- ret = PTR_ERR(rtc_clk);
- rtc_clk = NULL;
- return ret;
+ info->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(info->base))
+ return PTR_ERR(info->base);
+
+ info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
+ if (IS_ERR(info->rtc_clk)) {
+ dev_err(&pdev->dev, "failed to find rtc clock\n");
+ return PTR_ERR(info->rtc_clk);
}
+ clk_prepare_enable(info->rtc_clk);
- clk_prepare_enable(rtc_clk);
+ info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
+ if (IS_ERR(info->rtc_src_clk)) {
+ dev_err(&pdev->dev, "failed to find rtc source clock\n");
+ return PTR_ERR(info->rtc_src_clk);
+ }
+ clk_prepare_enable(info->rtc_src_clk);
- /* check to see if everything is setup correctly */
- s3c_rtc_enable(pdev, 1);
+ /* check to see if everything is setup correctly */
+ if (info->data->enable)
+ info->data->enable(info);
dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
- readw(s3c_rtc_base + S3C2410_RTCCON));
+ readw(info->base + S3C2410_RTCCON));
device_init_wakeup(&pdev->dev, 1);
/* register RTC and exit */
-
- rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
+ info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
THIS_MODULE);
-
- if (IS_ERR(rtc)) {
+ if (IS_ERR(info->rtc)) {
dev_err(&pdev->dev, "cannot attach rtc\n");
- ret = PTR_ERR(rtc);
+ ret = PTR_ERR(info->rtc);
goto err_nortc;
}
- s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev);
+ ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
+ 0, "s3c2410-rtc alarm", info);
+ if (ret) {
+ dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
+ goto err_nortc;
+ }
- /* Check RTC Time */
+ ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq,
+ 0, "s3c2410-rtc tick", info);
+ if (ret) {
+ dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret);
+ goto err_nortc;
+ }
- s3c_rtc_gettime(NULL, &rtc_tm);
+ /* Check RTC Time */
+ s3c_rtc_gettime(&pdev->dev, &rtc_tm);
if (rtc_valid_tm(&rtc_tm)) {
rtc_tm.tm_year = 100;
@@ -523,163 +586,312 @@ static int s3c_rtc_probe(struct platform_device *pdev)
rtc_tm.tm_min = 0;
rtc_tm.tm_sec = 0;
- s3c_rtc_settime(NULL, &rtc_tm);
+ s3c_rtc_settime(&pdev->dev, &rtc_tm);
dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
}
- if (s3c_rtc_cpu_type != TYPE_S3C2410)
- rtc->max_user_freq = 32768;
- else
- rtc->max_user_freq = 128;
-
- if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
- tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
- tmp |= S3C2443_RTCCON_TICSEL;
- writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
- }
+ if (info->data->select_tick_clk)
+ info->data->select_tick_clk(info);
- platform_set_drvdata(pdev, rtc);
+ s3c_rtc_setfreq(info, 1);
- s3c_rtc_setfreq(&pdev->dev, 1);
-
- ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq,
- 0, "s3c2410-rtc alarm", rtc);
- if (ret) {
- dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
- goto err_nortc;
- }
-
- ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq,
- 0, "s3c2410-rtc tick", rtc);
- if (ret) {
- dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
- goto err_nortc;
- }
-
- clk_disable(rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
return 0;
err_nortc:
- s3c_rtc_enable(pdev, 0);
- clk_disable_unprepare(rtc_clk);
+ if (info->data->disable)
+ info->data->disable(info);
+ clk_disable_unprepare(info->rtc_clk);
return ret;
}
#ifdef CONFIG_PM_SLEEP
-/* RTC Power management control */
-
-static int ticnt_save, ticnt_en_save;
-static bool wake_en;
static int s3c_rtc_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct s3c_rtc *info = dev_get_drvdata(dev);
+
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
- clk_enable(rtc_clk);
/* save TICNT for anyone using periodic interrupts */
- if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
- ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
- ticnt_en_save &= S3C64XX_RTCCON_TICEN;
- ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT);
- } else {
- ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
- }
- s3c_rtc_enable(pdev, 0);
+ if (info->data->save_tick_cnt)
+ info->data->save_tick_cnt(info);
+
+ if (info->data->disable)
+ info->data->disable(info);
- if (device_may_wakeup(dev) && !wake_en) {
- if (enable_irq_wake(s3c_rtc_alarmno) == 0)
- wake_en = true;
+ if (device_may_wakeup(dev) && !info->wake_en) {
+ if (enable_irq_wake(info->irq_alarm) == 0)
+ info->wake_en = true;
else
dev_err(dev, "enable_irq_wake failed\n");
}
- clk_disable(rtc_clk);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
return 0;
}
static int s3c_rtc_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- unsigned int tmp;
+ struct s3c_rtc *info = dev_get_drvdata(dev);
- clk_enable(rtc_clk);
- s3c_rtc_enable(pdev, 1);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
- writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
- if (ticnt_en_save) {
- tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
- writew(tmp | ticnt_en_save,
- s3c_rtc_base + S3C2410_RTCCON);
- }
- } else {
- writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
- }
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
- if (device_may_wakeup(dev) && wake_en) {
- disable_irq_wake(s3c_rtc_alarmno);
- wake_en = false;
+ if (info->data->enable)
+ info->data->enable(info);
+
+ if (info->data->restore_tick_cnt)
+ info->data->restore_tick_cnt(info);
+
+ if (device_may_wakeup(dev) && info->wake_en) {
+ disable_irq_wake(info->irq_alarm);
+ info->wake_en = false;
}
- clk_disable(rtc_clk);
+
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
return 0;
}
#endif
-
static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
-#ifdef CONFIG_OF
-static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
- [TYPE_S3C2410] = { TYPE_S3C2410 },
- [TYPE_S3C2416] = { TYPE_S3C2416 },
- [TYPE_S3C2443] = { TYPE_S3C2443 },
- [TYPE_S3C64XX] = { TYPE_S3C64XX },
+static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
+{
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+ rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+
+ s3c_rtc_alarm_clk_enable(info, false);
+}
+
+static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
+{
+ clk_enable(info->rtc_clk);
+ if (info->data->needs_src_clk)
+ clk_enable(info->rtc_src_clk);
+ rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
+ writeb(mask, info->base + S3C2410_INTP);
+ if (info->data->needs_src_clk)
+ clk_disable(info->rtc_src_clk);
+ clk_disable(info->rtc_clk);
+
+ s3c_rtc_alarm_clk_enable(info, false);
+}
+
+static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+ unsigned int tmp = 0;
+ int val;
+
+ tmp = readb(info->base + S3C2410_TICNT);
+ tmp &= S3C2410_TICNT_ENABLE;
+
+ val = (info->rtc->max_user_freq / freq) - 1;
+ tmp |= val;
+
+ writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+ unsigned int tmp = 0;
+ int val;
+
+ tmp = readb(info->base + S3C2410_TICNT);
+ tmp &= S3C2410_TICNT_ENABLE;
+
+ val = (info->rtc->max_user_freq / freq) - 1;
+
+ tmp |= S3C2443_TICNT_PART(val);
+ writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
+
+ writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2);
+
+ writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+ unsigned int tmp = 0;
+ int val;
+
+ tmp = readb(info->base + S3C2410_TICNT);
+ tmp &= S3C2410_TICNT_ENABLE;
+
+ val = (info->rtc->max_user_freq / freq) - 1;
+
+ tmp |= S3C2443_TICNT_PART(val);
+ writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
+
+ writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+ int val;
+
+ val = (info->rtc->max_user_freq / freq) - 1;
+ writel(val, info->base + S3C2410_TICNT);
+}
+
+static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
+{
+ unsigned int ticnt;
+
+ ticnt = readb(info->base + S3C2410_TICNT);
+ ticnt &= S3C2410_TICNT_ENABLE;
+
+ seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
+}
+
+static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info)
+{
+ unsigned int con;
+
+ con = readw(info->base + S3C2410_RTCCON);
+ con |= S3C2443_RTCCON_TICSEL;
+ writew(con, info->base + S3C2410_RTCCON);
+}
+
+static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
+{
+ unsigned int ticnt;
+
+ ticnt = readw(info->base + S3C2410_RTCCON);
+ ticnt &= S3C64XX_RTCCON_TICEN;
+
+ seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
+}
+
+static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info)
+{
+ info->ticnt_save = readb(info->base + S3C2410_TICNT);
+}
+
+static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info)
+{
+ writeb(info->ticnt_save, info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info)
+{
+ info->ticnt_en_save = readw(info->base + S3C2410_RTCCON);
+ info->ticnt_en_save &= S3C64XX_RTCCON_TICEN;
+ info->ticnt_save = readl(info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info)
+{
+ unsigned int con;
+
+ writel(info->ticnt_save, info->base + S3C2410_TICNT);
+ if (info->ticnt_en_save) {
+ con = readw(info->base + S3C2410_RTCCON);
+ writew(con | info->ticnt_en_save,
+ info->base + S3C2410_RTCCON);
+ }
+}
+
+static struct s3c_rtc_data const s3c2410_rtc_data = {
+ .max_user_freq = 128,
+ .irq_handler = s3c24xx_rtc_irq,
+ .set_freq = s3c2410_rtc_setfreq,
+ .enable_tick = s3c24xx_rtc_enable_tick,
+ .save_tick_cnt = s3c24xx_rtc_save_tick_cnt,
+ .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt,
+ .enable = s3c24xx_rtc_enable,
+ .disable = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c2416_rtc_data = {
+ .max_user_freq = 32768,
+ .irq_handler = s3c24xx_rtc_irq,
+ .set_freq = s3c2416_rtc_setfreq,
+ .enable_tick = s3c24xx_rtc_enable_tick,
+ .select_tick_clk = s3c2416_rtc_select_tick_clk,
+ .save_tick_cnt = s3c24xx_rtc_save_tick_cnt,
+ .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt,
+ .enable = s3c24xx_rtc_enable,
+ .disable = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c2443_rtc_data = {
+ .max_user_freq = 32768,
+ .irq_handler = s3c24xx_rtc_irq,
+ .set_freq = s3c2443_rtc_setfreq,
+ .enable_tick = s3c24xx_rtc_enable_tick,
+ .select_tick_clk = s3c2416_rtc_select_tick_clk,
+ .save_tick_cnt = s3c24xx_rtc_save_tick_cnt,
+ .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt,
+ .enable = s3c24xx_rtc_enable,
+ .disable = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c6410_rtc_data = {
+ .max_user_freq = 32768,
+ .irq_handler = s3c6410_rtc_irq,
+ .set_freq = s3c6410_rtc_setfreq,
+ .enable_tick = s3c6410_rtc_enable_tick,
+ .save_tick_cnt = s3c6410_rtc_save_tick_cnt,
+ .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt,
+ .enable = s3c24xx_rtc_enable,
+ .disable = s3c6410_rtc_disable,
+};
+
+static struct s3c_rtc_data const exynos3250_rtc_data = {
+ .max_user_freq = 32768,
+ .needs_src_clk = true,
+ .irq_handler = s3c6410_rtc_irq,
+ .set_freq = s3c6410_rtc_setfreq,
+ .enable_tick = s3c6410_rtc_enable_tick,
+ .save_tick_cnt = s3c6410_rtc_save_tick_cnt,
+ .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt,
+ .enable = s3c24xx_rtc_enable,
+ .disable = s3c6410_rtc_disable,
};
static const struct of_device_id s3c_rtc_dt_match[] = {
{
.compatible = "samsung,s3c2410-rtc",
- .data = &s3c_rtc_drv_data_array[TYPE_S3C2410],
+ .data = (void *)&s3c2410_rtc_data,
}, {
.compatible = "samsung,s3c2416-rtc",
- .data = &s3c_rtc_drv_data_array[TYPE_S3C2416],
+ .data = (void *)&s3c2416_rtc_data,
}, {
.compatible = "samsung,s3c2443-rtc",
- .data = &s3c_rtc_drv_data_array[TYPE_S3C2443],
+ .data = (void *)&s3c2443_rtc_data,
}, {
.compatible = "samsung,s3c6410-rtc",
- .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX],
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
-#endif
-
-static struct platform_device_id s3c_rtc_driver_ids[] = {
- {
- .name = "s3c2410-rtc",
- .driver_data = TYPE_S3C2410,
- }, {
- .name = "s3c2416-rtc",
- .driver_data = TYPE_S3C2416,
- }, {
- .name = "s3c2443-rtc",
- .driver_data = TYPE_S3C2443,
+ .data = (void *)&s3c6410_rtc_data,
}, {
- .name = "s3c64xx-rtc",
- .driver_data = TYPE_S3C64XX,
+ .compatible = "samsung,exynos3250-rtc",
+ .data = (void *)&exynos3250_rtc_data,
},
- { }
+ { /* sentinel */ },
};
-
-MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
+MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
static struct platform_driver s3c_rtc_driver = {
.probe = s3c_rtc_probe,
.remove = s3c_rtc_remove,
- .id_table = s3c_rtc_driver_ids,
.driver = {
.name = "s3c-rtc",
.owner = THIS_MODULE,
@@ -687,7 +899,6 @@ static struct platform_driver s3c_rtc_driver = {
.of_match_table = of_match_ptr(s3c_rtc_dt_match),
},
};
-
module_platform_driver(s3c_rtc_driver);
MODULE_DESCRIPTION("Samsung S3C RTC Driver");
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index d497aa05a72f..c692dfebd0ba 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev,
if (!num_args)
return count;
- if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
+ if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
mutex_lock(&cp->lock);
error = s390_vary_chpid(cp->chpid, 1);
mutex_unlock(&cp->lock);
- } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
+ } else if (!strncasecmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
mutex_lock(&cp->lock);
error = s390_vary_chpid(cp->chpid, 0);
mutex_unlock(&cp->lock);
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 52a216f21ae5..e5afc3884d74 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -528,7 +528,7 @@ ips_setup(char *ips_str)
* Update the variables
*/
for (i = 0; i < ARRAY_SIZE(options); i++) {
- if (strnicmp
+ if (strncasecmp
(key, options[i].option_name,
strlen(options[i].option_name)) == 0) {
if (value)
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 2b6d447ad6d6..238e06f13b8a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
char work[20];
if (1 == sscanf(buf, "%10s", work)) {
- if (0 == strnicmp(work,"0x", 2)) {
+ if (0 == strncasecmp(work,"0x", 2)) {
if (1 == sscanf(&work[2], "%x", &opts))
goto opts_done;
} else {
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
index 1718229f6278..d9d55d12fd5f 100644
--- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
@@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr)
{
int cmd_num;
for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
- if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num],
+ if (0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num],
strlen(android_wifi_cmd_str[cmd_num])))
break;
return cmd_num;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index 91d35df286c3..2d82f8993ea1 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee)
static inline const char *escape_essid(const char *essid, u8 essid_len)
{
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
if (rtllib_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped;
}
- essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
+ snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
return escaped;
}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 9ecfa4a2421d..b44aa17d30a7 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
static inline const char *escape_essid(const char *essid, u8 essid_len) {
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
if (ieee80211_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped;
}
- essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
+ snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
return escaped;
}
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 799ce8aa70ef..df577dfe7ffb 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -60,7 +60,6 @@
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/byteorder/generic.h>
-#include <linux/ctype.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -81,27 +80,6 @@
#include "hfa384x.h"
#include "prism2mgmt.h"
-/* Create a string of printable chars from something that might not be */
-/* It's recommended that the str be 4*len + 1 bytes long */
-#define wlan_mkprintstr(buf, buflen, str, strlen) \
-{ \
- int i = 0; \
- int j = 0; \
- memset(str, 0, (strlen)); \
- for (i = 0; i < (buflen); i++) { \
- if (isprint((buf)[i])) { \
- (str)[j] = (buf)[i]; \
- j++; \
- } else { \
- (str)[j] = '\\'; \
- (str)[j+1] = 'x'; \
- (str)[j+2] = hex_asc_hi((buf)[i]); \
- (str)[j+3] = hex_asc_lo((buf)[i]); \
- j += 4; \
- } \
- } \
-}
-
static char *dev_info = "prism2_usb";
static wlandevice_t *create_wlan(void);
@@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
u16 temp;
u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
- char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
/* Collect version and compatibility info */
/* Some are critical, some are not */
@@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
snum, HFA384x_RID_NICSERIALNUMBER_LEN);
if (!result) {
- wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
- pstr, sizeof(pstr));
- netdev_info(wlandev->netdev, "Prism2 card SN: %s\n", pstr);
+ netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n",
+ HFA384x_RID_NICSERIALNUMBER_LEN, snum);
} else {
netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
goto failed;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 71b0ec0c370d..1e23f4f8d2c2 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name)
return def_governor;
list_for_each_entry(pos, &thermal_governor_list, governor_list)
- if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
+ if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH))
return pos;
return NULL;
@@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor)
name = pos->tzp->governor_name;
- if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+ if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH))
pos->governor = governor;
}
@@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node) {
- if (!strnicmp(pos->governor->name, governor->name,
+ if (!strncasecmp(pos->governor->name, governor->name,
THERMAL_NAME_LENGTH))
pos->governor = NULL;
}
@@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
- if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) {
+ if (!strncasecmp(name, pos->type, THERMAL_NAME_LENGTH)) {
found++;
ref = pos;
}
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index 167cffff3d4e..7c74f58fc101 100644
--- a/drivers/video/fbdev/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
for (i = 0 ; i < size ; i++ ) {
if (s != NULL) {
- if (!strnicmp(p[i].name, s, strlen(s)))
+ if (!strncasecmp(p[i].name, s, strlen(s)))
return p[i].val;
} else {
if (p[i].val == val)
diff --git a/drivers/video/fbdev/s3c2410fb.c b/drivers/video/fbdev/s3c2410fb.c
index 43c63a4f3178..e350eb57f11d 100644
--- a/drivers/video/fbdev/s3c2410fb.c
+++ b/drivers/video/fbdev/s3c2410fb.c
@@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev,
if (len < 1)
return -EINVAL;
- if (strnicmp(buf, "on", 2) == 0 ||
- strnicmp(buf, "1", 1) == 0) {
+ if (strncasecmp(buf, "on", 2) == 0 ||
+ strncasecmp(buf, "1", 1) == 0) {
debug = 1;
dev_dbg(dev, "s3c2410fb: Debug On");
- } else if (strnicmp(buf, "off", 3) == 0 ||
- strnicmp(buf, "0", 1) == 0) {
+ } else if (strncasecmp(buf, "off", 3) == 0 ||
+ strncasecmp(buf, "0", 1) == 0) {
debug = 0;
dev_dbg(dev, "s3c2410fb: Debug Off");
} else {
diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c
index 3f12a2dd959a..4f5cf035ac3c 100644
--- a/drivers/video/fbdev/sis/sis_main.c
+++ b/drivers/video/fbdev/sis/sis_main.c
@@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet)
return;
}
- if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+ if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
if(!quiet)
printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
@@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet)
i = 0; j = 0;
while(sisbios_mode[i].mode_no[0] != 0) {
- if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+ if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
if(sisfb_fstn) {
if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
sisbios_mode[i-1].mode_no[1] == 0x56 ||
@@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name)
if(name == NULL) return;
while(sis_crt2type[i].type_no != -1) {
- if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+ if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
sisfb_crt2type = sis_crt2type[i].type_no;
sisfb_tvplug = sis_crt2type[i].tvplug_no;
sisfb_crt2flags = sis_crt2type[i].flags;
@@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name)
return;
while(sis_tvtype[i].type_no != -1) {
- if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+ if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
sisfb_tvstd = sis_tvtype[i].type_no;
break;
}
@@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name)
if(name == NULL)
return;
- if(!strnicmp(name, "none", 4)) {
+ if(!strncasecmp(name, "none", 4)) {
sisfb_specialtiming = CUT_FORCENONE;
printk(KERN_DEBUG "sisfb: Special timing disabled\n");
} else {
while(mycustomttable[i].chipID != 0) {
- if(!strnicmp(name,mycustomttable[i].optionName,
+ if(!strncasecmp(name,mycustomttable[i].optionName,
strlen(mycustomttable[i].optionName))) {
sisfb_specialtiming = mycustomttable[i].SpecialID;
found = true;
@@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options)
if(!(*this_opt)) continue;
- if(!strnicmp(this_opt, "off", 3)) {
+ if(!strncasecmp(this_opt, "off", 3)) {
sisfb_off = 1;
- } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+ } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
/* Need to check crt2 type first for fstn/dstn */
sisfb_search_crt2type(this_opt + 14);
- } else if(!strnicmp(this_opt, "tvmode:",7)) {
+ } else if(!strncasecmp(this_opt, "tvmode:",7)) {
sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+ } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
sisfb_search_tvstd(this_opt + 11);
- } else if(!strnicmp(this_opt, "mode:", 5)) {
+ } else if(!strncasecmp(this_opt, "mode:", 5)) {
sisfb_search_mode(this_opt + 5, false);
- } else if(!strnicmp(this_opt, "vesa:", 5)) {
+ } else if(!strncasecmp(this_opt, "vesa:", 5)) {
sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
- } else if(!strnicmp(this_opt, "rate:", 5)) {
+ } else if(!strncasecmp(this_opt, "rate:", 5)) {
sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
+ } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
- } else if(!strnicmp(this_opt, "mem:",4)) {
+ } else if(!strncasecmp(this_opt, "mem:",4)) {
sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc:", 4)) {
+ } else if(!strncasecmp(this_opt, "pdc:", 4)) {
sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc1:", 5)) {
+ } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "noaccel", 7)) {
+ } else if(!strncasecmp(this_opt, "noaccel", 7)) {
sisfb_accel = 0;
- } else if(!strnicmp(this_opt, "accel", 5)) {
+ } else if(!strncasecmp(this_opt, "accel", 5)) {
sisfb_accel = -1;
- } else if(!strnicmp(this_opt, "noypan", 6)) {
+ } else if(!strncasecmp(this_opt, "noypan", 6)) {
sisfb_ypan = 0;
- } else if(!strnicmp(this_opt, "ypan", 4)) {
+ } else if(!strncasecmp(this_opt, "ypan", 4)) {
sisfb_ypan = -1;
- } else if(!strnicmp(this_opt, "nomax", 5)) {
+ } else if(!strncasecmp(this_opt, "nomax", 5)) {
sisfb_max = 0;
- } else if(!strnicmp(this_opt, "max", 3)) {
+ } else if(!strncasecmp(this_opt, "max", 3)) {
sisfb_max = -1;
- } else if(!strnicmp(this_opt, "userom:", 7)) {
+ } else if(!strncasecmp(this_opt, "userom:", 7)) {
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "useoem:", 7)) {
+ } else if(!strncasecmp(this_opt, "useoem:", 7)) {
sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
+ } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
sisfb_nocrt2rate = 1;
- } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+ } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
unsigned long temp = 2;
temp = simple_strtoul(this_opt + 9, NULL, 0);
if((temp == 0) || (temp == 1)) {
sisfb_scalelcd = temp ^ 1;
}
- } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+ } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
int temp = 0;
temp = (int)simple_strtol(this_opt + 13, NULL, 0);
if((temp >= -32) && (temp <= 32)) {
sisfb_tvxposoffset = temp;
}
- } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+ } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
int temp = 0;
temp = (int)simple_strtol(this_opt + 13, NULL, 0);
if((temp >= -32) && (temp <= 32)) {
sisfb_tvyposoffset = temp;
}
- } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
+ } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
sisfb_search_specialtiming(this_opt + 14);
- } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
+ } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
int temp = 4;
temp = simple_strtoul(this_opt + 7, NULL, 0);
if((temp >= 0) && (temp <= 3)) {
@@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options)
} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
sisfb_search_mode(this_opt, true);
#if !defined(__i386__) && !defined(__x86_64__)
- } else if(!strnicmp(this_opt, "resetcard", 9)) {
+ } else if(!strncasecmp(this_opt, "resetcard", 9)) {
sisfb_resetcard = 1;
- } else if(!strnicmp(this_opt, "videoram:", 9)) {
+ } else if(!strncasecmp(this_opt, "videoram:", 9)) {
sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
#endif
} else {
diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c
index c2c8eb668784..9e74e8fbe074 100644
--- a/drivers/video/fbdev/sm501fb.c
+++ b/drivers/video/fbdev/sm501fb.c
@@ -1187,9 +1187,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
if (len < 1)
return -EINVAL;
- if (strnicmp(buf, "crt", 3) == 0)
+ if (strncasecmp(buf, "crt", 3) == 0)
head = HEAD_CRT;
- else if (strnicmp(buf, "panel", 5) == 0)
+ else if (strncasecmp(buf, "panel", 5) == 0)
head = HEAD_PANEL;
else
return -EINVAL;
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 406b29836b19..abc853968fed 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -10,8 +10,6 @@
#include "affs.h"
-extern struct timezone sys_tz;
-
static char ErrorBuffer[256];
/*
diff --git a/fs/affs/file.c b/fs/affs/file.c
index a7fe57d2cd9a..1ed590aafecf 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -584,11 +584,14 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
bh->b_state &= ~(1UL << BH_New);
mark_buffer_dirty_inode(bh, inode);
if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);
+ u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
+
+ if (tmp_next)
+ affs_warning(sb, "extent_file_ofs",
+ "next block already set for %d (%d)",
+ bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
+ affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode);
affs_brelse(prev_bh);
}
@@ -727,11 +730,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New);
if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
+ u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
+
+ if (tmp_next)
+ affs_warning(sb, "commit_write_ofs",
+ "next block already set for %d (%d)",
+ bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
+ affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode);
}
}
@@ -758,11 +764,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New);
if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
+ u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
+
+ if (tmp_next)
+ affs_warning(sb, "commit_write_ofs",
+ "next block already set for %d (%d)",
+ bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
+ affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode);
}
} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
@@ -842,12 +851,12 @@ affs_truncate(struct inode *inode)
struct address_space *mapping = inode->i_mapping;
struct page *page;
void *fsdata;
- loff_t size = inode->i_size;
+ loff_t isize = inode->i_size;
int res;
- res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
+ res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, 0, &page, &fsdata);
if (!res)
- res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
+ res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
else
inode->i_size = AFFS_I(inode)->mmu_private;
mark_inode_dirty(inode);
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index bec2d1a0c91c..e217c511459b 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -14,13 +14,11 @@
#include "affs.h"
extern const struct inode_operations affs_symlink_inode_operations;
-extern struct timezone sys_tz;
struct inode *affs_iget(struct super_block *sb, unsigned long ino)
{
struct affs_sb_info *sbi = AFFS_SB(sb);
struct buffer_head *bh;
- struct affs_head *head;
struct affs_tail *tail;
struct inode *inode;
u32 block;
@@ -49,7 +47,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
goto bad_inode;
}
- head = AFFS_HEAD(bh);
tail = AFFS_TAIL(sb, bh);
prot = be32_to_cpu(tail->protect);
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 51f1a95bff73..f754ab68a840 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -20,8 +20,6 @@
#include <linux/writeback.h>
#include "affs.h"
-extern struct timezone sys_tz;
-
static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int affs_remount (struct super_block *sb, int *flags, char *data);
@@ -308,7 +306,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
u32 chksum;
int num_bm;
int i, j;
- s32 key;
kuid_t uid;
kgid_t gid;
int reserved;
@@ -367,7 +364,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
i = j = blocksize;
size = size / (blocksize / 512);
}
- for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
+ for (blocksize = i; blocksize <= j; blocksize <<= 1, size >>= 1) {
sbi->s_root_block = root_block;
if (root_block < 0)
sbi->s_root_block = (reserved + size - 1) / 2;
@@ -399,7 +396,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
sbi->s_hashsize = blocksize / 4 - 56;
sbi->s_root_block += num_bm;
- key = 1;
goto got_root;
}
affs_brelse(root_bh);
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 9e359fb20c0a..8e98cf954bab 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -79,6 +79,10 @@ struct autofs_info {
};
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
+#define AUTOFS_INF_NO_RCU (1<<1) /* the dentry is being considered
+ * for expiry, so RCU_walk is
+ * not permitted
+ */
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
struct autofs_wait_queue {
@@ -148,7 +152,7 @@ void autofs4_free_ino(struct autofs_info *);
/* Expiration */
int is_autofs4_dentry(struct dentry *);
-int autofs4_expire_wait(struct dentry *dentry);
+int autofs4_expire_wait(struct dentry *dentry, int rcu_walk);
int autofs4_expire_run(struct super_block *, struct vfsmount *,
struct autofs_sb_info *,
struct autofs_packet_expire __user *);
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 5b570b6efa28..aaf96cb25452 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -450,7 +450,7 @@ static int autofs_dev_ioctl_requester(struct file *fp,
ino = autofs4_dentry_ino(path.dentry);
if (ino) {
err = 0;
- autofs4_expire_wait(path.dentry);
+ autofs4_expire_wait(path.dentry, 0);
spin_lock(&sbi->fs_lock);
param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid);
param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 8fa3895cda02..683a5b9ce22a 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -30,12 +30,6 @@ static inline int autofs4_can_expire(struct dentry *dentry,
/* Too young to die */
if (!timeout || time_after(ino->last_used + timeout, now))
return 0;
-
- /* update last_used here :-
- - obviously makes sense if it is in use now
- - less obviously, prevents rapid-fire expire
- attempts if expire fails the first time */
- ino->last_used = now;
}
return 1;
}
@@ -327,10 +321,19 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
if (ino->flags & AUTOFS_INF_PENDING)
goto out;
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
- ino->flags |= AUTOFS_INF_EXPIRING;
- init_completion(&ino->expire_complete);
+ ino->flags |= AUTOFS_INF_NO_RCU;
spin_unlock(&sbi->fs_lock);
- return root;
+ synchronize_rcu();
+ spin_lock(&sbi->fs_lock);
+ if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
+ ino->flags |= AUTOFS_INF_EXPIRING;
+ smp_mb();
+ ino->flags &= ~AUTOFS_INF_NO_RCU;
+ init_completion(&ino->expire_complete);
+ spin_unlock(&sbi->fs_lock);
+ return root;
+ }
+ ino->flags &= ~AUTOFS_INF_NO_RCU;
}
out:
spin_unlock(&sbi->fs_lock);
@@ -339,6 +342,89 @@ out:
return NULL;
}
+/* Check if 'dentry' should expire, or return a nearby
+ * dentry that is suitable.
+ * If returned dentry is different from arg dentry,
+ * then a dget() reference was taken, else not.
+ */
+static struct dentry *should_expire(struct dentry *dentry,
+ struct vfsmount *mnt,
+ unsigned long timeout,
+ int how)
+{
+ int do_now = how & AUTOFS_EXP_IMMEDIATE;
+ int exp_leaves = how & AUTOFS_EXP_LEAVES;
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ unsigned int ino_count;
+
+ /* No point expiring a pending mount */
+ if (ino->flags & AUTOFS_INF_PENDING)
+ return NULL;
+
+ /*
+ * Case 1: (i) indirect mount or top level pseudo direct mount
+ * (autofs-4.1).
+ * (ii) indirect mount with offset mount, check the "/"
+ * offset (autofs-5.0+).
+ */
+ if (d_mountpoint(dentry)) {
+ DPRINTK("checking mountpoint %p %.*s",
+ dentry, (int)dentry->d_name.len, dentry->d_name.name);
+
+ /* Can we umount this guy */
+ if (autofs4_mount_busy(mnt, dentry))
+ return NULL;
+
+ /* Can we expire this guy */
+ if (autofs4_can_expire(dentry, timeout, do_now))
+ return dentry;
+ return NULL;
+ }
+
+ if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
+ DPRINTK("checking symlink %p %.*s",
+ dentry, (int)dentry->d_name.len, dentry->d_name.name);
+ /*
+ * A symlink can't be "busy" in the usual sense so
+ * just check last used for expire timeout.
+ */
+ if (autofs4_can_expire(dentry, timeout, do_now))
+ return dentry;
+ return NULL;
+ }
+
+ if (simple_empty(dentry))
+ return NULL;
+
+ /* Case 2: tree mount, expire iff entire tree is not busy */
+ if (!exp_leaves) {
+ /* Path walk currently on this dentry? */
+ ino_count = atomic_read(&ino->count) + 1;
+ if (d_count(dentry) > ino_count)
+ return NULL;
+
+ if (!autofs4_tree_busy(mnt, dentry, timeout, do_now))
+ return dentry;
+ /*
+ * Case 3: pseudo direct mount, expire individual leaves
+ * (autofs-4.1).
+ */
+ } else {
+ /* Path walk currently on this dentry? */
+ struct dentry *expired;
+ ino_count = atomic_read(&ino->count) + 1;
+ if (d_count(dentry) > ino_count)
+ return NULL;
+
+ expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
+ if (expired) {
+ if (expired == dentry)
+ dput(dentry);
+ return expired;
+ }
+ }
+ return NULL;
+}
/*
* Find an eligible tree to time-out
* A tree is eligible if :-
@@ -353,11 +439,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
unsigned long timeout;
struct dentry *root = sb->s_root;
struct dentry *dentry;
- struct dentry *expired = NULL;
- int do_now = how & AUTOFS_EXP_IMMEDIATE;
- int exp_leaves = how & AUTOFS_EXP_LEAVES;
+ struct dentry *expired;
struct autofs_info *ino;
- unsigned int ino_count;
if (!root)
return NULL;
@@ -369,77 +452,28 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
while ((dentry = get_next_positive_subdir(dentry, root))) {
spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry);
- /* No point expiring a pending mount */
- if (ino->flags & AUTOFS_INF_PENDING)
- goto next;
-
- /*
- * Case 1: (i) indirect mount or top level pseudo direct mount
- * (autofs-4.1).
- * (ii) indirect mount with offset mount, check the "/"
- * offset (autofs-5.0+).
- */
- if (d_mountpoint(dentry)) {
- DPRINTK("checking mountpoint %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
- /* Can we umount this guy */
- if (autofs4_mount_busy(mnt, dentry))
- goto next;
-
- /* Can we expire this guy */
- if (autofs4_can_expire(dentry, timeout, do_now)) {
- expired = dentry;
- goto found;
- }
- goto next;
+ if (ino->flags & AUTOFS_INF_NO_RCU)
+ expired = NULL;
+ else
+ expired = should_expire(dentry, mnt, timeout, how);
+ if (!expired) {
+ spin_unlock(&sbi->fs_lock);
+ continue;
}
-
- if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
- DPRINTK("checking symlink %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
- /*
- * A symlink can't be "busy" in the usual sense so
- * just check last used for expire timeout.
- */
- if (autofs4_can_expire(dentry, timeout, do_now)) {
- expired = dentry;
- goto found;
- }
- goto next;
- }
-
- if (simple_empty(dentry))
- goto next;
-
- /* Case 2: tree mount, expire iff entire tree is not busy */
- if (!exp_leaves) {
- /* Path walk currently on this dentry? */
- ino_count = atomic_read(&ino->count) + 1;
- if (d_count(dentry) > ino_count)
- goto next;
-
- if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
- expired = dentry;
- goto found;
- }
- /*
- * Case 3: pseudo direct mount, expire individual leaves
- * (autofs-4.1).
- */
- } else {
- /* Path walk currently on this dentry? */
- ino_count = atomic_read(&ino->count) + 1;
- if (d_count(dentry) > ino_count)
- goto next;
-
- expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
- if (expired) {
+ ino = autofs4_dentry_ino(expired);
+ ino->flags |= AUTOFS_INF_NO_RCU;
+ spin_unlock(&sbi->fs_lock);
+ synchronize_rcu();
+ spin_lock(&sbi->fs_lock);
+ if (should_expire(expired, mnt, timeout, how)) {
+ if (expired != dentry)
dput(dentry);
- goto found;
- }
+ goto found;
}
-next:
+
+ ino->flags &= ~AUTOFS_INF_NO_RCU;
+ if (expired != dentry)
+ dput(expired);
spin_unlock(&sbi->fs_lock);
}
return NULL;
@@ -447,8 +481,9 @@ next:
found:
DPRINTK("returning %p %.*s",
expired, (int)expired->d_name.len, expired->d_name.name);
- ino = autofs4_dentry_ino(expired);
ino->flags |= AUTOFS_INF_EXPIRING;
+ smp_mb();
+ ino->flags &= ~AUTOFS_INF_NO_RCU;
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
spin_lock(&sbi->lookup_lock);
@@ -461,13 +496,18 @@ found:
return expired;
}
-int autofs4_expire_wait(struct dentry *dentry)
+int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
int status;
/* Block on any pending expire */
+ if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)))
+ return 0;
+ if (rcu_walk)
+ return -ECHILD;
+
spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_EXPIRING) {
spin_unlock(&sbi->fs_lock);
@@ -519,6 +559,8 @@ int autofs4_expire_run(struct super_block *sb,
spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry);
+ /* avoid rapid-fire expire attempts if expiry fails */
+ ino->last_used = now;
ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
@@ -545,6 +587,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
spin_lock(&sbi->fs_lock);
+ /* avoid rapid-fire expire attempts if expiry fails */
+ ino->last_used = now;
ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index cdb25ebccc4c..d76d083f2f06 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -210,7 +210,8 @@ next:
return NULL;
}
-static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
+static struct dentry *autofs4_lookup_expiring(struct dentry *dentry,
+ bool rcu_walk)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *parent = dentry->d_parent;
@@ -229,6 +230,11 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
struct dentry *expiring;
struct qstr *qstr;
+ if (rcu_walk) {
+ spin_unlock(&sbi->lookup_lock);
+ return ERR_PTR(-ECHILD);
+ }
+
ino = list_entry(p, struct autofs_info, expiring);
expiring = ino->dentry;
@@ -264,13 +270,15 @@ next:
return NULL;
}
-static int autofs4_mount_wait(struct dentry *dentry)
+static int autofs4_mount_wait(struct dentry *dentry, bool rcu_walk)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
int status = 0;
if (ino->flags & AUTOFS_INF_PENDING) {
+ if (rcu_walk)
+ return -ECHILD;
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);
status = autofs4_wait(sbi, dentry, NFY_MOUNT);
@@ -280,20 +288,22 @@ static int autofs4_mount_wait(struct dentry *dentry)
return status;
}
-static int do_expire_wait(struct dentry *dentry)
+static int do_expire_wait(struct dentry *dentry, bool rcu_walk)
{
struct dentry *expiring;
- expiring = autofs4_lookup_expiring(dentry);
+ expiring = autofs4_lookup_expiring(dentry, rcu_walk);
+ if (IS_ERR(expiring))
+ return PTR_ERR(expiring);
if (!expiring)
- return autofs4_expire_wait(dentry);
+ return autofs4_expire_wait(dentry, rcu_walk);
else {
/*
* If we are racing with expire the request might not
* be quite complete, but the directory has been removed
* so it must have been successful, just wait for it.
*/
- autofs4_expire_wait(expiring);
+ autofs4_expire_wait(expiring, 0);
autofs4_del_expiring(expiring);
dput(expiring);
}
@@ -345,7 +355,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
* and the directory was removed, so just go ahead and try
* the mount.
*/
- status = do_expire_wait(dentry);
+ status = do_expire_wait(dentry, 0);
if (status && status != -EAGAIN)
return NULL;
@@ -353,7 +363,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_PENDING) {
spin_unlock(&sbi->fs_lock);
- status = autofs4_mount_wait(dentry);
+ status = autofs4_mount_wait(dentry, 0);
if (status)
return ERR_PTR(status);
goto done;
@@ -394,7 +404,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
}
ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
- status = autofs4_mount_wait(dentry);
+ status = autofs4_mount_wait(dentry, 0);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
if (status) {
@@ -423,28 +433,46 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
/* The daemon never waits. */
if (autofs4_oz_mode(sbi)) {
- if (rcu_walk)
- return 0;
if (!d_mountpoint(dentry))
return -EISDIR;
return 0;
}
- /* We need to sleep, so we need pathwalk to be in ref-mode */
- if (rcu_walk)
- return -ECHILD;
-
/* Wait for pending expires */
- do_expire_wait(dentry);
+ if (do_expire_wait(dentry, rcu_walk) == -ECHILD)
+ return -ECHILD;
/*
* This dentry may be under construction so wait on mount
* completion.
*/
- status = autofs4_mount_wait(dentry);
+ status = autofs4_mount_wait(dentry, rcu_walk);
if (status)
return status;
+ if (rcu_walk) {
+ /* We don't need fs_lock in rcu_walk mode,
+ * just testing 'AUTOFS_INFO_NO_RCU' is enough.
+ * simple_empty() takes a spinlock, so leave it
+ * to last.
+ * We only return -EISDIR when certain this isn't
+ * a mount-trap.
+ */
+ struct inode *inode;
+ if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
+ return 0;
+ if (d_mountpoint(dentry))
+ return 0;
+ inode = ACCESS_ONCE(dentry->d_inode);
+ if (inode && S_ISLNK(inode->i_mode))
+ return -EISDIR;
+ if (list_empty(&dentry->d_subdirs))
+ return 0;
+ if (!simple_empty(dentry))
+ return -EISDIR;
+ return 0;
+ }
+
spin_lock(&sbi->fs_lock);
/*
* If the dentry has been selected for expire while we slept
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
index 9c7faa8a9288..0826e91dacda 100644
--- a/fs/befs/btree.c
+++ b/fs/befs/btree.c
@@ -78,11 +78,11 @@
/*
* In memory structure of each btree node
*/
-typedef struct {
+struct befs_btree_node {
befs_host_btree_nodehead head; /* head of node converted to cpu byteorder */
struct buffer_head *bh;
befs_btree_nodehead *od_node; /* on disk node */
-} befs_btree_node;
+};
/* local constants */
static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
@@ -90,27 +90,30 @@ static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
/* local functions */
static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
befs_btree_super * bt_super,
- befs_btree_node * this_node,
+ struct befs_btree_node *this_node,
befs_off_t * node_off);
static int befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
befs_btree_super * sup);
static int befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
- befs_btree_node * node, befs_off_t node_off);
+ struct befs_btree_node *node,
+ befs_off_t node_off);
-static int befs_leafnode(befs_btree_node * node);
+static int befs_leafnode(struct befs_btree_node *node);
-static fs16 *befs_bt_keylen_index(befs_btree_node * node);
+static fs16 *befs_bt_keylen_index(struct befs_btree_node *node);
-static fs64 *befs_bt_valarray(befs_btree_node * node);
+static fs64 *befs_bt_valarray(struct befs_btree_node *node);
-static char *befs_bt_keydata(befs_btree_node * node);
+static char *befs_bt_keydata(struct befs_btree_node *node);
-static int befs_find_key(struct super_block *sb, befs_btree_node * node,
+static int befs_find_key(struct super_block *sb,
+ struct befs_btree_node *node,
const char *findkey, befs_off_t * value);
-static char *befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
+static char *befs_bt_get_key(struct super_block *sb,
+ struct befs_btree_node *node,
int index, u16 * keylen);
static int befs_compare_strings(const void *key1, int keylen1,
@@ -191,7 +194,7 @@ befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
static int
befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
- befs_btree_node * node, befs_off_t node_off)
+ struct befs_btree_node *node, befs_off_t node_off)
{
uint off = 0;
@@ -247,7 +250,7 @@ int
befs_btree_find(struct super_block *sb, befs_data_stream * ds,
const char *key, befs_off_t * value)
{
- befs_btree_node *this_node = NULL;
+ struct befs_btree_node *this_node = NULL;
befs_btree_super bt_super;
befs_off_t node_off;
int res;
@@ -260,11 +263,11 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
goto error;
}
- this_node = kmalloc(sizeof (befs_btree_node),
+ this_node = kmalloc(sizeof(struct befs_btree_node),
GFP_NOFS);
if (!this_node) {
befs_error(sb, "befs_btree_find() failed to allocate %zu "
- "bytes of memory", sizeof (befs_btree_node));
+ "bytes of memory", sizeof(struct befs_btree_node));
goto error;
}
@@ -333,7 +336,7 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
* Use binary search instead of a linear.
*/
static int
-befs_find_key(struct super_block *sb, befs_btree_node * node,
+befs_find_key(struct super_block *sb, struct befs_btree_node *node,
const char *findkey, befs_off_t * value)
{
int first, last, mid;
@@ -417,7 +420,7 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
loff_t key_no, size_t bufsize, char *keybuf, size_t * keysize,
befs_off_t * value)
{
- befs_btree_node *this_node;
+ struct befs_btree_node *this_node;
befs_btree_super bt_super;
befs_off_t node_off = 0;
int cur_key;
@@ -436,9 +439,10 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
goto error;
}
- if ((this_node = kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) {
+ this_node = kmalloc(sizeof(struct befs_btree_node), GFP_NOFS);
+ if (this_node == NULL) {
befs_error(sb, "befs_btree_read() failed to allocate %zu "
- "bytes of memory", sizeof (befs_btree_node));
+ "bytes of memory", sizeof(struct befs_btree_node));
goto error;
}
@@ -545,7 +549,8 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
*/
static int
befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
- befs_btree_super * bt_super, befs_btree_node * this_node,
+ befs_btree_super *bt_super,
+ struct befs_btree_node *this_node,
befs_off_t * node_off)
{
@@ -600,7 +605,7 @@ befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
* Return 1 if leaf, 0 if interior
*/
static int
-befs_leafnode(befs_btree_node * node)
+befs_leafnode(struct befs_btree_node *node)
{
/* all interior nodes (and only interior nodes) have an overflow node */
if (node->head.overflow == befs_bt_inval)
@@ -623,7 +628,7 @@ befs_leafnode(befs_btree_node * node)
* Except that rounding up to 8 works, and rounding up to 4 doesn't.
*/
static fs16 *
-befs_bt_keylen_index(befs_btree_node * node)
+befs_bt_keylen_index(struct befs_btree_node *node)
{
const int keylen_align = 8;
unsigned long int off =
@@ -644,7 +649,7 @@ befs_bt_keylen_index(befs_btree_node * node)
* of the node pointed to by the node header
*/
static fs64 *
-befs_bt_valarray(befs_btree_node * node)
+befs_bt_valarray(struct befs_btree_node *node)
{
void *keylen_index_start = (void *) befs_bt_keylen_index(node);
size_t keylen_index_size = node->head.all_key_count * sizeof (fs16);
@@ -660,7 +665,7 @@ befs_bt_valarray(befs_btree_node * node)
* of the node pointed to by the node header
*/
static char *
-befs_bt_keydata(befs_btree_node * node)
+befs_bt_keydata(struct befs_btree_node *node)
{
return (char *) ((void *) node->od_node + sizeof (befs_btree_nodehead));
}
@@ -676,7 +681,7 @@ befs_bt_keydata(befs_btree_node * node)
* Returns NULL on failure (bad input) and sets *@keylen = 0
*/
static char *
-befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
+befs_bt_get_key(struct super_block *sb, struct befs_btree_node *node,
int index, u16 * keylen)
{
int prev_key_end;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index b60500300dd7..fd8beb9657a2 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -62,7 +62,22 @@ static struct file_system_type bm_fs_type;
static struct vfsmount *bm_mnt;
static int entry_count;
-/*
+/*
+ * Max length of the register string. Determined by:
+ * - 7 delimiters
+ * - name: ~50 bytes
+ * - type: 1 byte
+ * - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
+ * - magic: 128 bytes (512 in escaped form)
+ * - mask: 128 bytes (512 in escaped form)
+ * - interp: ~50 bytes
+ * - flags: 5 bytes
+ * Round that up a bit, and then back off to hold the internal data
+ * (like struct Node).
+ */
+#define MAX_REGISTER_LENGTH 1920
+
+/*
* Check if we support the binfmt
* if we do, return the node, else NULL
* locking is done in load_misc_binary
@@ -279,7 +294,7 @@ static Node *create_entry(const char __user *buffer, size_t count)
/* some sanity checks */
err = -EINVAL;
- if ((count < 11) || (count > 256))
+ if ((count < 11) || (count > MAX_REGISTER_LENGTH))
goto out;
err = -ENOMEM;
@@ -396,12 +411,12 @@ static int parse_command(const char __user *buffer, size_t count)
{
char s[4];
- if (!count)
- return 0;
if (count > 3)
return -EINVAL;
if (copy_from_user(s, buffer, count))
return -EFAULT;
+ if (!count)
+ return 0;
if (s[count-1] == '\n')
count--;
if (count == 1 && s[0] == '0')
diff --git a/fs/buffer.c b/fs/buffer.c
index d1f704806264..9614adc7e754 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1331,8 +1331,8 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
for (i = 0; i < BH_LRU_SIZE; i++) {
struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
- if (bh && bh->b_bdev == bdev &&
- bh->b_blocknr == block && bh->b_size == size) {
+ if (bh && bh->b_blocknr == block && bh->b_bdev == bdev &&
+ bh->b_size == size) {
if (i) {
while (i) {
__this_cpu_write(bh_lrus.bhs[i],
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 58df174deb10..b8602f199815 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -195,15 +195,15 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
else
noff = tkn_e - (sb_mountdata + off) + 1;
- if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
+ if (strncasecmp(sb_mountdata + off, "unc=", 4) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) {
+ if (strncasecmp(sb_mountdata + off, "ip=", 3) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
+ if (strncasecmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
off += noff;
continue;
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 36ca2045009b..239e1fb33000 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1718,7 +1718,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
goto cifs_parse_mount_err;
}
- if (strnicmp(string, "default", 7) != 0) {
+ if (strncasecmp(string, "default", 7) != 0) {
vol->iocharset = kstrdup(string,
GFP_KERNEL);
if (!vol->iocharset) {
@@ -1790,7 +1790,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (string == NULL)
goto out_nomem;
- if (strnicmp(string, "1", 1) == 0) {
+ if (strncasecmp(string, "1", 1) == 0) {
/* This is the default */
break;
}
diff --git a/fs/coredump.c b/fs/coredump.c
index a93f7e6ea4cf..b5c86ffd5033 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -199,6 +199,14 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
err = cn_printf(cn, "%d",
task_tgid_nr(current));
break;
+ case 'i':
+ err = cn_printf(cn, "%d",
+ task_pid_vnr(current));
+ break;
+ case 'I':
+ err = cn_printf(cn, "%d",
+ task_pid_nr(current));
+ break;
/* uid */
case 'u':
err = cn_printf(cn, "%d", cred->uid);
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 628e22a5a543..d8da2d2e30ae 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -164,8 +164,6 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
return 0;
}
-extern struct timezone sys_tz;
-
/*
* The epoch of FAT timestamp is 1980.
* : bits : value
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 0524cda47a6e..95d255219b1e 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -242,8 +242,6 @@ extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
/* super.c */
extern void hfs_mark_mdb_dirty(struct super_block *sb);
-extern struct timezone sys_tz;
-
/*
* There are two time systems. Both are based on seconds since
* a particular time/date.
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5ddaf8625d3b..881b3bd0143f 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -247,7 +247,7 @@ static int isofs_dentry_cmp_common(
}
if (alen == blen) {
if (ci) {
- if (strnicmp(name->name, str, alen) == 0)
+ if (strncasecmp(name->name, str, alen) == 0)
return 0;
} else {
if (strncmp(name->name, str, alen) == 0)
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 314e7add99b8..7cb751dfbeef 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -1178,9 +1178,6 @@ static int day_n[] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
-
-extern struct timezone sys_tz;
-
static int utc2local(int time)
{
return time - sys_tz.tz_minuteswest * 60;
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 24978153c0c4..e9e3325f29f3 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -56,11 +56,9 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
mutex_unlock(&inode->i_mutex);
nilfs = inode->i_sb->s_fs_info;
- if (!err && nilfs_test_opt(nilfs, BARRIER)) {
- err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
- if (err != -EIO)
- err = 0;
- }
+ if (!err)
+ err = nilfs_flush_device(nilfs);
+
return err;
}
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index d071e7f23de2..e1fa69b341b9 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -126,7 +126,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
nilfs_transaction_abort(inode->i_sb);
goto out;
}
- nilfs_mark_inode_dirty(inode);
+ nilfs_mark_inode_dirty_sync(inode);
nilfs_transaction_commit(inode->i_sb); /* never fails */
/* Error handling should be detailed */
set_buffer_new(bh_result);
@@ -672,7 +672,7 @@ void nilfs_write_inode_common(struct inode *inode,
for substitutions of appended fields */
}
-void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh)
+void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags)
{
ino_t ino = inode->i_ino;
struct nilfs_inode_info *ii = NILFS_I(inode);
@@ -683,7 +683,8 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh)
if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state))
memset(raw_inode, 0, NILFS_MDT(ifile)->mi_entry_size);
- set_bit(NILFS_I_INODE_DIRTY, &ii->i_state);
+ if (flags & I_DIRTY_DATASYNC)
+ set_bit(NILFS_I_INODE_SYNC, &ii->i_state);
nilfs_write_inode_common(inode, raw_inode, 0);
/* XXX: call with has_bmap = 0 is a workaround to avoid
@@ -939,7 +940,7 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
return 0;
}
-int nilfs_mark_inode_dirty(struct inode *inode)
+int __nilfs_mark_inode_dirty(struct inode *inode, int flags)
{
struct buffer_head *ibh;
int err;
@@ -950,7 +951,7 @@ int nilfs_mark_inode_dirty(struct inode *inode)
"failed to reget inode block.\n");
return err;
}
- nilfs_update_inode(inode, ibh);
+ nilfs_update_inode(inode, ibh, flags);
mark_buffer_dirty(ibh);
nilfs_mdt_mark_dirty(NILFS_I(inode)->i_root->ifile);
brelse(ibh);
@@ -983,7 +984,7 @@ void nilfs_dirty_inode(struct inode *inode, int flags)
return;
}
nilfs_transaction_begin(inode->i_sb, &ti, 0);
- nilfs_mark_inode_dirty(inode);
+ __nilfs_mark_inode_dirty(inode, flags);
nilfs_transaction_commit(inode->i_sb); /* never fails */
}
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 422fb54b7377..9a20e513d7eb 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -1022,11 +1022,9 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
return ret;
nilfs = inode->i_sb->s_fs_info;
- if (nilfs_test_opt(nilfs, BARRIER)) {
- ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
- if (ret == -EIO)
- return ret;
- }
+ ret = nilfs_flush_device(nilfs);
+ if (ret < 0)
+ return ret;
if (argp != NULL) {
down_read(&nilfs->ns_segctor_sem);
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 0696161bf59d..91093cd74f0d 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -104,7 +104,7 @@ enum {
constructor */
NILFS_I_COLLECTED, /* All dirty blocks are collected */
NILFS_I_UPDATED, /* The file has been written back */
- NILFS_I_INODE_DIRTY, /* write_inode is requested */
+ NILFS_I_INODE_SYNC, /* dsync is not allowed for inode */
NILFS_I_BMAP, /* has bmap and btnode_cache */
NILFS_I_GCINODE, /* inode for GC, on memory only */
};
@@ -273,7 +273,7 @@ struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
unsigned long ino);
extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
unsigned long ino, __u64 cno);
-extern void nilfs_update_inode(struct inode *, struct buffer_head *);
+extern void nilfs_update_inode(struct inode *, struct buffer_head *, int);
extern void nilfs_truncate(struct inode *);
extern void nilfs_evict_inode(struct inode *);
extern int nilfs_setattr(struct dentry *, struct iattr *);
@@ -282,10 +282,18 @@ int nilfs_permission(struct inode *inode, int mask);
int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh);
extern int nilfs_inode_dirty(struct inode *);
int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty);
-extern int nilfs_mark_inode_dirty(struct inode *);
+extern int __nilfs_mark_inode_dirty(struct inode *, int);
extern void nilfs_dirty_inode(struct inode *, int flags);
int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len);
+static inline int nilfs_mark_inode_dirty(struct inode *inode)
+{
+ return __nilfs_mark_inode_dirty(inode, I_DIRTY);
+}
+static inline int nilfs_mark_inode_dirty_sync(struct inode *inode)
+{
+ return __nilfs_mark_inode_dirty(inode, I_DIRTY_SYNC);
+}
/* super.c */
extern struct inode *nilfs_alloc_inode(struct super_block *);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index a1a191634abc..7ef18fc656c2 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -930,7 +930,7 @@ static void nilfs_drop_collected_inodes(struct list_head *head)
if (!test_and_clear_bit(NILFS_I_COLLECTED, &ii->i_state))
continue;
- clear_bit(NILFS_I_INODE_DIRTY, &ii->i_state);
+ clear_bit(NILFS_I_INODE_SYNC, &ii->i_state);
set_bit(NILFS_I_UPDATED, &ii->i_state);
}
}
@@ -1833,6 +1833,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
nilfs_set_next_segment(nilfs, segbuf);
if (update_sr) {
+ nilfs->ns_flushed_device = 0;
nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start,
segbuf->sb_sum.seg_seq, nilfs->ns_cno++);
@@ -2194,7 +2195,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
nilfs_transaction_lock(sb, &ti, 0);
ii = NILFS_I(inode);
- if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) ||
+ if (test_bit(NILFS_I_INODE_SYNC, &ii->i_state) ||
nilfs_test_opt(nilfs, STRICT_ORDER) ||
test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) ||
nilfs_discontinued(nilfs)) {
@@ -2216,6 +2217,8 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
sci->sc_dsync_end = end;
err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
+ if (!err)
+ nilfs->ns_flushed_device = 0;
nilfs_transaction_unlock(sb);
return err;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 228f5bdf0772..2e5b3ec85b8f 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -310,6 +310,9 @@ int nilfs_commit_super(struct super_block *sb, int flag)
nilfs->ns_sbsize));
}
clear_nilfs_sb_dirty(nilfs);
+ nilfs->ns_flushed_device = 1;
+ /* make sure store to ns_flushed_device cannot be reordered */
+ smp_wmb();
return nilfs_sync_super(sb, flag);
}
@@ -514,6 +517,9 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
}
up_write(&nilfs->ns_sem);
+ if (!err)
+ err = nilfs_flush_device(nilfs);
+
return err;
}
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index d01ead1bea9a..23778d385836 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -46,6 +46,7 @@ enum {
/**
* struct the_nilfs - struct to supervise multiple nilfs mount points
* @ns_flags: flags
+ * @ns_flushed_device: flag indicating if all volatile data was flushed
* @ns_bdev: block device
* @ns_sem: semaphore for shared states
* @ns_snapshot_mount_mutex: mutex to protect snapshot mounts
@@ -103,6 +104,7 @@ enum {
*/
struct the_nilfs {
unsigned long ns_flags;
+ int ns_flushed_device;
struct block_device *ns_bdev;
struct rw_semaphore ns_sem;
@@ -371,4 +373,24 @@ static inline int nilfs_segment_is_active(struct the_nilfs *nilfs, __u64 n)
return n == nilfs->ns_segnum || n == nilfs->ns_nextnum;
}
+static inline int nilfs_flush_device(struct the_nilfs *nilfs)
+{
+ int err;
+
+ if (!nilfs_test_opt(nilfs, BARRIER) || nilfs->ns_flushed_device)
+ return 0;
+
+ nilfs->ns_flushed_device = 1;
+ /*
+ * the store to ns_flushed_device must not be reordered after
+ * blkdev_issue_flush().
+ */
+ smp_wmb();
+
+ err = blkdev_issue_flush(nilfs->ns_bdev, GFP_KERNEL, NULL);
+ if (err != -EIO)
+ err = 0;
+ return err;
+}
+
#endif /* _THE_NILFS_H */
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index d13385448168..eb9d48746ab4 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -2244,7 +2244,7 @@ ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
return -EINVAL;
for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) {
- if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len))
+ if (strncasecmp(page, o2hb_heartbeat_mode_desc[i], len))
continue;
ret = o2hb_global_heartbeat_mode_set(i);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 07ac24fd9252..af7598bff1b5 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -49,13 +49,13 @@ static ssize_t mlog_mask_show(u64 mask, char *buf)
static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count)
{
- if (!strnicmp(buf, "allow", 5)) {
+ if (!strncasecmp(buf, "allow", 5)) {
__mlog_set_u64(mask, mlog_and_bits);
__mlog_clear_u64(mask, mlog_not_bits);
- } else if (!strnicmp(buf, "deny", 4)) {
+ } else if (!strncasecmp(buf, "deny", 4)) {
__mlog_set_u64(mask, mlog_not_bits);
__mlog_clear_u64(mask, mlog_and_bits);
- } else if (!strnicmp(buf, "off", 3)) {
+ } else if (!strncasecmp(buf, "off", 3)) {
__mlog_clear_u64(mask, mlog_not_bits);
__mlog_clear_u64(mask, mlog_and_bits);
} else
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index ba8819702c56..138321b0c6c2 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -306,9 +306,7 @@ static const struct super_operations omfs_sops = {
*/
static int omfs_get_imap(struct super_block *sb)
{
- int bitmap_size;
- int array_size;
- int count;
+ unsigned int bitmap_size, count, array_size;
struct omfs_sb_info *sbi = OMFS_SB(sb);
struct buffer_head *bh;
unsigned long **ptr;
@@ -473,6 +471,12 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_sys_blocksize = be32_to_cpu(omfs_sb->s_sys_blocksize);
mutex_init(&sbi->s_bitmap_lock);
+ if (sbi->s_num_blocks > OMFS_MAX_BLOCKS) {
+ printk(KERN_ERR "omfs: sysblock number (%llx) is out of range\n",
+ (unsigned long long)sbi->s_num_blocks);
+ goto out_brelse_bh;
+ }
+
if (sbi->s_sys_blocksize > PAGE_SIZE) {
printk(KERN_ERR "omfs: sysblock size (%d) is out of range\n",
sbi->s_sys_blocksize);
diff --git a/fs/omfs/omfs_fs.h b/fs/omfs/omfs_fs.h
index ee5e4327de92..83a98330ed66 100644
--- a/fs/omfs/omfs_fs.h
+++ b/fs/omfs/omfs_fs.h
@@ -18,6 +18,7 @@
#define OMFS_XOR_COUNT 19
#define OMFS_MAX_BLOCK_SIZE 8192
#define OMFS_MAX_CLUSTER_SIZE 8
+#define OMFS_MAX_BLOCKS (1ul << 31)
struct omfs_super_block {
char s_fill1[256];
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index b7a7dc963a35..4e0388cffe3d 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -827,8 +827,21 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
.private = &cp,
};
down_read(&mm->mmap_sem);
- if (type == CLEAR_REFS_SOFT_DIRTY)
+ if (type == CLEAR_REFS_SOFT_DIRTY) {
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ if (!(vma->vm_flags & VM_SOFTDIRTY))
+ continue;
+ up_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ vma->vm_flags &= ~VM_SOFTDIRTY;
+ vma_set_page_prot(vma);
+ }
+ downgrade_write(&mm->mmap_sem);
+ break;
+ }
mmu_notifier_invalidate_range_start(mm, 0, -1);
+ }
for (vma = mm->mmap; vma; vma = vma->vm_next) {
cp.vma = vma;
if (is_vm_hugetlb_page(vma))
@@ -848,10 +861,6 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
continue;
if (type == CLEAR_REFS_MAPPED && !vma->vm_file)
continue;
- if (type == CLEAR_REFS_SOFT_DIRTY) {
- if (vma->vm_flags & VM_SOFTDIRTY)
- vma->vm_flags &= ~VM_SOFTDIRTY;
- }
walk_page_range(vma->vm_start, vma->vm_end,
&clear_refs_walk);
}
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index a88b1b3e7db3..d571e173a990 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -699,11 +699,13 @@ static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh,
chunk->bh[chunk->nr++] = bh;
if (chunk->nr >= CHUNK_SIZE) {
ret = 1;
- if (lock)
+ if (lock) {
spin_unlock(lock);
- fn(chunk);
- if (lock)
+ fn(chunk);
spin_lock(lock);
+ } else {
+ fn(chunk);
+ }
}
return ret;
}
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 7bc20809c99e..2c1036080d52 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -784,7 +784,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
};
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
- struct ufs_cylinder_group *ucg;
unsigned start, length, loc;
unsigned pos, want, blockmap, mask, end;
u64 result;
@@ -792,8 +791,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
(unsigned long long)goal, count);
- ucg = ubh_get_ucg(UCPI_UBH(ucpi));
-
if (goal)
start = ufs_dtogd(uspi, goal) >> 3;
else
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 081ff8826bf6..752e30d63904 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -253,6 +253,20 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
#define pgprot_device pgprot_noncached
#endif
+#ifndef pgprot_modify
+#define pgprot_modify pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+ if (pgprot_val(oldprot) == pgprot_val(pgprot_noncached(oldprot)))
+ newprot = pgprot_noncached(newprot);
+ if (pgprot_val(oldprot) == pgprot_val(pgprot_writecombine(oldprot)))
+ newprot = pgprot_writecombine(newprot);
+ if (pgprot_val(oldprot) == pgprot_val(pgprot_device(oldprot)))
+ newprot = pgprot_device(newprot);
+ return newprot;
+}
+#endif
+
/*
* When walking page tables, get the address of the next boundary,
* or the end address of the range if that comes earlier. Although no
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 371b93042520..0430ed05d3b9 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -22,6 +22,9 @@ extern int __init cma_declare_contiguous(phys_addr_t size,
phys_addr_t base, phys_addr_t limit,
phys_addr_t alignment, unsigned int order_per_bit,
bool fixed, struct cma **res_cma);
+extern int cma_init_reserved_mem(phys_addr_t size,
+ phys_addr_t base, int order_per_bit,
+ struct cma **res_cma);
extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align);
extern bool cma_release(struct cma *cma, struct page *pages, int count);
#endif
diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h
new file mode 100644
index 000000000000..cdd1cc202d51
--- /dev/null
+++ b/include/linux/compiler-gcc5.h
@@ -0,0 +1,66 @@
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead."
+#endif
+
+#define __used __attribute__((__used__))
+#define __must_check __attribute__((warn_unused_result))
+#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
+
+/* Mark functions as cold. gcc will assume any path leading to a call
+ to them will be unlikely. This means a lot of manual unlikely()s
+ are unnecessary now for any paths leading to the usual suspects
+ like BUG(), printk(), panic() etc. [but let's keep them for now for
+ older compilers]
+
+ Early snapshots of gcc 4.3 don't support this and we can't detect this
+ in the preprocessor, but we can live with this because they're unreleased.
+ Maketime probing would be overkill here.
+
+ gcc also has a __attribute__((__hot__)) to move hot functions into
+ a special section, but I don't see any sense in this right now in
+ the kernel context */
+#define __cold __attribute__((__cold__))
+
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+#ifndef __CHECKER__
+# define __compiletime_warning(message) __attribute__((warning(message)))
+# define __compiletime_error(message) __attribute__((error(message)))
+#endif /* __CHECKER__ */
+
+/*
+ * Mark a position in code as unreachable. This can be used to
+ * suppress control flow warnings after asm blocks that transfer
+ * control elsewhere.
+ *
+ * Early snapshots of gcc 4.5 don't support this and we can't detect
+ * this in the preprocessor, but we can live with this because they're
+ * unreleased. Really, we need to have autoconf for the kernel.
+ */
+#define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone __attribute__((__noclone__))
+
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ * Fixed in GCC 4.8.2 and later versions.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
+
+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 35c8ffb0136f..40728cf1c452 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -376,10 +376,6 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern long simple_strtol(const char *,char **,unsigned int);
extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
extern long long simple_strtoll(const char *,char **,unsigned int);
-#define strict_strtoul kstrtoul
-#define strict_strtol kstrtol
-#define strict_strtoull kstrtoull
-#define strict_strtoll kstrtoll
extern int num_to_str(char *buf, int size, unsigned long long num);
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 4b2a0e11cc5b..9d957b7ae095 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -178,6 +178,7 @@ struct kexec_buf {
struct kimage *image;
char *buffer;
unsigned long bufsz;
+ unsigned long mem;
unsigned long memsz;
unsigned long buf_align;
unsigned long buf_min;
diff --git a/include/linux/list.h b/include/linux/list.h
index cbbb96fcead9..f33f831eb3c8 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -5,6 +5,7 @@
#include <linux/stddef.h>
#include <linux/poison.h>
#include <linux/const.h>
+#include <linux/kernel.h>
/*
* Simple doubly linked list implementation.
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fa0d74e06428..02d11ee7f19d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -347,6 +347,7 @@ static inline int put_page_unless_one(struct page *page)
}
extern int page_is_ram(unsigned long pfn);
+extern int region_is_ram(resource_size_t phys_addr, unsigned long size);
/* Support for virtually mapped pages */
struct page *vmalloc_to_page(const void *addr);
@@ -1973,11 +1974,16 @@ static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm,
#ifdef CONFIG_MMU
pgprot_t vm_get_page_prot(unsigned long vm_flags);
+void vma_set_page_prot(struct vm_area_struct *vma);
#else
static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
{
return __pgprot(0);
}
+static inline void vma_set_page_prot(struct vm_area_struct *vma)
+{
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+}
#endif
#ifdef CONFIG_NUMA_BALANCING
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index b43f4752304e..1c9effa25e26 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -78,6 +78,8 @@ struct kernel_param {
};
};
+extern const struct kernel_param __start___param[], __stop___param[];
+
/* Special one for strings we want to copy into */
struct kparam_string {
unsigned int maxlen;
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index 1d2a6ab6b8bb..9b2022ab4d85 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -24,6 +24,19 @@ static inline void touch_nmi_watchdog(void)
}
#endif
+#if defined(CONFIG_HARDLOCKUP_DETECTOR)
+extern void watchdog_enable_hardlockup_detector(bool val);
+extern bool watchdog_hardlockup_detector_is_enabled(void);
+#else
+static inline void watchdog_enable_hardlockup_detector(bool val)
+{
+}
+static inline bool watchdog_hardlockup_detector_is_enabled(void)
+{
+ return true;
+}
+#endif
+
/*
* Create trigger_all_cpu_backtrace() out of the arch-provided
* base function. Return whether such support was available,
diff --git a/include/linux/prio_heap.h b/include/linux/prio_heap.h
deleted file mode 100644
index 08094350f26a..000000000000
--- a/include/linux/prio_heap.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _LINUX_PRIO_HEAP_H
-#define _LINUX_PRIO_HEAP_H
-
-/*
- * Simple insertion-only static-sized priority heap containing
- * pointers, based on CLR, chapter 7
- */
-
-#include <linux/gfp.h>
-
-/**
- * struct ptr_heap - simple static-sized priority heap
- * @ptrs - pointer to data area
- * @max - max number of elements that can be stored in @ptrs
- * @size - current number of valid elements in @ptrs (in the range 0..@size-1
- * @gt: comparison operator, which should implement "greater than"
- */
-struct ptr_heap {
- void **ptrs;
- int max;
- int size;
- int (*gt)(void *, void *);
-};
-
-/**
- * heap_init - initialize an empty heap with a given memory size
- * @heap: the heap structure to be initialized
- * @size: amount of memory to use in bytes
- * @gfp_mask: mask to pass to kmalloc()
- * @gt: comparison operator, which should implement "greater than"
- */
-extern int heap_init(struct ptr_heap *heap, size_t size, gfp_t gfp_mask,
- int (*gt)(void *, void *));
-
-/**
- * heap_free - release a heap's storage
- * @heap: the heap structure whose data should be released
- */
-void heap_free(struct ptr_heap *heap);
-
-/**
- * heap_insert - insert a value into the heap and return any overflowed value
- * @heap: the heap to be operated on
- * @p: the pointer to be inserted
- *
- * Attempts to insert the given value into the priority heap. If the
- * heap is full prior to the insertion, then the resulting heap will
- * consist of the smallest @max elements of the original heap and the
- * new element; the greatest element will be removed from the heap and
- * returned. Note that the returned element will be the new element
- * (i.e. no change to the heap) if the new element is greater than all
- * elements currently in the heap.
- */
-extern void *heap_insert(struct ptr_heap *heap, void *p);
-
-
-
-#endif /* _LINUX_PRIO_HEAP_H */
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h
index fea49b5da12a..378c5ee75f78 100644
--- a/include/linux/rbtree_augmented.h
+++ b/include/linux/rbtree_augmented.h
@@ -43,6 +43,16 @@ struct rb_augment_callbacks {
extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
+/*
+ * Fixup the rbtree and update the augmented information when rebalancing.
+ *
+ * On insertion, the user must update the augmented information on the path
+ * leading to the inserted node, then call rb_link_node() as usual and
+ * rb_augment_inserted() instead of the usual rb_insert_color() call.
+ * If rb_augment_inserted() rebalances the rbtree, it will callback into
+ * a user provided function to update the augmented information on the
+ * affected subtrees.
+ */
static inline void
rb_insert_augmented(struct rb_node *node, struct rb_root *root,
const struct rb_augment_callbacks *augment)
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 750196fcc0a5..ab1e0392b5ac 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -2,6 +2,7 @@
#define _LINUX_SIGNAL_H
#include <linux/list.h>
+#include <linux/bug.h>
#include <uapi/linux/signal.h>
struct task_struct;
@@ -67,7 +68,6 @@ static inline int sigismember(sigset_t *set, int _sig)
static inline int sigisemptyset(sigset_t *set)
{
- extern void _NSIG_WORDS_is_unsupported_size(void);
switch (_NSIG_WORDS) {
case 4:
return (set->sig[3] | set->sig[2] |
@@ -77,7 +77,7 @@ static inline int sigisemptyset(sigset_t *set)
case 1:
return set->sig[0] == 0;
default:
- _NSIG_WORDS_is_unsupported_size();
+ BUILD_BUG();
return 0;
}
}
@@ -90,24 +90,23 @@ static inline int sigisemptyset(sigset_t *set)
#define _SIG_SET_BINOP(name, op) \
static inline void name(sigset_t *r, const sigset_t *a, const sigset_t *b) \
{ \
- extern void _NSIG_WORDS_is_unsupported_size(void); \
unsigned long a0, a1, a2, a3, b0, b1, b2, b3; \
\
switch (_NSIG_WORDS) { \
- case 4: \
+ case 4: \
a3 = a->sig[3]; a2 = a->sig[2]; \
b3 = b->sig[3]; b2 = b->sig[2]; \
r->sig[3] = op(a3, b3); \
r->sig[2] = op(a2, b2); \
- case 2: \
+ case 2: \
a1 = a->sig[1]; b1 = b->sig[1]; \
r->sig[1] = op(a1, b1); \
- case 1: \
+ case 1: \
a0 = a->sig[0]; b0 = b->sig[0]; \
r->sig[0] = op(a0, b0); \
break; \
- default: \
- _NSIG_WORDS_is_unsupported_size(); \
+ default: \
+ BUILD_BUG(); \
} \
}
@@ -128,16 +127,14 @@ _SIG_SET_BINOP(sigandnsets, _sig_andn)
#define _SIG_SET_OP(name, op) \
static inline void name(sigset_t *set) \
{ \
- extern void _NSIG_WORDS_is_unsupported_size(void); \
- \
switch (_NSIG_WORDS) { \
- case 4: set->sig[3] = op(set->sig[3]); \
- set->sig[2] = op(set->sig[2]); \
- case 2: set->sig[1] = op(set->sig[1]); \
- case 1: set->sig[0] = op(set->sig[0]); \
+ case 4: set->sig[3] = op(set->sig[3]); \
+ set->sig[2] = op(set->sig[2]); \
+ case 2: set->sig[1] = op(set->sig[1]); \
+ case 1: set->sig[0] = op(set->sig[0]); \
break; \
- default: \
- _NSIG_WORDS_is_unsupported_size(); \
+ default: \
+ BUILD_BUG(); \
} \
}
diff --git a/include/linux/string.h b/include/linux/string.h
index d36977e029af..e6edfe51575a 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -41,7 +41,7 @@ extern int strcmp(const char *,const char *);
extern int strncmp(const char *,const char *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRNICMP
-extern int strnicmp(const char *, const char *, __kernel_size_t);
+#define strnicmp strncasecmp
#endif
#ifndef __HAVE_ARCH_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 3eeee9672a4a..6eb567ac56bc 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -20,40 +20,6 @@ int string_get_size(u64 size, enum string_size_units units,
#define UNESCAPE_ANY \
(UNESCAPE_SPACE | UNESCAPE_OCTAL | UNESCAPE_HEX | UNESCAPE_SPECIAL)
-/**
- * string_unescape - unquote characters in the given string
- * @src: source buffer (escaped)
- * @dst: destination buffer (unescaped)
- * @size: size of the destination buffer (0 to unlimit)
- * @flags: combination of the flags (bitwise OR):
- * %UNESCAPE_SPACE:
- * '\f' - form feed
- * '\n' - new line
- * '\r' - carriage return
- * '\t' - horizontal tab
- * '\v' - vertical tab
- * %UNESCAPE_OCTAL:
- * '\NNN' - byte with octal value NNN (1 to 3 digits)
- * %UNESCAPE_HEX:
- * '\xHH' - byte with hexadecimal value HH (1 to 2 digits)
- * %UNESCAPE_SPECIAL:
- * '\"' - double quote
- * '\\' - backslash
- * '\a' - alert (BEL)
- * '\e' - escape
- * %UNESCAPE_ANY:
- * all previous together
- *
- * Returns amount of characters processed to the destination buffer excluding
- * trailing '\0'.
- *
- * Because the size of the output will be the same as or less than the size of
- * the input, the transformation may be performed in place.
- *
- * Caller must provide valid source and destination pointers. Be aware that
- * destination buffer will always be NULL-terminated. Source string must be
- * NULL-terminated as well.
- */
int string_unescape(char *src, char *dst, size_t size, unsigned int flags);
static inline int string_unescape_inplace(char *buf, unsigned int flags)
@@ -71,4 +37,35 @@ static inline int string_unescape_any_inplace(char *buf)
return string_unescape_any(buf, buf, 0);
}
+#define ESCAPE_SPACE 0x01
+#define ESCAPE_SPECIAL 0x02
+#define ESCAPE_NULL 0x04
+#define ESCAPE_OCTAL 0x08
+#define ESCAPE_ANY \
+ (ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_SPECIAL | ESCAPE_NULL)
+#define ESCAPE_NP 0x10
+#define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP)
+#define ESCAPE_HEX 0x20
+
+int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
+ unsigned int flags, const char *esc);
+
+static inline int string_escape_mem_any_np(const char *src, size_t isz,
+ char **dst, size_t osz, const char *esc)
+{
+ return string_escape_mem(src, isz, dst, osz, ESCAPE_ANY_NP, esc);
+}
+
+static inline int string_escape_str(const char *src, char **dst, size_t sz,
+ unsigned int flags, const char *esc)
+{
+ return string_escape_mem(src, strlen(src), dst, sz, flags, esc);
+}
+
+static inline int string_escape_str_any_np(const char *src, char **dst,
+ size_t sz, const char *esc)
+{
+ return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, esc);
+}
+
#endif
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index be95b9262801..aab0f427edb5 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -32,11 +32,6 @@
#include <linux/timer.h>
#include <linux/seq_file.h>
-/* print_ssid() is intended to be used in debug (and possibly error)
- * messages. It should never be used for passing ssid to user space. */
-const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
-#define DECLARE_SSID_BUF(var) char var[IEEE80211_MAX_SSID_LEN * 4 + 1] __maybe_unused
-
#define NUM_WEP_KEYS 4
enum {
diff --git a/init/Kconfig b/init/Kconfig
index 1c505e090422..3ee28ae02cc8 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -838,6 +838,7 @@ config LOG_BUF_SHIFT
config LOG_CPU_MAX_BUF_SHIFT
int "CPU kernel log buffer size contribution (13 => 8 KB, 17 => 128KB)"
+ depends on SMP
range 0 21
default 12 if !BASE_SMALL
default 0 if BASE_SMALL
diff --git a/init/initramfs.c b/init/initramfs.c
index bece48c3461e..ad1bd7787bbb 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -197,14 +197,14 @@ static __initdata enum state {
} state, next_state;
static __initdata char *victim;
-static unsigned long count __initdata;
+static unsigned long byte_count __initdata;
static __initdata loff_t this_header, next_header;
static inline void __init eat(unsigned n)
{
victim += n;
this_header += n;
- count -= n;
+ byte_count -= n;
}
static __initdata char *vcollected;
@@ -214,7 +214,7 @@ static __initdata char *collect;
static void __init read_into(char *buf, unsigned size, enum state next)
{
- if (count >= size) {
+ if (byte_count >= size) {
collected = victim;
eat(size);
state = next;
@@ -237,8 +237,8 @@ static int __init do_start(void)
static int __init do_collect(void)
{
unsigned long n = remains;
- if (count < n)
- n = count;
+ if (byte_count < n)
+ n = byte_count;
memcpy(collect, victim, n);
eat(n);
collect += n;
@@ -280,8 +280,8 @@ static int __init do_header(void)
static int __init do_skip(void)
{
- if (this_header + count < next_header) {
- eat(count);
+ if (this_header + byte_count < next_header) {
+ eat(byte_count);
return 1;
} else {
eat(next_header - this_header);
@@ -292,9 +292,9 @@ static int __init do_skip(void)
static int __init do_reset(void)
{
- while(count && *victim == '\0')
+ while (byte_count && *victim == '\0')
eat(1);
- if (count && (this_header & 3))
+ if (byte_count && (this_header & 3))
error("broken padding");
return 1;
}
@@ -309,11 +309,11 @@ static int __init maybe_link(void)
return 0;
}
-static void __init clean_path(char *path, umode_t mode)
+static void __init clean_path(char *path, umode_t fmode)
{
struct stat st;
- if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) {
+ if (!sys_newlstat(path, &st) && (st.st_mode ^ fmode) & S_IFMT) {
if (S_ISDIR(st.st_mode))
sys_rmdir(path);
else
@@ -368,7 +368,7 @@ static int __init do_name(void)
static int __init do_copy(void)
{
- if (count >= body_len) {
+ if (byte_count >= body_len) {
if (xwrite(wfd, victim, body_len) != body_len)
error("write error");
sys_close(wfd);
@@ -378,10 +378,10 @@ static int __init do_copy(void)
state = SkipIt;
return 0;
} else {
- if (xwrite(wfd, victim, count) != count)
+ if (xwrite(wfd, victim, byte_count) != byte_count)
error("write error");
- body_len -= count;
- eat(count);
+ body_len -= byte_count;
+ eat(byte_count);
return 1;
}
}
@@ -411,12 +411,12 @@ static __initdata int (*actions[])(void) = {
static long __init write_buffer(char *buf, unsigned long len)
{
- count = len;
+ byte_count = len;
victim = buf;
while (!actions[state]())
;
- return len - count;
+ return len - byte_count;
}
static long __init flush_buffer(void *bufv, unsigned long len)
diff --git a/init/main.c b/init/main.c
index 89ec862da2d4..800a0daede7e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -501,7 +501,6 @@ asmlinkage __visible void __init start_kernel(void)
{
char *command_line;
char *after_dashes;
- extern const struct kernel_param __start___param[], __stop___param[];
/*
* Need to run as early as possible, to initialize the
@@ -844,7 +843,6 @@ static char *initcall_level_names[] __initdata = {
static void __init do_initcall_level(int level)
{
- extern const struct kernel_param __start___param[], __stop___param[];
initcall_t *fn;
strcpy(initcall_command_line, saved_command_line);
diff --git a/ipc/compat.c b/ipc/compat.c
index b5ef4f7946dc..9b3c85f8a538 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -171,32 +171,32 @@ static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
}
static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
- struct compat_ipc_perm __user *up)
+ struct compat_ipc_perm __user *uip)
{
int err;
__compat_uid_t u;
__compat_gid_t g;
- err = __put_user(p->key, &up->key);
+ err = __put_user(p->key, &uip->key);
SET_UID(u, p->uid);
- err |= __put_user(u, &up->uid);
+ err |= __put_user(u, &uip->uid);
SET_GID(g, p->gid);
- err |= __put_user(g, &up->gid);
+ err |= __put_user(g, &uip->gid);
SET_UID(u, p->cuid);
- err |= __put_user(u, &up->cuid);
+ err |= __put_user(u, &uip->cuid);
SET_GID(g, p->cgid);
- err |= __put_user(g, &up->cgid);
- err |= __put_user(p->mode, &up->mode);
- err |= __put_user(p->seq, &up->seq);
+ err |= __put_user(g, &uip->cgid);
+ err |= __put_user(p->mode, &uip->mode);
+ err |= __put_user(p->seq, &uip->seq);
return err;
}
-static inline int get_compat_semid64_ds(struct semid64_ds *s64,
+static inline int get_compat_semid64_ds(struct semid64_ds *sem64,
struct compat_semid64_ds __user *up64)
{
if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
return -EFAULT;
- return __get_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
+ return __get_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
}
static inline int get_compat_semid_ds(struct semid64_ds *s,
@@ -207,17 +207,17 @@ static inline int get_compat_semid_ds(struct semid64_ds *s,
return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
}
-static inline int put_compat_semid64_ds(struct semid64_ds *s64,
+static inline int put_compat_semid64_ds(struct semid64_ds *sem64,
struct compat_semid64_ds __user *up64)
{
int err;
if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
return -EFAULT;
- err = __put_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
- err |= __put_user(s64->sem_otime, &up64->sem_otime);
- err |= __put_user(s64->sem_ctime, &up64->sem_ctime);
- err |= __put_user(s64->sem_nsems, &up64->sem_nsems);
+ err = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
+ err |= __put_user(sem64->sem_otime, &up64->sem_otime);
+ err |= __put_user(sem64->sem_ctime, &up64->sem_ctime);
+ err |= __put_user(sem64->sem_nsems, &up64->sem_nsems);
return err;
}
@@ -239,11 +239,11 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
{
unsigned long fourth;
int err, err2;
- struct semid64_ds s64;
+ struct semid64_ds sem64;
struct semid64_ds __user *up64;
int version = compat_ipc_parse_version(&third);
- memset(&s64, 0, sizeof(s64));
+ memset(&sem64, 0, sizeof(sem64));
if ((third & (~IPC_64)) == SETVAL)
#ifdef __BIG_ENDIAN
@@ -269,29 +269,29 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
case IPC_STAT:
case SEM_STAT:
- up64 = compat_alloc_user_space(sizeof(s64));
+ up64 = compat_alloc_user_space(sizeof(sem64));
fourth = (unsigned long)up64;
err = sys_semctl(first, second, third, fourth);
if (err < 0)
break;
- if (copy_from_user(&s64, up64, sizeof(s64)))
+ if (copy_from_user(&sem64, up64, sizeof(sem64)))
err2 = -EFAULT;
else if (version == IPC_64)
- err2 = put_compat_semid64_ds(&s64, compat_ptr(pad));
+ err2 = put_compat_semid64_ds(&sem64, compat_ptr(pad));
else
- err2 = put_compat_semid_ds(&s64, compat_ptr(pad));
+ err2 = put_compat_semid_ds(&sem64, compat_ptr(pad));
if (err2)
err = -EFAULT;
break;
case IPC_SET:
if (version == IPC_64)
- err = get_compat_semid64_ds(&s64, compat_ptr(pad));
+ err = get_compat_semid64_ds(&sem64, compat_ptr(pad));
else
- err = get_compat_semid_ds(&s64, compat_ptr(pad));
+ err = get_compat_semid_ds(&sem64, compat_ptr(pad));
- up64 = compat_alloc_user_space(sizeof(s64));
- if (copy_to_user(up64, &s64, sizeof(s64)))
+ up64 = compat_alloc_user_space(sizeof(sem64));
+ if (copy_to_user(up64, &sem64, sizeof(sem64)))
err = -EFAULT;
if (err)
break;
@@ -561,12 +561,12 @@ COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
return (long)ret;
}
-static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
+static inline int get_compat_shmid64_ds(struct shmid64_ds *sem64,
struct compat_shmid64_ds __user *up64)
{
if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
return -EFAULT;
- return __get_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
+ return __get_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
}
static inline int get_compat_shmid_ds(struct shmid64_ds *s,
@@ -577,21 +577,21 @@ static inline int get_compat_shmid_ds(struct shmid64_ds *s,
return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
}
-static inline int put_compat_shmid64_ds(struct shmid64_ds *s64,
+static inline int put_compat_shmid64_ds(struct shmid64_ds *sem64,
struct compat_shmid64_ds __user *up64)
{
int err;
if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
return -EFAULT;
- err = __put_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
- err |= __put_user(s64->shm_atime, &up64->shm_atime);
- err |= __put_user(s64->shm_dtime, &up64->shm_dtime);
- err |= __put_user(s64->shm_ctime, &up64->shm_ctime);
- err |= __put_user(s64->shm_segsz, &up64->shm_segsz);
- err |= __put_user(s64->shm_nattch, &up64->shm_nattch);
- err |= __put_user(s64->shm_cpid, &up64->shm_cpid);
- err |= __put_user(s64->shm_lpid, &up64->shm_lpid);
+ err = __put_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
+ err |= __put_user(sem64->shm_atime, &up64->shm_atime);
+ err |= __put_user(sem64->shm_dtime, &up64->shm_dtime);
+ err |= __put_user(sem64->shm_ctime, &up64->shm_ctime);
+ err |= __put_user(sem64->shm_segsz, &up64->shm_segsz);
+ err |= __put_user(sem64->shm_nattch, &up64->shm_nattch);
+ err |= __put_user(sem64->shm_cpid, &up64->shm_cpid);
+ err |= __put_user(sem64->shm_lpid, &up64->shm_lpid);
return err;
}
@@ -668,12 +668,12 @@ static inline int put_compat_shm_info(struct shm_info __user *ip,
COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
{
void __user *p;
- struct shmid64_ds s64;
+ struct shmid64_ds sem64;
struct shminfo64 smi;
int err, err2;
int version = compat_ipc_parse_version(&second);
- memset(&s64, 0, sizeof(s64));
+ memset(&sem64, 0, sizeof(sem64));
switch (second & (~IPC_64)) {
case IPC_RMID:
@@ -700,14 +700,14 @@ COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
case IPC_SET:
if (version == IPC_64)
- err = get_compat_shmid64_ds(&s64, uptr);
+ err = get_compat_shmid64_ds(&sem64, uptr);
else
- err = get_compat_shmid_ds(&s64, uptr);
+ err = get_compat_shmid_ds(&sem64, uptr);
if (err)
break;
- p = compat_alloc_user_space(sizeof(s64));
- if (copy_to_user(p, &s64, sizeof(s64)))
+ p = compat_alloc_user_space(sizeof(sem64));
+ if (copy_to_user(p, &sem64, sizeof(sem64)))
err = -EFAULT;
else
err = sys_shmctl(first, second, p);
@@ -715,16 +715,16 @@ COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
case IPC_STAT:
case SHM_STAT:
- p = compat_alloc_user_space(sizeof(s64));
+ p = compat_alloc_user_space(sizeof(sem64));
err = sys_shmctl(first, second, p);
if (err < 0)
break;
- if (copy_from_user(&s64, p, sizeof(s64)))
+ if (copy_from_user(&sem64, p, sizeof(sem64)))
err2 = -EFAULT;
else if (version == IPC_64)
- err2 = put_compat_shmid64_ds(&s64, uptr);
+ err2 = put_compat_shmid64_ds(&sem64, uptr);
else
- err2 = put_compat_shmid_ds(&s64, uptr);
+ err2 = put_compat_shmid_ds(&sem64, uptr);
if (err2)
err = -EFAULT;
break;
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index c3f0326e98db..e8075b247497 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -123,7 +123,6 @@ static int proc_ipcauto_dointvec_minmax(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table ipc_table;
- size_t lenp_bef = *lenp;
int oldval;
int rc;
@@ -133,7 +132,7 @@ static int proc_ipcauto_dointvec_minmax(struct ctl_table *table, int write,
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
- if (write && !rc && lenp_bef == *lenp) {
+ if (write && !rc) {
int newval = *((int *)(ipc_table.data));
/*
* The file "auto_msgmni" has correctly been set.
diff --git a/ipc/shm.c b/ipc/shm.c
index 7fc9f9f3a26b..01454796ba3c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1172,13 +1172,6 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
if (find_vma_intersection(current->mm, addr, addr + size))
goto invalid;
- /*
- * If shm segment goes below stack, make sure there is some
- * space left for the stack to grow (at least 4 pages).
- */
- if (addr < current->mm->start_stack &&
- addr > current->mm->start_stack - size - PAGE_SIZE * 5)
- goto invalid;
}
addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate);
diff --git a/ipc/util.c b/ipc/util.c
index d73b7af581e2..88adc329888c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -892,28 +892,16 @@ static const struct seq_operations sysvipc_proc_seqops = {
static int sysvipc_proc_open(struct inode *inode, struct file *file)
{
- int ret;
- struct seq_file *seq;
struct ipc_proc_iter *iter;
- ret = -ENOMEM;
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ iter = __seq_open_private(file, &sysvipc_proc_seqops, sizeof(*iter));
if (!iter)
- goto out;
-
- ret = seq_open(file, &sysvipc_proc_seqops);
- if (ret) {
- kfree(iter);
- goto out;
- }
-
- seq = file->private_data;
- seq->private = iter;
+ return -ENOMEM;
iter->iface = PDE_DATA(inode);
iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);
-out:
- return ret;
+
+ return 0;
}
static int sysvipc_proc_release(struct inode *inode, struct file *file)
diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c
index 70a504601dc3..b20d544f20c2 100644
--- a/kernel/debug/kdb/kdb_bp.c
+++ b/kernel/debug/kdb/kdb_bp.c
@@ -52,11 +52,11 @@ static int kdb_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
bp->bph_length = 1;
if ((argc + 1) != nextarg) {
- if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0)
+ if (strncasecmp(argv[nextarg], "datar", sizeof("datar")) == 0)
bp->bp_type = BP_ACCESS_WATCHPOINT;
- else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0)
+ else if (strncasecmp(argv[nextarg], "dataw", sizeof("dataw")) == 0)
bp->bp_type = BP_WRITE_WATCHPOINT;
- else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0)
+ else if (strncasecmp(argv[nextarg], "inst", sizeof("inst")) == 0)
bp->bp_type = BP_HARDWARE_BREAKPOINT;
else
return KDB_ARGCOUNT;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index ae5167087845..5c5987f10819 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -565,19 +565,12 @@ static int kallsyms_open(struct inode *inode, struct file *file)
* using get_symbol_offset for every symbol.
*/
struct kallsym_iter *iter;
- int ret;
-
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
if (!iter)
return -ENOMEM;
reset_iter(iter, 0);
- ret = seq_open(file, &kallsyms_op);
- if (ret == 0)
- ((struct seq_file *)file->private_data)->private = iter;
- else
- kfree(iter);
- return ret;
+ return 0;
}
#ifdef CONFIG_KGDB_KDB
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 2bee072268d9..2abf9f6e9a61 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1759,7 +1759,6 @@ static __initdata char *suffix_tbl[] = {
*/
static int __init parse_crashkernel_suffix(char *cmdline,
unsigned long long *crash_size,
- unsigned long long *crash_base,
const char *suffix)
{
char *cur = cmdline;
@@ -1848,7 +1847,7 @@ static int __init __parse_crashkernel(char *cmdline,
if (suffix)
return parse_crashkernel_suffix(ck_cmdline, crash_size,
- crash_base, suffix);
+ suffix);
/*
* if the commandline contains a ':', then that's the extended
* syntax -- if not, it must be the classic syntax
@@ -2016,22 +2015,6 @@ static int __init crash_save_vmcoreinfo_init(void)
subsys_initcall(crash_save_vmcoreinfo_init);
#ifdef CONFIG_KEXEC_FILE
-static int __kexec_add_segment(struct kimage *image, char *buf,
- unsigned long bufsz, unsigned long mem,
- unsigned long memsz)
-{
- struct kexec_segment *ksegment;
-
- ksegment = &image->segment[image->nr_segments];
- ksegment->kbuf = buf;
- ksegment->bufsz = bufsz;
- ksegment->mem = mem;
- ksegment->memsz = memsz;
- image->nr_segments++;
-
- return 0;
-}
-
static int locate_mem_hole_top_down(unsigned long start, unsigned long end,
struct kexec_buf *kbuf)
{
@@ -2064,8 +2047,7 @@ static int locate_mem_hole_top_down(unsigned long start, unsigned long end,
} while (1);
/* If we are here, we found a suitable memory range */
- __kexec_add_segment(image, kbuf->buffer, kbuf->bufsz, temp_start,
- kbuf->memsz);
+ kbuf->mem = temp_start;
/* Success, stop navigating through remaining System RAM ranges */
return 1;
@@ -2099,8 +2081,7 @@ static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,
} while (1);
/* If we are here, we found a suitable memory range */
- __kexec_add_segment(image, kbuf->buffer, kbuf->bufsz, temp_start,
- kbuf->memsz);
+ kbuf->mem = temp_start;
/* Success, stop navigating through remaining System RAM ranges */
return 1;
@@ -2187,7 +2168,12 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
}
/* Found a suitable memory range */
- ksegment = &image->segment[image->nr_segments - 1];
+ ksegment = &image->segment[image->nr_segments];
+ ksegment->kbuf = kbuf->buffer;
+ ksegment->bufsz = kbuf->bufsz;
+ ksegment->mem = kbuf->mem;
+ ksegment->memsz = kbuf->memsz;
+ image->nr_segments++;
*load_addr = ksegment->mem;
return 0;
}
diff --git a/kernel/params.c b/kernel/params.c
index 041b5899d5e2..db97b791390f 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -513,8 +514,6 @@ EXPORT_SYMBOL(param_ops_string);
#define to_module_attr(n) container_of(n, struct module_attribute, attr)
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
-extern struct kernel_param __start___param[], __stop___param[];
-
struct param_attribute
{
struct module_attribute mattr;
@@ -774,7 +773,7 @@ static struct module_kobject * __init locate_module_kobject(const char *name)
}
static void __init kernel_add_sysfs_param(const char *name,
- struct kernel_param *kparam,
+ const struct kernel_param *kparam,
unsigned int name_skip)
{
struct module_kobject *mk;
@@ -809,7 +808,7 @@ static void __init kernel_add_sysfs_param(const char *name,
*/
static void __init param_sysfs_builtin(void)
{
- struct kernel_param *kp;
+ const struct kernel_param *kp;
unsigned int name_len;
char modname[MODULE_NAME_LEN];
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 7a6e69441f75..e3962d63e368 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -267,7 +267,6 @@ static u32 clear_idx;
#define LOG_ALIGN __alignof__(struct printk_log)
#endif
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
-#define __LOG_CPU_MAX_BUF_LEN (1 << CONFIG_LOG_CPU_MAX_BUF_SHIFT)
static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
static char *log_buf = __log_buf;
static u32 log_buf_len = __LOG_BUF_LEN;
@@ -852,6 +851,9 @@ static int __init log_buf_len_setup(char *str)
}
early_param("log_buf_len", log_buf_len_setup);
+#ifdef CONFIG_SMP
+#define __LOG_CPU_MAX_BUF_LEN (1 << CONFIG_LOG_CPU_MAX_BUF_SHIFT)
+
static void __init log_buf_add_cpu(void)
{
unsigned int cpu_extra;
@@ -878,6 +880,9 @@ static void __init log_buf_add_cpu(void)
log_buf_len_update(cpu_extra + __LOG_BUF_LEN);
}
+#else /* !CONFIG_SMP */
+static inline void log_buf_add_cpu(void) {}
+#endif /* CONFIG_SMP */
void __init setup_log_buf(int early)
{
@@ -1674,12 +1679,7 @@ asmlinkage int vprintk_emit(int facility, int level,
* The printf needs to come first; we need the syslog
* prefix which might be passed-in as a parameter.
*/
- if (in_sched)
- text_len = scnprintf(text, sizeof(textbuf),
- KERN_WARNING "[sched_delayed] ");
-
- text_len += vscnprintf(text + text_len,
- sizeof(textbuf) - text_len, fmt, args);
+ text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
/* mark and strip a trailing newline */
if (text_len && text[text_len-1] == '\n') {
diff --git a/kernel/resource.c b/kernel/resource.c
index 46322019ab7d..0bcebffc4e77 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -491,6 +491,42 @@ int __weak page_is_ram(unsigned long pfn)
}
EXPORT_SYMBOL_GPL(page_is_ram);
+/*
+ * Search for a resouce entry that fully contains the specified region.
+ * If found, return 1 if it is RAM, 0 if not.
+ * If not found, or region is not fully contained, return -1
+ *
+ * Used by the ioremap functions to ensure the user is not remapping RAM and is
+ * a vast speed up over walking through the resource table page by page.
+ */
+int region_is_ram(resource_size_t start, unsigned long size)
+{
+ struct resource *p;
+ resource_size_t end = start + size - 1;
+ int flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ const char *name = "System RAM";
+ int ret = -1;
+
+ read_lock(&resource_lock);
+ for (p = iomem_resource.child; p ; p = p->sibling) {
+ if (end < p->start)
+ continue;
+
+ if (p->start <= start && end <= p->end) {
+ /* resource fully contains region */
+ if ((p->flags != flags) || strcmp(p->name, name))
+ ret = 0;
+ else
+ ret = 1;
+ break;
+ }
+ if (p->end < start)
+ break; /* not found */
+ }
+ read_unlock(&resource_lock);
+ return ret;
+}
+
void __weak arch_remove_reservations(struct resource *avail)
{
}
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index ff7fd80bef99..49e9537f3673 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -59,6 +59,25 @@ static unsigned long soft_lockup_nmi_warn;
static int hardlockup_panic =
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
+static bool hardlockup_detector_enabled = true;
+/*
+ * We may not want to enable hard lockup detection by default in all cases,
+ * for example when running the kernel as a guest on a hypervisor. In these
+ * cases this function can be called to disable hard lockup detection. This
+ * function should only be executed once by the boot processor before the
+ * kernel command line parameters are parsed, because otherwise it is not
+ * possible to override this in hardlockup_panic_setup().
+ */
+void watchdog_enable_hardlockup_detector(bool val)
+{
+ hardlockup_detector_enabled = val;
+}
+
+bool watchdog_hardlockup_detector_is_enabled(void)
+{
+ return hardlockup_detector_enabled;
+}
+
static int __init hardlockup_panic_setup(char *str)
{
if (!strncmp(str, "panic", 5))
@@ -67,6 +86,14 @@ static int __init hardlockup_panic_setup(char *str)
hardlockup_panic = 0;
else if (!strncmp(str, "0", 1))
watchdog_user_enabled = 0;
+ else if (!strncmp(str, "1", 1) || !strncmp(str, "2", 1)) {
+ /*
+ * Setting 'nmi_watchdog=1' or 'nmi_watchdog=2' (legacy option)
+ * has the same effect.
+ */
+ watchdog_user_enabled = 1;
+ watchdog_enable_hardlockup_detector(true);
+ }
return 1;
}
__setup("nmi_watchdog=", hardlockup_panic_setup);
@@ -465,6 +492,15 @@ static int watchdog_nmi_enable(unsigned int cpu)
struct perf_event_attr *wd_attr;
struct perf_event *event = per_cpu(watchdog_ev, cpu);
+ /*
+ * Some kernels need to default hard lockup detection to
+ * 'disabled', for example a guest on a hypervisor.
+ */
+ if (!watchdog_hardlockup_detector_is_enabled()) {
+ event = ERR_PTR(-ENOENT);
+ goto handle_err;
+ }
+
/* is it already setup and enabled? */
if (event && event->state > PERF_EVENT_STATE_OFF)
goto out;
@@ -479,6 +515,7 @@ static int watchdog_nmi_enable(unsigned int cpu)
/* Try to register using hardware perf events */
event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
+handle_err:
/* save cpu0 error for future comparision */
if (cpu == 0 && IS_ERR(event))
cpu0_err = PTR_ERR(event);
@@ -624,11 +661,13 @@ int proc_dowatchdog(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int err, old_thresh, old_enabled;
+ bool old_hardlockup;
static DEFINE_MUTEX(watchdog_proc_mutex);
mutex_lock(&watchdog_proc_mutex);
old_thresh = ACCESS_ONCE(watchdog_thresh);
old_enabled = ACCESS_ONCE(watchdog_user_enabled);
+ old_hardlockup = watchdog_hardlockup_detector_is_enabled();
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (err || !write)
@@ -640,15 +679,22 @@ int proc_dowatchdog(struct ctl_table *table, int write,
* disabled. The 'watchdog_running' variable check in
* watchdog_*_all_cpus() function takes care of this.
*/
- if (watchdog_user_enabled && watchdog_thresh)
+ if (watchdog_user_enabled && watchdog_thresh) {
+ /*
+ * Prevent a change in watchdog_thresh accidentally overriding
+ * the enablement of the hardlockup detector.
+ */
+ if (watchdog_user_enabled != old_enabled)
+ watchdog_enable_hardlockup_detector(true);
err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh);
- else
+ } else
watchdog_disable_all_cpus();
/* Restore old values on failure */
if (err) {
watchdog_thresh = old_thresh;
watchdog_user_enabled = old_enabled;
+ watchdog_enable_hardlockup_detector(old_hardlockup);
}
out:
mutex_unlock(&watchdog_proc_mutex);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index e7ad58c5fbeb..4e35a5d767ed 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1648,7 +1648,7 @@ config DMA_API_DEBUG
If unsure, say N.
-config TEST_MODULE
+config TEST_LKM
tristate "Test module loading with 'hello world' module"
default n
depends on m
diff --git a/lib/Makefile b/lib/Makefile
index d6b4bc496408..7512dc978f18 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o timerqueue.o\
idr.o int_sqrt.o extable.o \
sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
- proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
+ proportions.o flex_proportions.o ratelimit.o show_mem.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
earlycpio.o
@@ -31,7 +31,7 @@ obj-y += string_helpers.o
obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
obj-y += kstrtox.o
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
-obj-$(CONFIG_TEST_MODULE) += test_module.o
+obj-$(CONFIG_TEST_LKM) += test_module.o
obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
obj-$(CONFIG_TEST_BPF) += test_bpf.o
obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 31fe79e31ab8..dfba05521748 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -819,22 +819,9 @@ static const struct seq_operations ddebug_proc_seqops = {
*/
static int ddebug_proc_open(struct inode *inode, struct file *file)
{
- struct ddebug_iter *iter;
- int err;
-
vpr_info("called\n");
-
- iter = kzalloc(sizeof(*iter), GFP_KERNEL);
- if (iter == NULL)
- return -ENOMEM;
-
- err = seq_open(file, &ddebug_proc_seqops);
- if (err) {
- kfree(iter);
- return err;
- }
- ((struct seq_file *)file->private_data)->private = iter;
- return 0;
+ return seq_open_private(file, &ddebug_proc_seqops,
+ sizeof(struct ddebug_iter));
}
static const struct file_operations ddebug_proc_fops = {
diff --git a/lib/prio_heap.c b/lib/prio_heap.c
deleted file mode 100644
index a7af6f85eca8..000000000000
--- a/lib/prio_heap.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Simple insertion-only static-sized priority heap containing
- * pointers, based on CLR, chapter 7
- */
-
-#include <linux/slab.h>
-#include <linux/prio_heap.h>
-
-int heap_init(struct ptr_heap *heap, size_t size, gfp_t gfp_mask,
- int (*gt)(void *, void *))
-{
- heap->ptrs = kmalloc(size, gfp_mask);
- if (!heap->ptrs)
- return -ENOMEM;
- heap->size = 0;
- heap->max = size / sizeof(void *);
- heap->gt = gt;
- return 0;
-}
-
-void heap_free(struct ptr_heap *heap)
-{
- kfree(heap->ptrs);
-}
-
-void *heap_insert(struct ptr_heap *heap, void *p)
-{
- void *res;
- void **ptrs = heap->ptrs;
- int pos;
-
- if (heap->size < heap->max) {
- /* Heap insertion */
- pos = heap->size++;
- while (pos > 0 && heap->gt(p, ptrs[(pos-1)/2])) {
- ptrs[pos] = ptrs[(pos-1)/2];
- pos = (pos-1)/2;
- }
- ptrs[pos] = p;
- return NULL;
- }
-
- /* The heap is full, so something will have to be dropped */
-
- /* If the new pointer is greater than the current max, drop it */
- if (heap->gt(p, ptrs[0]))
- return p;
-
- /* Replace the current max and heapify */
- res = ptrs[0];
- ptrs[0] = p;
- pos = 0;
-
- while (1) {
- int left = 2 * pos + 1;
- int right = 2 * pos + 2;
- int largest = pos;
- if (left < heap->size && heap->gt(ptrs[left], p))
- largest = left;
- if (right < heap->size && heap->gt(ptrs[right], ptrs[largest]))
- largest = right;
- if (largest == pos)
- break;
- /* Push p down the heap one level and bump one up */
- ptrs[pos] = ptrs[largest];
- ptrs[largest] = p;
- pos = largest;
- }
- return res;
-}
diff --git a/lib/string.c b/lib/string.c
index f3c6ff596414..2fc20aa06f84 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -27,14 +27,14 @@
#include <linux/bug.h>
#include <linux/errno.h>
-#ifndef __HAVE_ARCH_STRNICMP
+#ifndef __HAVE_ARCH_STRNCASECMP
/**
- * strnicmp - Case insensitive, length-limited string comparison
+ * strncasecmp - Case insensitive, length-limited string comparison
* @s1: One string
* @s2: The other string
* @len: the maximum number of characters to compare
*/
-int strnicmp(const char *s1, const char *s2, size_t len)
+int strncasecmp(const char *s1, const char *s2, size_t len)
{
/* Yes, Virginia, it had better be unsigned */
unsigned char c1, c2;
@@ -56,6 +56,14 @@ int strnicmp(const char *s1, const char *s2, size_t len)
} while (--len);
return (int)c1 - (int)c2;
}
+EXPORT_SYMBOL(strncasecmp);
+#endif
+#ifndef __HAVE_ARCH_STRNICMP
+#undef strnicmp
+int strnicmp(const char *s1, const char *s2, size_t len)
+{
+ return strncasecmp(s1, s2, len);
+}
EXPORT_SYMBOL(strnicmp);
#endif
@@ -73,20 +81,6 @@ int strcasecmp(const char *s1, const char *s2)
EXPORT_SYMBOL(strcasecmp);
#endif
-#ifndef __HAVE_ARCH_STRNCASECMP
-int strncasecmp(const char *s1, const char *s2, size_t n)
-{
- int c1, c2;
-
- do {
- c1 = tolower(*s1++);
- c2 = tolower(*s2++);
- } while ((--n > 0) && c1 == c2 && c1 != 0);
- return c1 - c2;
-}
-EXPORT_SYMBOL(strncasecmp);
-#endif
-
#ifndef __HAVE_ARCH_STRCPY
/**
* strcpy - Copy a %NUL terminated string
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 29033f319aea..58b78ba57439 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -8,6 +8,8 @@
#include <linux/math64.h>
#include <linux/export.h>
#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/string.h>
#include <linux/string_helpers.h>
/**
@@ -168,6 +170,44 @@ static bool unescape_special(char **src, char **dst)
return true;
}
+/**
+ * string_unescape - unquote characters in the given string
+ * @src: source buffer (escaped)
+ * @dst: destination buffer (unescaped)
+ * @size: size of the destination buffer (0 to unlimit)
+ * @flags: combination of the flags (bitwise OR):
+ * %UNESCAPE_SPACE:
+ * '\f' - form feed
+ * '\n' - new line
+ * '\r' - carriage return
+ * '\t' - horizontal tab
+ * '\v' - vertical tab
+ * %UNESCAPE_OCTAL:
+ * '\NNN' - byte with octal value NNN (1 to 3 digits)
+ * %UNESCAPE_HEX:
+ * '\xHH' - byte with hexadecimal value HH (1 to 2 digits)
+ * %UNESCAPE_SPECIAL:
+ * '\"' - double quote
+ * '\\' - backslash
+ * '\a' - alert (BEL)
+ * '\e' - escape
+ * %UNESCAPE_ANY:
+ * all previous together
+ *
+ * Description:
+ * The function unquotes characters in the given string.
+ *
+ * Because the size of the output will be the same as or less than the size of
+ * the input, the transformation may be performed in place.
+ *
+ * Caller must provide valid source and destination pointers. Be aware that
+ * destination buffer will always be NULL-terminated. Source string must be
+ * NULL-terminated as well.
+ *
+ * Return:
+ * The amount of the characters processed to the destination buffer excluding
+ * trailing '\0' is returned.
+ */
int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
{
char *out = dst;
@@ -202,3 +242,275 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
return out - dst;
}
EXPORT_SYMBOL(string_unescape);
+
+static int escape_passthrough(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+
+ if (*osz < 1)
+ return -ENOMEM;
+
+ *out++ = c;
+
+ *dst = out;
+ *osz -= 1;
+
+ return 1;
+}
+
+static int escape_space(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+ unsigned char to;
+
+ if (*osz < 2)
+ return -ENOMEM;
+
+ switch (c) {
+ case '\n':
+ to = 'n';
+ break;
+ case '\r':
+ to = 'r';
+ break;
+ case '\t':
+ to = 't';
+ break;
+ case '\v':
+ to = 'v';
+ break;
+ case '\f':
+ to = 'f';
+ break;
+ default:
+ return 0;
+ }
+
+ *out++ = '\\';
+ *out++ = to;
+
+ *dst = out;
+ *osz -= 2;
+
+ return 1;
+}
+
+static int escape_special(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+ unsigned char to;
+
+ if (*osz < 2)
+ return -ENOMEM;
+
+ switch (c) {
+ case '\\':
+ to = '\\';
+ break;
+ case '\a':
+ to = 'a';
+ break;
+ case '\e':
+ to = 'e';
+ break;
+ default:
+ return 0;
+ }
+
+ *out++ = '\\';
+ *out++ = to;
+
+ *dst = out;
+ *osz -= 2;
+
+ return 1;
+}
+
+static int escape_null(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+
+ if (*osz < 2)
+ return -ENOMEM;
+
+ if (c)
+ return 0;
+
+ *out++ = '\\';
+ *out++ = '0';
+
+ *dst = out;
+ *osz -= 2;
+
+ return 1;
+}
+
+static int escape_octal(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+
+ if (*osz < 4)
+ return -ENOMEM;
+
+ *out++ = '\\';
+ *out++ = ((c >> 6) & 0x07) + '0';
+ *out++ = ((c >> 3) & 0x07) + '0';
+ *out++ = ((c >> 0) & 0x07) + '0';
+
+ *dst = out;
+ *osz -= 4;
+
+ return 1;
+}
+
+static int escape_hex(unsigned char c, char **dst, size_t *osz)
+{
+ char *out = *dst;
+
+ if (*osz < 4)
+ return -ENOMEM;
+
+ *out++ = '\\';
+ *out++ = 'x';
+ *out++ = hex_asc_hi(c);
+ *out++ = hex_asc_lo(c);
+
+ *dst = out;
+ *osz -= 4;
+
+ return 1;
+}
+
+/**
+ * string_escape_mem - quote characters in the given memory buffer
+ * @src: source buffer (unescaped)
+ * @isz: source buffer size
+ * @dst: destination buffer (escaped)
+ * @osz: destination buffer size
+ * @flags: combination of the flags (bitwise OR):
+ * %ESCAPE_SPACE:
+ * '\f' - form feed
+ * '\n' - new line
+ * '\r' - carriage return
+ * '\t' - horizontal tab
+ * '\v' - vertical tab
+ * %ESCAPE_SPECIAL:
+ * '\\' - backslash
+ * '\a' - alert (BEL)
+ * '\e' - escape
+ * %ESCAPE_NULL:
+ * '\0' - null
+ * %ESCAPE_OCTAL:
+ * '\NNN' - byte with octal value NNN (3 digits)
+ * %ESCAPE_ANY:
+ * all previous together
+ * %ESCAPE_NP:
+ * escape only non-printable characters (checked by isprint)
+ * %ESCAPE_ANY_NP:
+ * all previous together
+ * %ESCAPE_HEX:
+ * '\xHH' - byte with hexadecimal value HH (2 digits)
+ * @esc: NULL-terminated string of characters any of which, if found in
+ * the source, has to be escaped
+ *
+ * Description:
+ * The process of escaping byte buffer includes several parts. They are applied
+ * in the following sequence.
+ * 1. The character is matched to the printable class, if asked, and in
+ * case of match it passes through to the output.
+ * 2. The character is not matched to the one from @esc string and thus
+ * must go as is to the output.
+ * 3. The character is checked if it falls into the class given by @flags.
+ * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
+ * character. Note that they actually can't go together, otherwise
+ * %ESCAPE_HEX will be ignored.
+ *
+ * Caller must provide valid source and destination pointers. Be aware that
+ * destination buffer will not be NULL-terminated, thus caller have to append
+ * it if needs.
+ *
+ * Return:
+ * The amount of the characters processed to the destination buffer, or
+ * %-ENOMEM if the size of buffer is not enough to put an escaped character is
+ * returned.
+ *
+ * Even in the case of error @dst pointer will be updated to point to the byte
+ * after the last processed character.
+ */
+int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
+ unsigned int flags, const char *esc)
+{
+ char *out = *dst, *p = out;
+ bool is_dict = esc && *esc;
+ int ret = 0;
+
+ while (isz--) {
+ unsigned char c = *src++;
+
+ /*
+ * Apply rules in the following sequence:
+ * - the character is printable, when @flags has
+ * %ESCAPE_NP bit set
+ * - the @esc string is supplied and does not contain a
+ * character under question
+ * - the character doesn't fall into a class of symbols
+ * defined by given @flags
+ * In these cases we just pass through a character to the
+ * output buffer.
+ */
+ if ((flags & ESCAPE_NP && isprint(c)) ||
+ (is_dict && !strchr(esc, c))) {
+ /* do nothing */
+ } else {
+ if (flags & ESCAPE_SPACE) {
+ ret = escape_space(c, &p, &osz);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ continue;
+ }
+
+ if (flags & ESCAPE_SPECIAL) {
+ ret = escape_special(c, &p, &osz);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ continue;
+ }
+
+ if (flags & ESCAPE_NULL) {
+ ret = escape_null(c, &p, &osz);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ continue;
+ }
+
+ /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
+ if (flags & ESCAPE_OCTAL) {
+ ret = escape_octal(c, &p, &osz);
+ if (ret < 0)
+ break;
+ continue;
+ }
+ if (flags & ESCAPE_HEX) {
+ ret = escape_hex(c, &p, &osz);
+ if (ret < 0)
+ break;
+ continue;
+ }
+ }
+
+ ret = escape_passthrough(c, &p, &osz);
+ if (ret < 0)
+ break;
+ }
+
+ *dst = p;
+
+ if (ret < 0)
+ return ret;
+
+ return p - out;
+}
+EXPORT_SYMBOL(string_escape_mem);
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c
index 6ac48de04c0e..ab0d30e1e18f 100644
--- a/lib/test-string_helpers.c
+++ b/lib/test-string_helpers.c
@@ -5,11 +5,32 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
+static __init bool test_string_check_buf(const char *name, unsigned int flags,
+ char *in, size_t p,
+ char *out_real, size_t q_real,
+ char *out_test, size_t q_test)
+{
+ if (q_real == q_test && !memcmp(out_test, out_real, q_test))
+ return true;
+
+ pr_warn("Test '%s' failed: flags = %u\n", name, flags);
+
+ print_hex_dump(KERN_WARNING, "Input: ", DUMP_PREFIX_NONE, 16, 1,
+ in, p, true);
+ print_hex_dump(KERN_WARNING, "Expected: ", DUMP_PREFIX_NONE, 16, 1,
+ out_test, q_test, true);
+ print_hex_dump(KERN_WARNING, "Got: ", DUMP_PREFIX_NONE, 16, 1,
+ out_real, q_real, true);
+
+ return false;
+}
+
struct test_string {
const char *in;
const char *out;
@@ -39,12 +60,17 @@ static const struct test_string strings[] __initconst = {
},
};
-static void __init test_string_unescape(unsigned int flags, bool inplace)
+static void __init test_string_unescape(const char *name, unsigned int flags,
+ bool inplace)
{
- char in[256];
- char out_test[256];
- char out_real[256];
- int i, p = 0, q_test = 0, q_real = sizeof(out_real);
+ int q_real = 256;
+ char *in = kmalloc(q_real, GFP_KERNEL);
+ char *out_test = kmalloc(q_real, GFP_KERNEL);
+ char *out_real = kmalloc(q_real, GFP_KERNEL);
+ int i, p = 0, q_test = 0;
+
+ if (!in || !out_test || !out_real)
+ goto out;
for (i = 0; i < ARRAY_SIZE(strings); i++) {
const char *s = strings[i].in;
@@ -77,15 +103,225 @@ static void __init test_string_unescape(unsigned int flags, bool inplace)
q_real = string_unescape(in, out_real, q_real, flags);
}
- if (q_real != q_test || memcmp(out_test, out_real, q_test)) {
- pr_warn("Test failed: flags = %u\n", flags);
- print_hex_dump(KERN_WARNING, "Input: ",
- DUMP_PREFIX_NONE, 16, 1, in, p - 1, true);
- print_hex_dump(KERN_WARNING, "Expected: ",
- DUMP_PREFIX_NONE, 16, 1, out_test, q_test, true);
- print_hex_dump(KERN_WARNING, "Got: ",
- DUMP_PREFIX_NONE, 16, 1, out_real, q_real, true);
+ test_string_check_buf(name, flags, in, p - 1, out_real, q_real,
+ out_test, q_test);
+out:
+ kfree(out_real);
+ kfree(out_test);
+ kfree(in);
+}
+
+struct test_string_1 {
+ const char *out;
+ unsigned int flags;
+};
+
+#define TEST_STRING_2_MAX_S1 32
+struct test_string_2 {
+ const char *in;
+ struct test_string_1 s1[TEST_STRING_2_MAX_S1];
+};
+
+#define TEST_STRING_2_DICT_0 NULL
+static const struct test_string_2 escape0[] __initconst = {{
+ .in = "\f\\ \n\r\t\v",
+ .s1 = {{
+ .out = "\\f\\ \\n\\r\\t\\v",
+ .flags = ESCAPE_SPACE,
+ },{
+ .out = "\\f\\134\\040\\n\\r\\t\\v",
+ .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
+ },{
+ .out = "\\f\\x5c\\x20\\n\\r\\t\\v",
+ .flags = ESCAPE_SPACE | ESCAPE_HEX,
+ },{
+ /* terminator */
+ }},
+},{
+ .in = "\\h\\\"\a\e\\",
+ .s1 = {{
+ .out = "\\\\h\\\\\"\\a\\e\\\\",
+ .flags = ESCAPE_SPECIAL,
+ },{
+ .out = "\\\\\\150\\\\\\042\\a\\e\\\\",
+ .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
+ },{
+ .out = "\\\\\\x68\\\\\\x22\\a\\e\\\\",
+ .flags = ESCAPE_SPECIAL | ESCAPE_HEX,
+ },{
+ /* terminator */
+ }},
+},{
+ .in = "\eb \\C\007\"\x90\r]",
+ .s1 = {{
+ .out = "\eb \\C\007\"\x90\\r]",
+ .flags = ESCAPE_SPACE,
+ },{
+ .out = "\\eb \\\\C\\a\"\x90\r]",
+ .flags = ESCAPE_SPECIAL,
+ },{
+ .out = "\\eb \\\\C\\a\"\x90\\r]",
+ .flags = ESCAPE_SPACE | ESCAPE_SPECIAL,
+ },{
+ .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135",
+ .flags = ESCAPE_OCTAL,
+ },{
+ .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135",
+ .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
+ },{
+ .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\015\\135",
+ .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
+ },{
+ .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\r\\135",
+ .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL,
+ },{
+ .out = "\eb \\C\007\"\x90\r]",
+ .flags = ESCAPE_NP,
+ },{
+ .out = "\eb \\C\007\"\x90\\r]",
+ .flags = ESCAPE_SPACE | ESCAPE_NP,
+ },{
+ .out = "\\eb \\C\\a\"\x90\r]",
+ .flags = ESCAPE_SPECIAL | ESCAPE_NP,
+ },{
+ .out = "\\eb \\C\\a\"\x90\\r]",
+ .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NP,
+ },{
+ .out = "\\033b \\C\\007\"\\220\\015]",
+ .flags = ESCAPE_OCTAL | ESCAPE_NP,
+ },{
+ .out = "\\033b \\C\\007\"\\220\\r]",
+ .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NP,
+ },{
+ .out = "\\eb \\C\\a\"\\220\\r]",
+ .flags = ESCAPE_SPECIAL | ESCAPE_SPACE | ESCAPE_OCTAL |
+ ESCAPE_NP,
+ },{
+ .out = "\\x1bb \\C\\x07\"\\x90\\x0d]",
+ .flags = ESCAPE_NP | ESCAPE_HEX,
+ },{
+ /* terminator */
+ }},
+},{
+ /* terminator */
+}};
+
+#define TEST_STRING_2_DICT_1 "b\\ \t\r"
+static const struct test_string_2 escape1[] __initconst = {{
+ .in = "\f\\ \n\r\t\v",
+ .s1 = {{
+ .out = "\f\\134\\040\n\\015\\011\v",
+ .flags = ESCAPE_OCTAL,
+ },{
+ .out = "\f\\x5c\\x20\n\\x0d\\x09\v",
+ .flags = ESCAPE_HEX,
+ },{
+ /* terminator */
+ }},
+},{
+ .in = "\\h\\\"\a\e\\",
+ .s1 = {{
+ .out = "\\134h\\134\"\a\e\\134",
+ .flags = ESCAPE_OCTAL,
+ },{
+ /* terminator */
+ }},
+},{
+ .in = "\eb \\C\007\"\x90\r]",
+ .s1 = {{
+ .out = "\e\\142\\040\\134C\007\"\x90\\015]",
+ .flags = ESCAPE_OCTAL,
+ },{
+ /* terminator */
+ }},
+},{
+ /* terminator */
+}};
+
+static __init const char *test_string_find_match(const struct test_string_2 *s2,
+ unsigned int flags)
+{
+ const struct test_string_1 *s1 = s2->s1;
+ unsigned int i;
+
+ if (!flags)
+ return s2->in;
+
+ /* Test cases are NULL-aware */
+ flags &= ~ESCAPE_NULL;
+
+ /* ESCAPE_OCTAL has a higher priority */
+ if (flags & ESCAPE_OCTAL)
+ flags &= ~ESCAPE_HEX;
+
+ for (i = 0; i < TEST_STRING_2_MAX_S1 && s1->out; i++, s1++)
+ if (s1->flags == flags)
+ return s1->out;
+ return NULL;
+}
+
+static __init void test_string_escape(const char *name,
+ const struct test_string_2 *s2,
+ unsigned int flags, const char *esc)
+{
+ int q_real = 512;
+ char *out_test = kmalloc(q_real, GFP_KERNEL);
+ char *out_real = kmalloc(q_real, GFP_KERNEL);
+ char *in = kmalloc(256, GFP_KERNEL);
+ char *buf = out_real;
+ int p = 0, q_test = 0;
+
+ if (!out_test || !out_real || !in)
+ goto out;
+
+ for (; s2->in; s2++) {
+ const char *out;
+ int len;
+
+ /* NULL injection */
+ if (flags & ESCAPE_NULL) {
+ in[p++] = '\0';
+ out_test[q_test++] = '\\';
+ out_test[q_test++] = '0';
+ }
+
+ /* Don't try strings that have no output */
+ out = test_string_find_match(s2, flags);
+ if (!out)
+ continue;
+
+ /* Copy string to in buffer */
+ len = strlen(s2->in);
+ memcpy(&in[p], s2->in, len);
+ p += len;
+
+ /* Copy expected result for given flags */
+ len = strlen(out);
+ memcpy(&out_test[q_test], out, len);
+ q_test += len;
}
+
+ q_real = string_escape_mem(in, p, &buf, q_real, flags, esc);
+
+ test_string_check_buf(name, flags, in, p, out_real, q_real, out_test,
+ q_test);
+out:
+ kfree(in);
+ kfree(out_real);
+ kfree(out_test);
+}
+
+static __init void test_string_escape_nomem(void)
+{
+ char *in = "\eb \\C\007\"\x90\r]";
+ char out[64], *buf = out;
+ int rc = -ENOMEM, ret;
+
+ ret = string_escape_str_any_np(in, &buf, strlen(in), NULL);
+ if (ret == rc)
+ return;
+
+ pr_err("Test 'escape nomem' failed: got %d instead of %d\n", ret, rc);
}
static int __init test_string_helpers_init(void)
@@ -94,8 +330,19 @@ static int __init test_string_helpers_init(void)
pr_info("Running tests...\n");
for (i = 0; i < UNESCAPE_ANY + 1; i++)
- test_string_unescape(i, false);
- test_string_unescape(get_random_int() % (UNESCAPE_ANY + 1), true);
+ test_string_unescape("unescape", i, false);
+ test_string_unescape("unescape inplace",
+ get_random_int() % (UNESCAPE_ANY + 1), true);
+
+ /* Without dictionary */
+ for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
+ test_string_escape("escape 0", escape0, i, TEST_STRING_2_DICT_0);
+
+ /* With dictionary */
+ for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
+ test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1);
+
+ test_string_escape_nomem();
return -EINVAL;
}
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 0c7e9ab2d88f..0b79908dfe89 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -249,9 +249,7 @@ EXPORT_SYMBOL(textsearch_find_continuous);
* @flags: search flags
*
* Looks up the search algorithm module and creates a new textsearch
- * configuration for the specified pattern. Upon completion all
- * necessary refcnts are held and the configuration must be put back
- * using textsearch_put() after usage.
+ * configuration for the specified pattern.
*
* Note: The format of the pattern may not be compatible between
* the various search algorithms.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index ba3cd0a35640..ec337f64f52d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -33,6 +33,7 @@
#include <asm/page.h> /* for PAGE_SIZE */
#include <asm/sections.h> /* for dereference_function_descriptor() */
+#include <linux/string_helpers.h>
#include "kstrtox.h"
/**
@@ -1101,6 +1102,62 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
}
static noinline_for_stack
+char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
+ const char *fmt)
+{
+ bool found = true;
+ int count = 1;
+ unsigned int flags = 0;
+ int len;
+
+ if (spec.field_width == 0)
+ return buf; /* nothing to print */
+
+ if (ZERO_OR_NULL_PTR(addr))
+ return string(buf, end, NULL, spec); /* NULL pointer */
+
+
+ do {
+ switch (fmt[count++]) {
+ case 'a':
+ flags |= ESCAPE_ANY;
+ break;
+ case 'c':
+ flags |= ESCAPE_SPECIAL;
+ break;
+ case 'h':
+ flags |= ESCAPE_HEX;
+ break;
+ case 'n':
+ flags |= ESCAPE_NULL;
+ break;
+ case 'o':
+ flags |= ESCAPE_OCTAL;
+ break;
+ case 'p':
+ flags |= ESCAPE_NP;
+ break;
+ case 's':
+ flags |= ESCAPE_SPACE;
+ break;
+ default:
+ found = false;
+ break;
+ }
+ } while (found);
+
+ if (!flags)
+ flags = ESCAPE_ANY_NP;
+
+ len = spec.field_width < 0 ? 1 : spec.field_width;
+
+ /* Ignore the error. We print as many characters as we can */
+ string_escape_mem(addr, len, &buf, end - buf, flags, NULL);
+
+ return buf;
+}
+
+static noinline_for_stack
char *uuid_string(char *buf, char *end, const u8 *addr,
struct printf_spec spec, const char *fmt)
{
@@ -1221,6 +1278,17 @@ int kptr_restrict __read_mostly;
* - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
* - 'I[6S]c' for IPv6 addresses printed as specified by
* http://tools.ietf.org/html/rfc5952
+ * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
+ * of the following flags (see string_escape_mem() for the
+ * details):
+ * a - ESCAPE_ANY
+ * c - ESCAPE_SPECIAL
+ * h - ESCAPE_HEX
+ * n - ESCAPE_NULL
+ * o - ESCAPE_OCTAL
+ * p - ESCAPE_NP
+ * s - ESCAPE_SPACE
+ * By default ESCAPE_ANY_NP is used.
* - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
* Options for %pU are:
@@ -1321,6 +1389,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
}}
}
break;
+ case 'E':
+ return escaped_string(buf, end, ptr, spec, fmt);
case 'U':
return uuid_string(buf, end, ptr, spec, fmt);
case 'V':
@@ -1633,6 +1703,7 @@ qualifier:
* %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
* %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
* case.
+ * %*pE[achnops] print an escaped buffer
* %*ph[CDN] a variable-length hex string with a separator (supports up to 64
* bytes of the input)
* %n is ignored
diff --git a/mm/cma.c b/mm/cma.c
index 474c644a0dc6..963bc4add9af 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -58,7 +58,9 @@ unsigned long cma_get_size(struct cma *cma)
static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order)
{
- return (1UL << (align_order >> cma->order_per_bit)) - 1;
+ if (align_order <= cma->order_per_bit)
+ return 0;
+ return (1UL << (align_order - cma->order_per_bit)) - 1;
}
static unsigned long cma_bitmap_maxno(struct cma *cma)
@@ -141,6 +143,54 @@ static int __init cma_init_reserved_areas(void)
core_initcall(cma_init_reserved_areas);
/**
+ * cma_init_reserved_mem() - create custom contiguous area from reserved memory
+ * @base: Base address of the reserved area
+ * @size: Size of the reserved area (in bytes),
+ * @order_per_bit: Order of pages represented by one bit on bitmap.
+ * @res_cma: Pointer to store the created cma region.
+ *
+ * This function creates custom contiguous area from already reserved memory.
+ */
+int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
+ int order_per_bit, struct cma **res_cma)
+{
+ struct cma *cma;
+ phys_addr_t alignment;
+
+ /* Sanity checks */
+ if (cma_area_count == ARRAY_SIZE(cma_areas)) {
+ pr_err("Not enough slots for CMA reserved regions!\n");
+ return -ENOSPC;
+ }
+
+ if (!size || !memblock_is_region_reserved(base, size))
+ return -EINVAL;
+
+ /* ensure minimal alignment requied by mm core */
+ alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+
+ /* alignment should be aligned with order_per_bit */
+ if (!IS_ALIGNED(alignment >> PAGE_SHIFT, 1 << order_per_bit))
+ return -EINVAL;
+
+ if (ALIGN(base, alignment) != base || ALIGN(size, alignment) != size)
+ return -EINVAL;
+
+ /*
+ * Each reserved area must be initialised later, when more kernel
+ * subsystems (like slab allocator) are available.
+ */
+ cma = &cma_areas[cma_area_count];
+ cma->base_pfn = PFN_DOWN(base);
+ cma->count = size >> PAGE_SHIFT;
+ cma->order_per_bit = order_per_bit;
+ *res_cma = cma;
+ cma_area_count++;
+
+ return 0;
+}
+
+/**
* cma_declare_contiguous() - reserve custom contiguous area
* @base: Base address of the reserved area optional, use 0 for any
* @size: Size of the reserved area (in bytes),
@@ -163,7 +213,6 @@ int __init cma_declare_contiguous(phys_addr_t base,
phys_addr_t alignment, unsigned int order_per_bit,
bool fixed, struct cma **res_cma)
{
- struct cma *cma;
phys_addr_t memblock_end = memblock_end_of_DRAM();
phys_addr_t highmem_start = __pa(high_memory);
int ret = 0;
@@ -235,16 +284,9 @@ int __init cma_declare_contiguous(phys_addr_t base,
}
}
- /*
- * Each reserved area must be initialised later, when more kernel
- * subsystems (like slab allocator) are available.
- */
- cma = &cma_areas[cma_area_count];
- cma->base_pfn = PFN_DOWN(base);
- cma->count = size >> PAGE_SHIFT;
- cma->order_per_bit = order_per_bit;
- *res_cma = cma;
- cma_area_count++;
+ ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma);
+ if (ret)
+ goto err;
pr_info("Reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
(unsigned long)base);
diff --git a/mm/memory.c b/mm/memory.c
index e229970e4223..1cc6bfbd872e 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2053,7 +2053,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
old_page = vm_normal_page(vma, address, orig_pte);
if (!old_page) {
/*
- * VM_MIXEDMAP !pfn_valid() case
+ * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
+ * VM_PFNMAP VMA.
*
* We should not cow pages in a shared writeable mapping.
* Just mark the pages writable as we can't do any dirty
diff --git a/mm/mmap.c b/mm/mmap.c
index 93d28c7e5420..7f855206e7fb 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -89,6 +89,25 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags)
}
EXPORT_SYMBOL(vm_get_page_prot);
+static pgprot_t vm_pgprot_modify(pgprot_t oldprot, unsigned long vm_flags)
+{
+ return pgprot_modify(oldprot, vm_get_page_prot(vm_flags));
+}
+
+/* Update vma->vm_page_prot to reflect vma->vm_flags. */
+void vma_set_page_prot(struct vm_area_struct *vma)
+{
+ unsigned long vm_flags = vma->vm_flags;
+
+ vma->vm_page_prot = vm_pgprot_modify(vma->vm_page_prot, vm_flags);
+ if (vma_wants_writenotify(vma)) {
+ vm_flags &= ~VM_SHARED;
+ vma->vm_page_prot = vm_pgprot_modify(vma->vm_page_prot,
+ vm_flags);
+ }
+}
+
+
int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */
unsigned long sysctl_overcommit_kbytes __read_mostly;
@@ -1475,11 +1494,16 @@ int vma_wants_writenotify(struct vm_area_struct *vma)
if (vma->vm_ops && vma->vm_ops->page_mkwrite)
return 1;
- /* The open routine did something to the protections already? */
+ /* The open routine did something to the protections that pgprot_modify
+ * won't preserve? */
if (pgprot_val(vma->vm_page_prot) !=
- pgprot_val(vm_get_page_prot(vm_flags)))
+ pgprot_val(vm_pgprot_modify(vma->vm_page_prot, vm_flags)))
return 0;
+ /* Do we need to track softdirty? */
+ if (IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) && !(vm_flags & VM_SOFTDIRTY))
+ return 1;
+
/* Specialty mapping? */
if (vm_flags & VM_PFNMAP)
return 0;
@@ -1615,21 +1639,6 @@ munmap_back:
goto free_vma;
}
- if (vma_wants_writenotify(vma)) {
- pgprot_t pprot = vma->vm_page_prot;
-
- /* Can vma->vm_page_prot have changed??
- *
- * Answer: Yes, drivers may have changed it in their
- * f_op->mmap method.
- *
- * Ensures that vmas marked as uncached stay that way.
- */
- vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED);
- if (pgprot_val(pprot) == pgprot_val(pgprot_noncached(pprot)))
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- }
-
vma_link(mm, vma, prev, rb_link, rb_parent);
/* Once vma denies write, undo our temporary denial count */
if (file) {
@@ -1663,6 +1672,8 @@ out:
*/
vma->vm_flags |= VM_SOFTDIRTY;
+ vma_set_page_prot(vma);
+
return addr;
unmap_and_free_vma:
diff --git a/mm/mprotect.c b/mm/mprotect.c
index c43d557941f8..ace93454ce8e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -29,13 +29,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-#ifndef pgprot_modify
-static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
-{
- return newprot;
-}
-#endif
-
/*
* For a prot_numa update we only hold mmap_sem for read so there is a
* potential race with faulting where a pmd was temporarily none. This
@@ -93,7 +86,9 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
* Avoid taking write faults for pages we
* know to be dirty.
*/
- if (dirty_accountable && pte_dirty(ptent))
+ if (dirty_accountable && pte_dirty(ptent) &&
+ (pte_soft_dirty(ptent) ||
+ !(vma->vm_flags & VM_SOFTDIRTY)))
ptent = pte_mkwrite(ptent);
ptep_modify_prot_commit(mm, addr, pte, ptent);
updated = true;
@@ -320,13 +315,8 @@ success:
* held in write mode.
*/
vma->vm_flags = newflags;
- vma->vm_page_prot = pgprot_modify(vma->vm_page_prot,
- vm_get_page_prot(newflags));
-
- if (vma_wants_writenotify(vma)) {
- vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
- dirty_accountable = 1;
- }
+ dirty_accountable = vma_wants_writenotify(vma);
+ vma_set_page_prot(vma);
change_protection(vma, start, end, vma->vm_page_prot,
dirty_accountable, 0);
diff --git a/mm/slab.c b/mm/slab.c
index 154aac8411c5..eb2b2ea30130 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1992,7 +1992,7 @@ static struct array_cache __percpu *alloc_kmem_cache_cpus(
struct array_cache __percpu *cpu_cache;
size = sizeof(void *) * entries + sizeof(struct array_cache);
- cpu_cache = __alloc_percpu(size, 0);
+ cpu_cache = __alloc_percpu(size, sizeof(void *));
if (!cpu_cache)
return NULL;
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 6f5e621f220a..88a1bc3804d1 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -44,10 +44,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
if (strlen(buff) > 4) {
tmp_ptr = buff + strlen(buff) - 4;
- if (strnicmp(tmp_ptr, "mbit", 4) == 0)
+ if (strncasecmp(tmp_ptr, "mbit", 4) == 0)
bw_unit_type = BATADV_BW_UNIT_MBIT;
- if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
+ if ((strncasecmp(tmp_ptr, "kbit", 4) == 0) ||
(bw_unit_type == BATADV_BW_UNIT_MBIT))
*tmp_ptr = '\0';
}
@@ -77,10 +77,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
if (strlen(slash_ptr + 1) > 4) {
tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1);
- if (strnicmp(tmp_ptr, "mbit", 4) == 0)
+ if (strncasecmp(tmp_ptr, "mbit", 4) == 0)
bw_unit_type = BATADV_BW_UNIT_MBIT;
- if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
+ if ((strncasecmp(tmp_ptr, "kbit", 4) == 0) ||
(bw_unit_type == BATADV_BW_UNIT_MBIT))
*tmp_ptr = '\0';
}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index a64fa15790e5..1d5341f3761d 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -96,13 +96,13 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
if (data_limit - data < plen) {
/* check if there is partial match */
- if (strnicmp(data, pattern, data_limit - data) == 0)
+ if (strncasecmp(data, pattern, data_limit - data) == 0)
return -1;
else
return 0;
}
- if (strnicmp(data, pattern, plen) != 0) {
+ if (strncasecmp(data, pattern, plen) != 0) {
return 0;
}
s = data + plen;
@@ -354,7 +354,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
data_limit = skb_tail_pointer(skb);
while (data <= data_limit - 6) {
- if (strnicmp(data, "PASV\r\n", 6) == 0) {
+ if (strncasecmp(data, "PASV\r\n", 6) == 0) {
/* Passive mode on */
IP_VS_DBG(7, "got PASV at %td of %td\n",
data - data_start,
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index b8a0924064ef..b666959f17c0 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -304,12 +304,12 @@ static int find_pattern(const char *data, size_t dlen,
if (dlen <= plen) {
/* Short packet: try for partial? */
- if (strnicmp(data, pattern, dlen) == 0)
+ if (strncasecmp(data, pattern, dlen) == 0)
return -1;
else return 0;
}
- if (strnicmp(data, pattern, plen) != 0) {
+ if (strncasecmp(data, pattern, plen) != 0) {
#if 0
size_t i;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 4c3ba1c8d682..885b4aba3695 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -247,7 +247,7 @@ int ct_sip_parse_request(const struct nf_conn *ct,
for (; dptr < limit - strlen("sip:"); dptr++) {
if (*dptr == '\r' || *dptr == '\n')
return -1;
- if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) {
+ if (strncasecmp(dptr, "sip:", strlen("sip:")) == 0) {
dptr += strlen("sip:");
break;
}
@@ -350,7 +350,7 @@ static const char *ct_sip_header_search(const char *dptr, const char *limit,
continue;
}
- if (strnicmp(dptr, needle, len) == 0)
+ if (strncasecmp(dptr, needle, len) == 0)
return dptr;
}
return NULL;
@@ -383,10 +383,10 @@ int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
/* Find header. Compact headers must be followed by a
* non-alphabetic character to avoid mismatches. */
if (limit - dptr >= hdr->len &&
- strnicmp(dptr, hdr->name, hdr->len) == 0)
+ strncasecmp(dptr, hdr->name, hdr->len) == 0)
dptr += hdr->len;
else if (hdr->cname && limit - dptr >= hdr->clen + 1 &&
- strnicmp(dptr, hdr->cname, hdr->clen) == 0 &&
+ strncasecmp(dptr, hdr->cname, hdr->clen) == 0 &&
!isalpha(*(dptr + hdr->clen)))
dptr += hdr->clen;
else
@@ -620,9 +620,9 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,
if (ct_sip_parse_param(ct, dptr, dataoff, datalen, "transport=",
&matchoff, &matchlen)) {
- if (!strnicmp(dptr + matchoff, "TCP", strlen("TCP")))
+ if (!strncasecmp(dptr + matchoff, "TCP", strlen("TCP")))
*proto = IPPROTO_TCP;
- else if (!strnicmp(dptr + matchoff, "UDP", strlen("UDP")))
+ else if (!strncasecmp(dptr + matchoff, "UDP", strlen("UDP")))
*proto = IPPROTO_UDP;
else
return 0;
@@ -743,10 +743,10 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
if (term != SDP_HDR_UNSPEC &&
limit - dptr >= thdr->len &&
- strnicmp(dptr, thdr->name, thdr->len) == 0)
+ strncasecmp(dptr, thdr->name, thdr->len) == 0)
break;
else if (limit - dptr >= hdr->len &&
- strnicmp(dptr, hdr->name, hdr->len) == 0)
+ strncasecmp(dptr, hdr->name, hdr->len) == 0)
dptr += hdr->len;
else
continue;
@@ -1394,7 +1394,7 @@ static int process_sip_response(struct sk_buff *skb, unsigned int protoff,
if (handler->response == NULL)
continue;
if (*datalen < matchend + handler->len ||
- strnicmp(*dptr + matchend, handler->method, handler->len))
+ strncasecmp(*dptr + matchend, handler->method, handler->len))
continue;
return handler->response(skb, protoff, dataoff, dptr, datalen,
cseq, code);
@@ -1435,7 +1435,7 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff,
if (handler->request == NULL)
continue;
if (*datalen < handler->len ||
- strnicmp(*dptr, handler->method, handler->len))
+ strncasecmp(*dptr, handler->method, handler->len))
continue;
if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
@@ -1462,7 +1462,7 @@ static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct,
const struct nf_nat_sip_hooks *hooks;
int ret;
- if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
+ if (strncasecmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
ret = process_sip_request(skb, protoff, dataoff, dptr, datalen);
else
ret = process_sip_response(skb, protoff, dataoff, dptr, datalen);
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index daad6022c689..d7197649dba6 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -30,7 +30,7 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger)
log = rcu_dereference_protected(loggers[pf][i],
lockdep_is_held(&nf_log_mutex));
- if (!strnicmp(str_logger, log->name, strlen(log->name)))
+ if (!strncasecmp(str_logger, log->name, strlen(log->name)))
return log;
}
diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
index b4d691db955e..791fac4fd745 100644
--- a/net/netfilter/nf_nat_sip.c
+++ b/net/netfilter/nf_nat_sip.c
@@ -155,7 +155,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
int request, in_header;
/* Basic rules: requests and responses. */
- if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
+ if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
if (ct_sip_parse_request(ct, *dptr, *datalen,
&matchoff, &matchlen,
&addr, &port) > 0 &&
diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c
index a55c27b75ee5..459611577d3d 100644
--- a/net/wireless/lib80211.c
+++ b/net/wireless/lib80211.c
@@ -46,38 +46,6 @@ static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info,
static void lib80211_crypt_quiescing(struct lib80211_crypt_info *info);
static void lib80211_crypt_deinit_handler(unsigned long data);
-const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
-{
- const char *s = ssid;
- char *d = buf;
-
- ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN);
- while (ssid_len--) {
- if (isprint(*s)) {
- *d++ = *s++;
- continue;
- }
-
- *d++ = '\\';
- if (*s == '\0')
- *d++ = '0';
- else if (*s == '\n')
- *d++ = 'n';
- else if (*s == '\r')
- *d++ = 'r';
- else if (*s == '\t')
- *d++ = 't';
- else if (*s == '\\')
- *d++ = '\\';
- else
- d += snprintf(d, 3, "%03o", *s);
- s++;
- }
- *d = '\0';
- return buf;
-}
-EXPORT_SYMBOL(print_ssid);
-
int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name,
spinlock_t *lock)
{
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4d08b398411f..374abf443636 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,8 @@ use strict;
use POSIX;
my $P = $0;
-$P =~ s@.*/@@g;
+$P =~ s@(.*)/@@g;
+my $D = $1;
my $V = '0.32';
@@ -43,6 +44,8 @@ my $configuration_file = ".checkpatch.conf";
my $max_line_length = 80;
my $ignore_perl_version = 0;
my $minimum_perl_version = 5.10.0;
+my $min_conf_desc_length = 4;
+my $spelling_file = "$D/spelling.txt";
sub help {
my ($exitcode) = @_;
@@ -63,6 +66,7 @@ Options:
--types TYPE(,TYPE2...) show only these comma separated message types
--ignore TYPE(,TYPE2...) ignore various comma separated message types
--max-line-length=n set the maximum line length, if exceeded, warn
+ --min-conf-desc-length=n set the min description length, if shorter, warn
--show-types show the message "types" in the output
--root=PATH PATH to the kernel tree root
--no-summary suppress the per-file summary
@@ -131,6 +135,7 @@ GetOptions(
'types=s' => \@use,
'show-types!' => \$show_types,
'max-line-length=i' => \$max_line_length,
+ 'min-conf-desc-length=i' => \$min_conf_desc_length,
'root=s' => \$root,
'summary!' => \$summary,
'mailback!' => \$mailback,
@@ -425,10 +430,35 @@ foreach my $entry (@mode_permission_funcs) {
our $allowed_asm_includes = qr{(?x:
irq|
- memory
+ memory|
+ time|
+ reboot
)};
# memory.h: ARM has a custom one
+# Load common spelling mistakes and build regular expression list.
+my $misspellings;
+my @spelling_list;
+my %spelling_fix;
+open(my $spelling, '<', $spelling_file)
+ or die "$P: Can't open $spelling_file for reading: $!\n";
+while (<$spelling>) {
+ my $line = $_;
+
+ $line =~ s/\s*\n?$//g;
+ $line =~ s/^\s*//g;
+
+ next if ($line =~ m/^\s*#/);
+ next if ($line =~ m/^\s*$/);
+
+ my ($suspect, $fix) = split(/\|\|/, $line);
+
+ push(@spelling_list, $suspect);
+ $spelling_fix{$suspect} = $fix;
+}
+close($spelling);
+$misspellings = join("|", @spelling_list);
+
sub build_types {
my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
@@ -2215,6 +2245,23 @@ sub process {
"8-bit UTF-8 used in possible commit log\n" . $herecurr);
}
+# Check for various typo / spelling mistakes
+ if ($in_commit_log || $line =~ /^\+/) {
+ while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:$|[^a-z@])/gi) {
+ my $typo = $1;
+ my $typo_fix = $spelling_fix{lc($typo)};
+ $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
+ $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
+ my $msg_type = \&WARN;
+ $msg_type = \&CHK if ($file);
+ if (&{$msg_type}("TYPO_SPELLING",
+ "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
+ }
+ }
+ }
+
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
@@ -2283,8 +2330,10 @@ sub process {
}
$length++;
}
- WARN("CONFIG_DESCRIPTION",
- "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_start && $is_end && $length < 4);
+ if ($is_start && $is_end && $length < $min_conf_desc_length) {
+ WARN("CONFIG_DESCRIPTION",
+ "please write a paragraph that describes the config symbol fully\n" . $herecurr);
+ }
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
}
@@ -2341,7 +2390,7 @@ sub process {
}
# check we are in a valid source file if not then ignore this hunk
- next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+ next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/);
#line length limit
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
@@ -2402,7 +2451,7 @@ sub process {
}
# check we are in a valid source file C or perl if not then ignore this hunk
- next if ($realfile !~ /\.(h|c|pl)$/);
+ next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs.
@@ -2424,7 +2473,7 @@ sub process {
"please, no space before tabs\n" . $herevet) &&
$fix) {
while ($fixed[$fixlinenr] =~
- s/(^\+.*) {8,8}+\t/$1\t\t/) {}
+ s/(^\+.*) {8,8}\t/$1\t\t/) {}
while ($fixed[$fixlinenr] =~
s/(^\+.*) +\t/$1\t/) {}
}
@@ -2592,10 +2641,14 @@ sub process {
next if ($realfile !~ /\.(h|c)$/);
# check indentation of any line with a bare else
+# (but not if it is a multiple line "if (foo) return bar; else return baz;")
# if the previous line is a break or return and is indented 1 tab more...
if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
my $tabs = length($1) + 1;
- if ($prevline =~ /^\+\t{$tabs,$tabs}(?:break|return)\b/) {
+ if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ ||
+ ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ &&
+ defined $lines[$linenr] &&
+ $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) {
WARN("UNNECESSARY_ELSE",
"else is not generally useful after a break or return\n" . $hereprev);
}
@@ -3752,7 +3805,6 @@ sub process {
if (ERROR("SPACING",
"space prohibited before that close parenthesis ')'\n" . $herecurr) &&
$fix) {
- print("fixlinenr: <$fixlinenr> fixed[fixlinenr]: <$fixed[$fixlinenr]>\n");
$fixed[$fixlinenr] =~
s/\s+\)/\)/;
}
@@ -4060,12 +4112,17 @@ sub process {
my $cnt = $realcnt;
my ($off, $dstat, $dcond, $rest);
my $ctx = '';
+ my $has_flow_statement = 0;
+ my $has_arg_concat = 0;
($dstat, $dcond, $ln, $cnt, $off) =
ctx_statement_block($linenr, $realcnt, 0);
$ctx = $dstat;
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
+ $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
+ $has_arg_concat = 1 if ($ctx =~ /\#\#/);
+
$dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
$dstat =~ s/$;//g;
$dstat =~ s/\\\n.//g;
@@ -4126,10 +4183,23 @@ sub process {
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
} else {
ERROR("COMPLEX_MACRO",
- "Macros with complex values should be enclosed in parenthesis\n" . "$herectx");
+ "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
}
}
+# check for macros with flow control, but without ## concatenation
+# ## concatenation is commonly a macro that defines a function so ignore those
+ if ($has_flow_statement && !$has_arg_concat) {
+ my $herectx = $here . "\n";
+ my $cnt = statement_rawlines($ctx);
+
+ for (my $n = 0; $n < $cnt; $n++) {
+ $herectx .= raw_line($linenr, $n) . "\n";
+ }
+ WARN("MACRO_WITH_FLOW_CONTROL",
+ "Macros with flow control statements should be avoided\n" . "$herectx");
+ }
+
# check for line continuations outside of #defines, preprocessor #, and asm
} else {
@@ -4338,6 +4408,12 @@ sub process {
"Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
}
+# concatenated string without spaces between elements
+ if ($line =~ /"X+"[A-Z_]+/ || $line =~ /[A-Z_]+"X+"/) {
+ CHK("CONCATENATED_STRING",
+ "Concatenated strings should use spaces between elements\n" . $herecurr);
+ }
+
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
CHK("REDUNDANT_CODE",
@@ -4371,6 +4447,17 @@ sub process {
}
}
+# check for logging functions with KERN_<LEVEL>
+ if ($line !~ /printk\s*\(/ &&
+ $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
+ my $level = $1;
+ if (WARN("UNNECESSARY_KERN_LEVEL",
+ "Possible unnecessary $level\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\s*$level\s*//;
+ }
+ }
+
# check for bad placement of section $InitAttribute (e.g.: __initdata)
if ($line =~ /(\b$InitAttribute\b)/) {
my $attr = $1;
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 5de5660cb708..fdebd66f8fc1 100644
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -1,8 +1,8 @@
#!/bin/sh
-if [ $# -lt 1 ]
+if [ $# -lt 2 ]
then
- echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...]
+ echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...]"
echo
echo "Prepares kernel header files for use by user space, by removing"
echo "all compiler.h definitions and #includes, removing any"
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
index 8fac3fd697a6..ba8700428e21 100644
--- a/scripts/sortextable.h
+++ b/scripts/sortextable.h
@@ -103,7 +103,7 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
Elf_Sym *sort_needed_sym;
Elf_Shdr *sort_needed_sec;
Elf_Rel *relocs = NULL;
- int relocs_size;
+ int relocs_size = 0;
uint32_t *sort_done_location;
const char *secstrtab;
const char *strtab;
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
new file mode 100644
index 000000000000..fc7fd52b5e03
--- /dev/null
+++ b/scripts/spelling.txt
@@ -0,0 +1,1042 @@
+# Originally from Debian's Lintian tool. Various false positives have been
+# removed, and various additions have been made as they've been discovered
+# in the kernel source.
+#
+# License: GPLv2
+#
+# The format of each line is:
+# mistake||correction
+#
+abandonning||abandoning
+abigious||ambiguous
+abitrate||arbitrate
+abov||above
+abreviated||abbreviated
+absense||absence
+absolut||absolute
+absoulte||absolute
+acccess||access
+acceleratoin||acceleration
+accelleration||acceleration
+accesing||accessing
+accesnt||accent
+accessable||accessible
+accesss||access
+accidentaly||accidentally
+accidentually||accidentally
+accoding||according
+accomodate||accommodate
+accomodates||accommodates
+accordign||according
+accoring||according
+accout||account
+accquire||acquire
+accquired||acquired
+acessable||accessible
+acess||access
+achitecture||architecture
+acient||ancient
+acitions||actions
+acitve||active
+acknowldegement||acknowldegement
+acknowledgement||acknowledgment
+ackowledge||acknowledge
+ackowledged||acknowledged
+acording||according
+activete||activate
+acumulating||accumulating
+adapater||adapter
+addional||additional
+additionaly||additionally
+addres||address
+addreses||addresses
+addresss||address
+aditional||additional
+aditionally||additionally
+aditionaly||additionally
+adminstrative||administrative
+adress||address
+adresses||addresses
+adviced||advised
+afecting||affecting
+agaist||against
+albumns||albums
+alegorical||allegorical
+algorith||algorithm
+algorithmical||algorithmically
+algoritm||algorithm
+algoritms||algorithms
+algorrithm||algorithm
+algorritm||algorithm
+allign||align
+allocatrd||allocated
+allocte||allocate
+allpication||application
+alocate||allocate
+alogirhtms||algorithms
+alogrithm||algorithm
+alot||a lot
+alow||allow
+alows||allows
+altough||although
+alue||value
+ambigious||ambiguous
+amoung||among
+amout||amount
+analysator||analyzer
+ang||and
+anniversery||anniversary
+annoucement||announcement
+anomolies||anomalies
+anomoly||anomaly
+anway||anyway
+aplication||application
+appearence||appearance
+applicaion||application
+appliction||application
+applictions||applications
+appplications||applications
+appropiate||appropriate
+appropriatly||appropriately
+approriate||appropriate
+approriately||appropriately
+aquainted||acquainted
+aquired||acquired
+arbitary||arbitrary
+architechture||architecture
+arguement||argument
+arguements||arguments
+aritmetic||arithmetic
+arne't||aren't
+arraival||arrival
+artifical||artificial
+artillary||artillery
+assiged||assigned
+assigment||assignment
+assigments||assignments
+assistent||assistant
+assocation||association
+associcated||associated
+assotiated||associated
+assum||assume
+assumtpion||assumption
+asuming||assuming
+asycronous||asynchronous
+asynchnous||asynchronous
+atomatically||automatically
+atomicly||atomically
+attachement||attachment
+attched||attached
+attemps||attempts
+attruibutes||attributes
+authentification||authentication
+automaticaly||automatically
+automaticly||automatically
+automatize||automate
+automatized||automated
+automatizes||automates
+autonymous||autonomous
+auxilliary||auxiliary
+avaiable||available
+avaible||available
+availabe||available
+availabled||available
+availablity||availability
+availale||available
+availavility||availability
+availble||available
+availiable||available
+avalable||available
+avaliable||available
+aysnc||async
+backgroud||background
+backword||backward
+backwords||backwards
+bahavior||behavior
+bakup||backup
+baloon||balloon
+baloons||balloons
+bandwith||bandwidth
+batery||battery
+beacuse||because
+becasue||because
+becomming||becoming
+becuase||because
+beeing||being
+befor||before
+begining||beginning
+beter||better
+betweeen||between
+bianries||binaries
+bitmast||bitmask
+boardcast||broadcast
+borad||board
+boundry||boundary
+brievely||briefly
+broadcat||broadcast
+cacluated||calculated
+caculation||calculation
+calender||calendar
+calle||called
+calucate||calculate
+calulate||calculate
+cancelation||cancellation
+capabilites||capabilities
+capabitilies||capabilities
+capatibilities||capabilities
+carefuly||carefully
+cariage||carriage
+catagory||category
+challange||challenge
+challanges||challenges
+chanell||channel
+changable||changeable
+channle||channel
+channnel||channel
+charachter||character
+charachters||characters
+charactor||character
+charater||character
+charaters||characters
+charcter||character
+checksuming||checksumming
+childern||children
+childs||children
+chiled||child
+chked||checked
+chnage||change
+chnages||changes
+chnnel||channel
+choosen||chosen
+chouse||chose
+circumvernt||circumvent
+claread||cleared
+clared||cleared
+closeing||closing
+clustred||clustered
+collapsable||collapsible
+colorfull||colorful
+comand||command
+comit||commit
+commerical||commercial
+comming||coming
+comminucation||communication
+commited||committed
+commiting||committing
+committ||commit
+commoditiy||commodity
+compability||compatibility
+compaibility||compatibility
+compatability||compatibility
+compatable||compatible
+compatibiliy||compatibility
+compatibilty||compatibility
+compilant||compliant
+compleatly||completely
+completly||completely
+complient||compliant
+componnents||components
+compres||compress
+compresion||compression
+comression||compression
+comunication||communication
+conbination||combination
+conditionaly||conditionally
+conected||connected
+configuratoin||configuration
+configuraton||configuration
+configuretion||configuration
+conider||consider
+conjuction||conjunction
+connectinos||connections
+connnection||connection
+connnections||connections
+consistancy||consistency
+consistant||consistent
+containes||contains
+containts||contains
+contaisn||contains
+contant||contact
+contence||contents
+continous||continuous
+continously||continuously
+continueing||continuing
+contraints||constraints
+controled||controlled
+controler||controller
+controll||control
+contruction||construction
+contry||country
+convertion||conversion
+convertor||converter
+convienient||convenient
+convinient||convenient
+corected||corrected
+correponding||corresponding
+correponds||corresponds
+correspoding||corresponding
+cotrol||control
+couter||counter
+coutner||counter
+cryptocraphic||cryptographic
+cunter||counter
+curently||currently
+dafault||default
+deafult||default
+deamon||daemon
+decompres||decompress
+decription||description
+defailt||default
+defferred||deferred
+definate||definite
+definately||definitely
+defintion||definition
+defualt||default
+defult||default
+deivce||device
+delared||declared
+delare||declare
+delares||declares
+delaring||declaring
+delemiter||delimiter
+dependancies||dependencies
+dependancy||dependency
+dependant||dependent
+depreacted||deprecated
+depreacte||deprecate
+desactivate||deactivate
+desciptors||descriptors
+descrition||description
+descritptor||descriptor
+desctiptor||descriptor
+desriptor||descriptor
+desriptors||descriptors
+destory||destroy
+destoryed||destroyed
+destorys||destroys
+destroied||destroyed
+detabase||database
+develope||develop
+developement||development
+developped||developed
+developpement||development
+developper||developer
+developpment||development
+deveolpment||development
+devided||divided
+deviece||device
+diable||disable
+dictionnary||dictionary
+diferent||different
+differrence||difference
+difinition||definition
+diplay||display
+direectly||directly
+disapear||disappear
+disapeared||disappeared
+disappared||disappeared
+disconnet||disconnect
+discontinous||discontinuous
+dispertion||dispersion
+dissapears||disappears
+distiction||distinction
+docuentation||documentation
+documantation||documentation
+documentaion||documentation
+documment||document
+dorp||drop
+dosen||doesn
+downlad||download
+downlads||downloads
+druing||during
+dynmaic||dynamic
+easilly||easily
+ecspecially||especially
+edditable||editable
+editting||editing
+efficently||efficiently
+ehther||ether
+eigth||eight
+eletronic||electronic
+enabledi||enabled
+enchanced||enhanced
+encorporating||incorporating
+encrupted||encrypted
+encrypiton||encryption
+endianess||endianness
+enhaced||enhanced
+enlightnment||enlightenment
+enocded||encoded
+enterily||entirely
+enviroiment||environment
+enviroment||environment
+environement||environment
+environent||environment
+eqivalent||equivalent
+equiped||equipped
+equivelant||equivalent
+equivilant||equivalent
+eror||error
+estbalishment||establishment
+etsablishment||establishment
+etsbalishment||establishment
+excecutable||executable
+exceded||exceeded
+excellant||excellent
+existance||existence
+existant||existent
+exixt||exist
+exlcude||exclude
+exlcusive||exclusive
+exmaple||example
+expecially||especially
+explicite||explicit
+explicitely||explicitly
+explict||explicit
+explictly||explicitly
+expresion||expression
+exprimental||experimental
+extened||extended
+extensability||extensibility
+extention||extension
+extracter||extractor
+faild||failed
+faill||fail
+failue||failure
+failuer||failure
+faireness||fairness
+faliure||failure
+familar||familiar
+fatser||faster
+feauture||feature
+feautures||features
+fetaure||feature
+fetaures||features
+fileystem||filesystem
+finanize||finalize
+findn||find
+finilizes||finalizes
+finsih||finish
+flusing||flushing
+folloing||following
+followign||following
+follwing||following
+forseeable||foreseeable
+forse||force
+fortan||fortran
+forwardig||forwarding
+framwork||framework
+frequncy||frequency
+frome||from
+fucntion||function
+fuction||function
+fuctions||functions
+funcion||function
+functionallity||functionality
+functionaly||functionally
+functionnality||functionality
+functonality||functionality
+funtion||function
+funtions||functions
+furthur||further
+futhermore||furthermore
+futrue||future
+gaurenteed||guaranteed
+generiously||generously
+genric||generic
+globel||global
+grabing||grabbing
+grahical||graphical
+grahpical||graphical
+grapic||graphic
+guage||gauge
+guarentee||guarantee
+halfs||halves
+hander||handler
+handfull||handful
+hanled||handled
+harware||hardware
+heirarchically||hierarchically
+helpfull||helpful
+hierachy||hierarchy
+hierarchie||hierarchy
+howver||however
+hsould||should
+hypter||hyper
+identidier||identifier
+imblance||imbalance
+immeadiately||immediately
+immedaite||immediate
+immediatelly||immediately
+immediatly||immediately
+immidiate||immediate
+impelentation||implementation
+impementated||implemented
+implemantation||implementation
+implemenation||implementation
+implementaiton||implementation
+implementated||implemented
+implemention||implementation
+implemetation||implementation
+implemntation||implementation
+implentation||implementation
+implmentation||implementation
+implmenting||implementing
+incomming||incoming
+incompatabilities||incompatibilities
+incompatable||incompatible
+inconsistant||inconsistent
+increas||increase
+incrment||increment
+indendation||indentation
+indended||intended
+independant||independent
+independantly||independently
+independed||independent
+indiate||indicate
+inexpect||inexpected
+infomation||information
+informatiom||information
+informations||information
+informtion||information
+infromation||information
+ingore||ignore
+inital||initial
+initalised||initialized
+initalise||initialize
+initalize||initialize
+initation||initiation
+initators||initiators
+initializiation||initialization
+initialzed||initialized
+initilization||initialization
+initilize||initialize
+inofficial||unofficial
+instal||install
+inteface||interface
+integreated||integrated
+integrety||integrity
+integrey||integrity
+intendet||intended
+intented||intended
+interanl||internal
+interchangable||interchangeable
+interferring||interfering
+interger||integer
+intermittant||intermittent
+internel||internal
+interoprability||interoperability
+interrface||interface
+interrrupt||interrupt
+interrup||interrupt
+interrups||interrupts
+interruptted||interrupted
+interupted||interrupted
+interupt||interrupt
+intial||initial
+intialized||initialized
+intialize||initialize
+intregral||integral
+intrrupt||interrupt
+intuative||intuitive
+invaid||invalid
+invalde||invald
+invalide||invalid
+invididual||individual
+invokation||invocation
+invokations||invocations
+irrelevent||irrelevant
+isssue||issue
+itslef||itself
+jave||java
+jeffies||jiffies
+juse||just
+jus||just
+kown||known
+langage||language
+langauage||language
+langauge||language
+langugage||language
+lauch||launch
+leightweight||lightweight
+lengh||length
+lenght||length
+lenth||length
+lesstiff||lesstif
+libaries||libraries
+libary||library
+librairies||libraries
+libraris||libraries
+licenceing||licencing
+loggging||logging
+loggin||login
+logile||logfile
+loosing||losing
+losted||lost
+machinary||machinery
+maintainance||maintenance
+maintainence||maintenance
+maintan||maintain
+makeing||making
+malplaced||misplaced
+malplace||misplace
+managable||manageable
+managment||management
+mangement||management
+manoeuvering||maneuvering
+mappping||mapping
+mathimatical||mathematical
+mathimatic||mathematic
+mathimatics||mathematics
+maxium||maximum
+mechamism||mechanism
+meetign||meeting
+ment||meant
+mergable||mergeable
+mesage||message
+messags||messages
+messgaes||messages
+messsage||message
+messsages||messages
+microprocesspr||microprocessor
+milliseonds||milliseconds
+minumum||minimum
+miscelleneous||miscellaneous
+misformed||malformed
+mispelled||misspelled
+mispelt||misspelt
+miximum||maximum
+mmnemonic||mnemonic
+mnay||many
+modeled||modelled
+modulues||modules
+monochorome||monochrome
+monochromo||monochrome
+monocrome||monochrome
+mopdule||module
+mroe||more
+mulitplied||multiplied
+multidimensionnal||multidimensional
+multple||multiple
+mumber||number
+muticast||multicast
+mutiple||multiple
+mutli||multi
+nams||names
+navagating||navigating
+nead||need
+neccecary||necessary
+neccesary||necessary
+neccessary||necessary
+necesary||necessary
+negaive||negative
+negoitation||negotiation
+negotation||negotiation
+nerver||never
+nescessary||necessary
+nessessary||necessary
+noticable||noticeable
+notications||notifications
+notifed||notified
+numebr||number
+numner||number
+obtaion||obtain
+occassionally||occasionally
+occationally||occasionally
+occurance||occurrence
+occurances||occurrences
+occured||occurred
+occurence||occurrence
+occure||occurred
+occuring||occurring
+offet||offset
+omitt||omit
+ommiting||omitting
+ommitted||omitted
+onself||oneself
+ony||only
+operatione||operation
+opertaions||operations
+optionnal||optional
+optmizations||optimizations
+orientatied||orientated
+orientied||oriented
+otherise||otherwise
+ouput||output
+overaall||overall
+overhread||overhead
+overlaping||overlapping
+overriden||overridden
+overun||overrun
+pacakge||package
+pachage||package
+packacge||package
+packege||package
+packge||package
+packtes||packets
+pakage||package
+pallette||palette
+paln||plan
+paramameters||parameters
+paramater||parameter
+parametes||parameters
+parametised||parametrised
+paramter||parameter
+paramters||parameters
+particuarly||particularly
+particularily||particularly
+pased||passed
+passin||passing
+pathes||paths
+pecularities||peculiarities
+peformance||performance
+peice||piece
+pendantic||pedantic
+peprocessor||preprocessor
+perfoming||performing
+permissons||permissions
+peroid||period
+persistance||persistence
+persistant||persistent
+platfrom||platform
+plattform||platform
+pleaes||please
+ploting||plotting
+plugable||pluggable
+poinnter||pointer
+poiter||pointer
+posible||possible
+positon||position
+possibilites||possibilities
+powerfull||powerful
+preceeded||preceded
+preceeding||preceding
+preceed||precede
+precendence||precedence
+precission||precision
+prefered||preferred
+prefferably||preferably
+premption||preemption
+prepaired||prepared
+pressre||pressure
+primative||primitive
+princliple||principle
+priorty||priority
+privilaged||privileged
+privilage||privilege
+priviledge||privilege
+priviledges||privileges
+probaly||probably
+procceed||proceed
+proccesors||processors
+procesed||processed
+proces||process
+processessing||processing
+processess||processes
+processpr||processor
+processsed||processed
+processsing||processing
+procteted||protected
+prodecure||procedure
+progams||programs
+progess||progress
+programers||programmers
+programm||program
+programms||programs
+progresss||progress
+promps||prompts
+pronnounced||pronounced
+prononciation||pronunciation
+pronouce||pronounce
+pronunce||pronounce
+propery||property
+propigate||propagate
+propigation||propagation
+propogate||propagate
+prosess||process
+protable||portable
+protcol||protocol
+protecion||protection
+protocoll||protocol
+psudo||pseudo
+psuedo||pseudo
+psychadelic||psychedelic
+pwoer||power
+quering||querying
+raoming||roaming
+reasearcher||researcher
+reasearchers||researchers
+reasearch||research
+recepient||recipient
+receving||receiving
+recieved||received
+recieve||receive
+reciever||receiver
+recieves||receives
+recogniced||recognised
+recognizeable||recognizable
+recommanded||recommended
+recyle||recycle
+redircet||redirect
+redirectrion||redirection
+refcounf||refcount
+refence||reference
+refered||referred
+referenace||reference
+refering||referring
+refernces||references
+refernnce||reference
+refrence||reference
+registerd||registered
+registeresd||registered
+registes||registers
+registraration||registration
+regster||register
+regualar||regular
+reguator||regulator
+regulamentations||regulations
+reigstration||registration
+releated||related
+relevent||relevant
+remoote||remote
+remore||remote
+removeable||removable
+repectively||respectively
+replacable||replaceable
+replacments||replacements
+replys||replies
+reponse||response
+representaion||representation
+reqeust||request
+requiere||require
+requirment||requirement
+requred||required
+requried||required
+requst||request
+reseting||resetting
+resizeable||resizable
+resouces||resources
+resoures||resources
+ressizes||resizes
+ressource||resource
+ressources||resources
+retransmited||retransmitted
+retreived||retrieved
+retreive||retrieve
+retrive||retrieve
+retuned||returned
+reuest||request
+reuqest||request
+reutnred||returned
+rmeoved||removed
+rmeove||remove
+rmeoves||removes
+rountine||routine
+routins||routines
+rquest||request
+runing||running
+runned||ran
+runnning||running
+runtine||runtime
+sacrifying||sacrificing
+safly||safely
+safty||safety
+savable||saveable
+scaned||scanned
+scaning||scanning
+scarch||search
+seach||search
+searchs||searches
+secquence||sequence
+secund||second
+segement||segment
+senarios||scenarios
+sentivite||sensitive
+separatly||separately
+sepcify||specify
+sepc||spec
+seperated||separated
+seperately||separately
+seperate||separate
+seperatly||separately
+seperator||separator
+sepperate||separate
+sequece||sequence
+sequencial||sequential
+serveral||several
+setts||sets
+settting||setting
+shotdown||shutdown
+shoud||should
+shoule||should
+shrinked||shrunk
+siginificantly||significantly
+signabl||signal
+similary||similarly
+similiar||similar
+simlar||similar
+simliar||similar
+simpified||simplified
+singaled||signaled
+singal||signal
+singed||signed
+sleeped||slept
+softwares||software
+speach||speech
+specfic||specific
+speciefied||specified
+specifc||specific
+specifed||specified
+specificatin||specification
+specificaton||specification
+specifing||specifying
+specifiying||specifying
+speficied||specified
+speicify||specify
+speling||spelling
+spinlcok||spinlock
+spinock||spinlock
+splitted||split
+spreaded||spread
+sructure||structure
+stablilization||stabilization
+staically||statically
+staion||station
+standardss||standards
+standartization||standardization
+standart||standard
+staticly||statically
+stoped||stopped
+stoppped||stopped
+straming||streaming
+struc||struct
+structres||structures
+stuct||struct
+sturcture||structure
+subdirectoires||subdirectories
+suble||subtle
+succesfully||successfully
+succesful||successful
+successfull||successful
+sucessfully||successfully
+sucess||success
+superflous||superfluous
+superseeded||superseded
+suplied||supplied
+suported||supported
+suport||support
+suppored||supported
+supportin||supporting
+suppoted||supported
+suppported||supported
+suppport||support
+supress||suppress
+surpresses||suppresses
+susbsystem||subsystem
+suspicously||suspiciously
+swaping||swapping
+switchs||switches
+symetric||symmetric
+synax||syntax
+synchonized||synchronized
+syncronize||synchronize
+syncronizing||synchronizing
+syncronus||synchronous
+syste||system
+sytem||system
+sythesis||synthesis
+taht||that
+targetted||targeted
+targetting||targeting
+teh||the
+temorary||temporary
+temproarily||temporarily
+thier||their
+threds||threads
+threshhold||threshold
+throught||through
+thses||these
+tiggered||triggered
+tipically||typically
+tmis||this
+torerable||tolerable
+tramsmitted||transmitted
+tramsmit||transmit
+tranfer||transfer
+transciever||transceiver
+transferd||transferrd
+transfered||transferred
+transfering||transferring
+transision||transition
+transmittd||transmitted
+transormed||transformed
+trasmission||transmission
+treshold||threshold
+trigerring||triggering
+trun||turn
+ture||true
+tyep||type
+udpate||update
+uesd||used
+unconditionaly||unconditionally
+underun||underrun
+unecessary||unnecessary
+unexecpted||unexpected
+unexpectd||unexpected
+unexpeted||unexpected
+unfortunatelly||unfortunately
+unifiy||unify
+unknonw||unknown
+unknow||unknown
+unkown||unknown
+unneedingly||unnecessarily
+unresgister||unregister
+unsinged||unsigned
+unstabel||unstable
+unsuccessfull||unsuccessful
+unsuported||unsupported
+untill||until
+unuseful||useless
+upate||update
+usefule||useful
+usefull||useful
+usege||usage
+usera||users
+usualy||usually
+utilites||utilities
+utillities||utilities
+utilties||utilities
+utiltity||utility
+utitity||utility
+utitlty||utility
+vaid||valid
+vaild||valid
+valide||valid
+variantions||variations
+varient||variant
+vaule||value
+verbse||verbose
+verisons||versions
+verison||version
+verson||version
+vicefersa||vice-versa
+virtal||virtual
+virtaul||virtual
+virtiual||virtual
+visiters||visitors
+vitual||virtual
+wating||waiting
+whataver||whatever
+whenver||whenever
+wheter||whether
+whe||when
+wierd||weird
+wiil||will
+wirte||write
+withing||within
+wnat||want
+workarould||workaround
+writeing||writing
+writting||writing
+zombe||zombie
+zomebie||zombie