Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
Merge second patch-bomb from Andrew Morton:
 - a few hotfixes
 - drivers/dma updates
 - MAINTAINERS updates
 - Quite a lot of lib/ updates
 - checkpatch updates
 - binfmt updates
 - autofs4
 - drivers/rtc/
 - various small tweaks to less used filesystems
 - ipc/ updates
 - kernel/watchdog.c changes

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits)
  mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared
  kernel/param: consolidate __{start,stop}___param[] in <linux/moduleparam.h>
  ia64: remove duplicate declarations of __per_cpu_start[] and __per_cpu_end[]
  frv: remove unused declarations of __start___ex_table and __stop___ex_table
  kvm: ensure hard lockup detection is disabled by default
  kernel/watchdog.c: control hard lockup detection default
  staging: rtl8192u: use %*pEn to escape buffer
  staging: rtl8192e: use %*pEn to escape buffer
  staging: wlan-ng: use %*pEhp to print SN
  lib80211: remove unused print_ssid()
  wireless: hostap: proc: print properly escaped SSID
  wireless: ipw2x00: print SSID via %*pE
  wireless: libertas: print esaped string via %*pE
  lib/vsprintf: add %*pE[achnops] format specifier
  lib / string_helpers: introduce string_escape_mem()
  lib / string_helpers: refactoring the test suite
  lib / string_helpers: move documentation to c-file
  include/linux: remove strict_strto* definitions
  arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable
  fs: check bh blocknr earlier when searching lru
  ...

150 files changed:
Documentation/binfmt_misc.txt
Documentation/devicetree/bindings/i2c/ti,bq32k.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/trivial-devices.txt
Documentation/devicetree/bindings/rtc/dallas,ds1339.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/s3c-rtc.txt
Documentation/filesystems/autofs4.txt [new file with mode: 0644]
Documentation/printk-formats.txt
Documentation/sysctl/kernel.txt
MAINTAINERS
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/mach-pxa/lpd270.c
arch/frv/mm/extable.c
arch/ia64/include/asm/sections.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/crash.c
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/kvm.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa.c
arch/x86/purgatory/Makefile
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-rk808.c [new file with mode: 0644]
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/memstick/host/r592.c
drivers/misc/altera-stapl/altera.c
drivers/net/wireless/hostap/hostap_proc.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/libipw_rx.c
drivers/net/wireless/ipw2x00/libipw_wx.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/mesh.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/interface.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-isl12022.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max77802.c [new file with mode: 0644]
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-rk808.c [new file with mode: 0644]
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s3c.c
drivers/s390/cio/chp.c
drivers/scsi/ips.c
drivers/scsi/scsi_debug.c
drivers/staging/rtl8188eu/os_dep/rtw_android.c
drivers/staging/rtl8192e/rtllib.h
drivers/staging/rtl8192u/ieee80211/ieee80211.h
drivers/staging/wlan-ng/prism2sta.c
drivers/thermal/thermal_core.c
drivers/video/fbdev/pvr2fb.c
drivers/video/fbdev/s3c2410fb.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/sm501fb.c
fs/affs/amigaffs.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/super.c
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/befs/btree.c
fs/binfmt_misc.c
fs/buffer.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/connect.c
fs/coredump.c
fs/fat/misc.c
fs/hfs/hfs_fs.h
fs/isofs/inode.c
fs/ncpfs/dir.c
fs/nilfs2/file.c
fs/nilfs2/inode.c
fs/nilfs2/ioctl.c
fs/nilfs2/nilfs.h
fs/nilfs2/segment.c
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.h
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.c
fs/omfs/inode.c
fs/omfs/omfs_fs.h
fs/proc/task_mmu.c
fs/reiserfs/journal.c
fs/ufs/balloc.c
include/asm-generic/pgtable.h
include/linux/cma.h
include/linux/compiler-gcc5.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/kexec.h
include/linux/list.h
include/linux/mm.h
include/linux/moduleparam.h
include/linux/nmi.h
include/linux/prio_heap.h [deleted file]
include/linux/rbtree_augmented.h
include/linux/signal.h
include/linux/string.h
include/linux/string_helpers.h
include/net/lib80211.h
init/Kconfig
init/initramfs.c
init/main.c
ipc/compat.c
ipc/ipc_sysctl.c
ipc/shm.c
ipc/util.c
kernel/debug/kdb/kdb_bp.c
kernel/kallsyms.c
kernel/kexec.c
kernel/params.c
kernel/printk/printk.c
kernel/resource.c
kernel/watchdog.c
lib/Kconfig.debug
lib/Makefile
lib/dynamic_debug.c
lib/prio_heap.c [deleted file]
lib/string.c
lib/string_helpers.c
lib/test-string_helpers.c
lib/textsearch.c
lib/vsprintf.c
mm/cma.c
mm/memory.c
mm/mmap.c
mm/mprotect.c
mm/slab.c
net/batman-adv/gateway_common.c
net/netfilter/ipvs/ip_vs_ftp.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_log.c
net/netfilter/nf_nat_sip.c
net/wireless/lib80211.c
scripts/checkpatch.pl
scripts/headers_install.sh
scripts/sortextable.h
scripts/spelling.txt [new file with mode: 0644]

index c1ed6948ba80e7f16fd313b9bab431118e18f31e..6b1de70583715d7728a7a31b4612564b0178679b 100644 (file)
@@ -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 (file)
index 0000000..e204906
--- /dev/null
@@ -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>;
+       };
index 5af3d9df6ecb05c5da5dbeff969bcfba18a09a9a..fbde415078e6845cc5ff862a758959d64810c316 100644 (file)
@@ -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 (file)
index 0000000..916f576
--- /dev/null
@@ -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>;
+       };
index 7ac7259fe9ea9d61eb208064c364b0998221aa11..ab757b84daa7edab473d2ec907cb0da3386d0b0a 100644 (file)
@@ -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 (file)
index 0000000..39d02e1
--- /dev/null
@@ -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
index b4498218c4744213bbe57609c7532fa4bd64bd54..5a615c14f75da79133db306179ccdd355bb0b4c4 100644 (file)
@@ -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
index f79eb96663790f1c116f6a44d706af048bdedc88..57baff5bdb806b3b725bdc7859c385fbdc1cac54 100644 (file)
@@ -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
index f413abff3807d72a7a1b1f574169936245038872..c52367997fb5bcca51b1483667918bff36383017 100644 (file)
@@ -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
index 1d52de6370d58a65022b0bc59bf2f07516066308..429a6c6cfcf95156df66fe8082a6e0a2ac2d8a73 100644 (file)
                };
 
                rtc: rtc@10070000 {
-                       compatible = "samsung,s3c6410-rtc";
+                       compatible = "samsung,exynos3250-rtc";
                        reg = <0x10070000 0x100>;
                        interrupts = <0 73 0>, <0 74 0>;
                        status = "disabled";
index 9f6ec167902a6bc1c2db823d257e006550a3c3b0..ad777b353bd5234797d93031ab6815747b65e363 100644 (file)
@@ -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);
index 6aea124f574db5a19d6dac8ec3aafff8d4df7246..2fb9b3ab57b9d624883fb5dd8d53944b12bb1556 100644 (file)
@@ -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;
index 1a873b36a4a1cd75f94bb196f1a7997d9ef621f3..2ab2003698ef6acd2fa7e5ffd5cabb31be3317b4 100644 (file)
@@ -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
index 700f958652f8ac1edc9e642b44f6cb61452c48cb..3eff36f719fb62dbb78ef64f37421b73a90c95ac 100644 (file)
@@ -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)
index a618fcd2c07d3d54062a8558a7f9941b16859203..f5ab56d1428718f6327c91012d5373cc200438a2 100644 (file)
@@ -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) {
index 9642b9b33655a739880fd5105473c81ff1696c9e..ca05f86481aace3a37cd6bf3fbe0e7d7ce3bb33a 100644 (file)
@@ -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;
index 3dd8e2c4d74a9ed4a124baf36a83de78be1be02d..95c3cb16af3e59e74d8a890bc59c2e35cb0fc014 100644 (file)
@@ -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)
index baff1da354e0ecfaf371b4e9f30ac6533d657a28..af78e50ca6cee7e4b7293075171986ab6f7166d5 100644 (file)
@@ -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
         */
index d221374d5ce82fa769dc31d864a4b72145ae8b42..1a883705a12a8a12410914be93b2ee65807cc423 100644 (file)
@@ -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);
@@ -480,6 +516,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
                                  &memblock.memory, mb->nid);
        }
 
+       /*
+        * 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;
 }
 
index 899dd24542568de85e815e4b9f206d66286bca8c..f52e033557c9e0b54c41248101e0d7d7ed7cb76f 100644 (file)
@@ -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)
index 7d6e84a51424b269d6bfffa401f6788ac44997ed..55b83983a9c00c8b5984c887a0435ffb6e03fe1d 100644 (file)
@@ -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
index 6606abdf880c816ce407c486fbabcc27d602cef9..473ff48924015f07daee1c81ebe3d6436727493e 100644 (file)
@@ -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
index cfd3af7b2cbd16cec12c23cf0767cc787c66a812..84e0590e31dc754fd1562d8bd99d2c3273090f3f 100644 (file)
@@ -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
index f537a0b1f798159824aa1d90ffd4378d1bff908d..99f53d5f876618be908525c3cbc4b9c3803119a2 100644 (file)
@@ -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 (file)
index 0000000..83902b9
--- /dev/null
@@ -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");
index d28a8c284da90d57092577f648964d7bdb5731d1..7206547c13ce0dc8dda59458658d843d64520327 100644 (file)
@@ -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);
index 8857d5b9be71dc03d4494562383fc76c779003ef..ee3434f1e949200ba9224669dd3a1c68045ad557 100644 (file)
@@ -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 */
index 31727bf285d0de164d00024a5c34fe539403c94d..e2a4f5f415b2be30d0b223d7fac1e423dec411cf 100644 (file)
@@ -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)
index 24272e022bec926f729d6cf26fd5953e63316ad7..bca2630d006f4d088b4873e08a399983bc845615 100644 (file)
@@ -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;
 
index 8efd17c52f65c5307b6136f14fcd94e2def45b2b..dd84557cf957e37d5a07ebce0b985f5e27d0d3a8 100644 (file)
@@ -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);
index c3d726f334e33c27c7a14f9a4266ba4f4a1aa783..6fabea0309dd9a208d82be0451e07d24af45ab16 100644 (file)
@@ -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 */
index f0c3c77a48d38eb7e2318280ab9492582091c39f..edc344334a7547006901de8e3b5dcd79db66c0a9 100644 (file)
@@ -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 */
index a586a85bfcfe88ccd6378ad476caca6b9aa10a15..2d66984079bb1f1bc928c1aed037851285a22ea6 100644 (file)
@@ -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;
        }
index 54aba474443867f463714e117f14a605ba251803..dd29f46d086b2bf2f60586655fb59ff9647c0b0c 100644 (file)
@@ -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)
index 818b1edaaa9aa5d38f3176828ca2ed3802fb3fde..34f09ef90bb31bbc02f0fda014c27ed3dfa52e72 100644 (file)
@@ -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;
index 01a67f62696f74788e6e4b01eb717f1f6d7fb75c..d0c881dd584677f18c551657d351b6bee435da5f 100644 (file)
@@ -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);
 }
index f959978c7aacdfca1da94b25021f1c86af1bcfb4..cf0f89364d4411f8321bdf69bff7b64725b5612f 100644 (file)
@@ -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;
index e6c403be09a924b7fe795e973dafb227a089affe..4b6808ff0e5df3517f5e72a9fdd71ed6f05d0a9e 100644 (file)
@@ -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,
index 1bea0fc43464f9dcc2ce3f94a87d3628590d6de5..8cd0beebdc3f0464670893eec27222b5d11c8b69 100644 (file)
@@ -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.
index 9055b7dd3dc5b93655088bd83f7911ca678e9d50..b188323c096a62421696fbe394a74d061939ddcb 100644 (file)
@@ -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
index c74bf0dc52cc83baa3a66de3f030f27c7a089335..314129e66d6e8fd47280202cacf19f0793848e58 100644 (file)
@@ -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>
 #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))
index b0e4a3eb33c7dc55d7632fd167cff27e0549b1fb..5b2e76159b419854ca8f69b8c3f99919fbab319f 100644 (file)
@@ -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)
index f03d5ba96db1fe3f5e063e15957056604896570b..bb43cf703efc590bf40ba62a3de52aeea64d71b4 100644 (file)
@@ -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)) {
index aa55f081c505c81bee8bf71ccfe49d85dc27fef7..ee3ba7e6b45e148d3f03c9d671ddefbcbc02f282 100644 (file)
@@ -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" },
        { },
 };
index d20a7f0786ebd9540625caa57c7609412569354f..cf73e969c8cc9a1ac38add953e79f6f9f6892094 100644 (file)
 #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 (file)
index 0000000..5664713
--- /dev/null
@@ -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");
index dc4f14255cc36c755ca90658cdad4c501fda4f71..3b965ad6f4d5ad959f84c920e52767443cb899d4 100644 (file)
@@ -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", },
        {},
index 5a197d9dc7e727b881740b5715e80aa31155ce7e..c2ef0a22ee94639a0db6d3f1e0334d26947059cb 100644 (file)
@@ -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);
index c2639845186b3f8433551116074ae19197ee1866..5911a6dca29199d976fd71b72e818eda1480431c 100644 (file)
@@ -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 (file)
index 0000000..df42257
--- /dev/null
@@ -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");
index ccf54f06396bf251bf42be6007c40db21b84a5c6..28871cd7e3b592681d0839b2830b710e4bce0d60 100644 (file)
@@ -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;
 }
index 4958a363b2c76a29b38c476177bca94fe378ca01..a6b1252c9941884a93dac49ed4c10c828ad0964d 100644 (file)
 #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");
index d497aa05a72f1da5f2e4b56091c06329696d0130..c692dfebd0bab1c808f460349dff194b028f5c5c 100644 (file)
@@ -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);
index 52a216f21ae579644b97c093e89e12306a265595..e5afc3884d74a68a3f180188edb3fb75c5fba762 100644 (file)
@@ -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)
index 2b6d447ad6d641723169cb45af42efdab5cb16be..238e06f13b8a1c977146699d95f1783bbef571e7 100644 (file)
@@ -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 {
index 1718229f627861993cf15223075367cdbb8e63e9..d9d55d12fd5fdef16e3632f3832c7111bb46044d 100644 (file)
@@ -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;
index 91d35df286c345cf0d71a10eee78da76dd437ed6..2d82f8993ea1422111fcfa18f90381b5862024cf 100644 (file)
@@ -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;
 }
 
index 9ecfa4a2421d7b5b815d114e0d551615ce9de0e5..b44aa17d30a764f429fad303d9c562d97975b8d4 100644 (file)
@@ -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;
 }
 
index 799ce8aa70efb2ba30018668d2aebbb6b8d4b107..df577dfe7ffbe18ea45a0f2a91804a1a22f7062e 100644 (file)
@@ -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>
 #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;
index 71b0ec0c370d73aad18d685118c197735c5b2833..1e23f4f8d2c2099cc2f634010e4ff8ff2c2db11c 100644 (file)
@@ -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;
                }
index 167cffff3d4e3436fc60856a43cef5efe3685763..7c74f58fc10194515ffb831ac31ba765315a2c44 100644 (file)
@@ -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)
index 43c63a4f31784adf4ddaf9021fc2dead0098d309..e350eb57f11d6d7f5e989e1d0a5187fb2944fec8 100644 (file)
@@ -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 {
index 3f12a2dd959a0ade49737a9938654acd14a4233f..4f5cf035ac3c9aa524686b67a7d6c57eb62a7456 100644 (file)
@@ -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 {
index c2c8eb668784f08766444b1cabb159c37c92f455..9e74e8fbe074015c7ee149104edf6826424a87a3 100644 (file)
@@ -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;
index 406b29836b19ebe3b8d3196dc51109c6491eb684..abc853968fed7307691aa7593f94b3b310cb80ab 100644 (file)
@@ -10,8 +10,6 @@
 
 #include "affs.h"
 
-extern struct timezone sys_tz;
-
 static char ErrorBuffer[256];
 
 /*
index a7fe57d2cd9a0aa6a59df2cd90778127ebc2bbc3..1ed590aafecf744884c3e55af7cd9627d1c729f8 100644 (file)
@@ -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);
index bec2d1a0c91c3e8ac62eb40a706a3bb704fd404e..e217c511459bbfdd0fe36e745cf2a0c7fe6d2bd2 100644 (file)
 #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);
 
index 51f1a95bff738e61f7b2600ee6584228f309c76c..f754ab68a840a22d1d9eae18f78706a8537f07ea 100644 (file)
@@ -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);
index 9e359fb20c0a5cec2b344fff4ef0b64844f0850d..8e98cf954babb8944a32fdc58fd3c38760933a5a 100644 (file)
@@ -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 *);
index 5b570b6efa280bfdb4b4e9dc930fb6ba6041e3ad..aaf96cb25452cf04a5d7a47f2b506486e67cd502 100644 (file)
@@ -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);
index 8fa3895cda02e9542b68280300801baf9a3c9aa0..683a5b9ce22a372d023bcf998f614afc3d284257 100644 (file)
@@ -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);
index cdb25ebccc4c49c2ac2f4a4c17d998ae99f14941..d76d083f2f0687ccc1e3cea255f041154ae2f662 100644 (file)
@@ -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
index 9c7faa8a9288ca3a015857ca885094eceb989e56..0826e91dacda31129e3d62faf3dd67350dfa30d1 100644 (file)
 /*
  * 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;
index b60500300dd7803e20655d50437aec7dfefeedec..fd8beb9657a2c66f406d3eacadae5ca95e65d805 100644 (file)
@@ -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')
index d1f7048062641e751410cc8f033b641c59d4ec57..9614adc7e7544f3e253260e2d43064a6ad6bd96e 100644 (file)
@@ -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],
index 58df174deb10e5b354a9003ea3ccbfc5240e5cd0..b8602f19981560bc51fe9123689d75eed24f8e0c 100644 (file)
@@ -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;
                }
index 36ca2045009bf342ef507c132921484c7eaf7ded..239e1fb330002f5153cc2bbb1047506254aa5276 100644 (file)
@@ -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;
                        }
index a93f7e6ea4cf935aea64e8266b221a2c53477628..b5c86ffd5033420523934c7153080d8cdc605bea 100644 (file)
@@ -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);
index 628e22a5a5433dae9287bdb94b10c19c6af8a538..d8da2d2e30aedfdd56a2ffc3ac9f80d2325f4ae7 100644 (file)
@@ -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
index 0524cda47a6e72db892c53c7da294aa212a4c17c..95d255219b1eb89c68db91d85037a19af20cf1a6 100644 (file)
@@ -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.
index 5ddaf8625d3b7a1ab3d0128a91dbd3b84b8b9b0b..881b3bd0143faf9e1b492f64d752f16846fea66d 100644 (file)
@@ -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)
index 314e7add99b89eef2c7a881da7526393687d23a2..7cb751dfbeef0a86d94237292d09e591e249f4e7 100644 (file)
@@ -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;
index 24978153c0c4daefd04f2853576db34aa3e8e0fe..e9e3325f29f30cbe0c01c4433441803ff097df58 100644 (file)
@@ -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;
 }
 
index d071e7f23de2a767929338309a5e5c73b5942f97..e1fa69b341b95e5ad970e92664b6a15dd8216e6d 100644 (file)
@@ -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 */
 }
 
index 422fb54b73771f04690e16726f9a85a74c4febfd..9a20e513d7eb89ee21228e6af0a723996c4150a5 100644 (file)
@@ -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);
index 0696161bf59d24cb8471491c2a38c852e0594934..91093cd74f0da15e7f972d9c695f221e5afb454d 100644 (file)
@@ -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 *);
index a1a191634abc1729f94a443ab4eac4cdddaaf54c..7ef18fc656c28568047c30c24adb0bc029bada5c 100644 (file)
@@ -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;
index 228f5bdf07721dabae68349461eb1f24f99a2f33..2e5b3ec85b8f62c967e785697449c773fe0e1337 100644 (file)
@@ -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;
 }
 
index d01ead1bea9a738a5268908fe321eed19af3cc07..23778d385836f56c9cad3be7aa3cdaca2e7c1e69 100644 (file)
@@ -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 */
index d1338544816896dc773fc930b43dc44bcc157266..eb9d48746ab4008acc1a529c37a15ca98a00c882 100644 (file)
@@ -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);
index 07ac24fd92520f604f6d3cfeff4cd4bd2c6ad85c..af7598bff1b51364affd08eba9cfedba8b3acf16 100644 (file)
@@ -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
index ba8819702c56719ae8a1a7b4596662a653a6ef0b..138321b0c6c2b95a8efcef1a5b3183f3126acbb9 100644 (file)
@@ -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);
index ee5e4327de92cc5e487e36dbbc8647f77702155d..83a98330ed6602d7a5ffe03e7f5598a201e6ecf7 100644 (file)
@@ -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];
index b7a7dc963a359229ee7607a8d32b9c28221810bf..4e0388cffe3db3f7ee88b9ab812d89c056d8c60b 100644 (file)
@@ -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);
                }
index a88b1b3e7db3e4f4f5c514062586dbf7a62fa21e..d571e173a9909110ae00452e87ae307cbfbc7730 100644 (file)
@@ -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;
 }
index 7bc20809c99e3936b232c12b7e0a50913a30b76b..2c1036080d5276bcb51314e649e45f0d6f0990a5 100644 (file)
@@ -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
index 081ff8826bf6855630f1a7d5a3c51302d72b87c7..752e30d639045c2ec970b479c680a08d4381d4e1 100644 (file)
@@ -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
index 371b93042520526dc297a00964267da39253923a..0430ed05d3b9f0511975fbef5ca89ec14faf3e92 100644 (file)
@@ -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 (file)
index 0000000..cdd1cc2
--- /dev/null
@@ -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 */
index 35c8ffb0136f5b88935ee56a504019b0b079e77b..40728cf1c452a8d5fbf8a7065864ad5f34656ad8 100644 (file)
@@ -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);
 
index 4b2a0e11cc5be7245f343ded8049f7d3e86f0855..9d957b7ae095ed7f2980db140a9c21a6aae70084 100644 (file)
@@ -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;
index cbbb96fcead9208da224866d849f3b3dfcf0337e..f33f831eb3c801925eed9f8d3333c65df8c57d08 100644 (file)
@@ -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.
index fa0d74e0642812dc21e9c32b8e4fc57514238117..02d11ee7f19d1515ac47178575d653e52fc8e4e8 100644 (file)
@@ -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
index b43f4752304e26410a0a870a6d8a15edd48058fd..1c9effa25e2632497384e973a28954f7e33aedbc 100644 (file)
@@ -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;
index 1d2a6ab6b8bbae61a679df9f46f1d97012831235..9b2022ab4d852744e1a558a3877fa8f676611a46 100644 (file)
@@ -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 (file)
index 0809435..0000000
+++ /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 */
index fea49b5da12a99bfa6c87b865a461a2a28e0495b..378c5ee75f78f5e1a521d87afeaf13fe21999af5 100644 (file)
@@ -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)
index 750196fcc0a5144aebb1df7f67102502c871a990..ab1e0392b5ac1ce89c80dc2bf0e4e4ccc7a736bd 100644 (file)
@@ -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();                                            \
        }                                                               \
 }
 
index d36977e029af065a7b104c381891db710050850b..e6edfe51575a6f5a452e937376add0afdb7c5d48 100644 (file)
@@ -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);
index 3eeee9672a4ac087fe57a691a1579637f810f5a1..6eb567ac56bc10394eb69793ad30b000545afe17 100644 (file)
@@ -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
index be95b9262801880f7a835f7954f14c1f0c1e2397..aab0f427edb58d59a868595bf6e5238a2546f43d 100644 (file)
 #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 {
index 1c505e09042283199905b9d5c25557dbdc2ea17d..3ee28ae02cc89cb0c0d3b2a9ca112c1edfda2e96 100644 (file)
@@ -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
index bece48c3461edd55ba4a9ea5fc1b8662be6bda0f..ad1bd7787bbb0c3298e2f9790b0edd5322227639 100644 (file)
@@ -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)
index 89ec862da2d49e8fca7b7475b3764f1f9b127901..800a0daede7e4d8b8940288bd30dfb43a6e922a8 100644 (file)
@@ -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);
index b5ef4f7946dca3a155b0788993c66512afc8fc4b..9b3c85f8a53825330b99015e34af9d2117393f06 100644 (file)
@@ -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;
index c3f0326e98db1ca9a4e0afe8e494b857992ca851..e8075b24749775f254c4d821ea1fb2c4a8a4c5f1 100644 (file)
@@ -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.
index 7fc9f9f3a26b874c7fa558d22618273e9eb357d3..01454796ba3c59e20b4db8e71fdf7a17c74f9ad7 100644 (file)
--- 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);
index d73b7af581e23a87617c8e165d9561b76f8d2c0f..88adc329888c5df2d0e93f23fe306995f498d68b 100644 (file)
@@ -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)
index 70a504601dc3909c15c424b1d2b1afdf25b9b341..b20d544f20c2a12c24ac492c4dae56961e0b959d 100644 (file)
@@ -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;
index ae51670878457d9b0db2498ee032d5735933e96f..5c5987f1081964109f96cd6cc52b285b948f0a9e 100644 (file)
@@ -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
index 2bee072268d94da0b7e19e60ee5ee90267ea2b63..2abf9f6e9a61866302c858e408c8dd7b5ec93dd5 100644 (file)
@@ -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;
 }
index 041b5899d5e2d0c70f791224d4e5697ddff2880b..db97b791390fa0ef3f4aa10d1bd5e53fe6e921b8 100644 (file)
@@ -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];
 
index 7a6e69441f75504c5e6dcf19d5accd14aa03feb9..e3962d63e3681408f43f90b228b63facc29ba4e7 100644 (file)
@@ -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') {
index 46322019ab7d388ad62029b42248d2c0a5ecaf72..0bcebffc4e77d5f45571e38ddc5dcc38f40594f4 100644 (file)
@@ -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)
 {
 }
index ff7fd80bef994d07730ac87de9602dc750600934..49e9537f3673714772c4aa042973f1f53b5ed56c 100644 (file)
@@ -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);
index e7ad58c5fbeb3c59cffd0cfe6ffe40570e1f96ca..4e35a5d767ed2f50c69df7dbdbcf0e3d9885777f 100644 (file)
@@ -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
index d6b4bc496408e5ce44735606286cb923fbbefee3..7512dc978f1872fe4a395868ed0f3cbd30de2ad0 100644 (file)
@@ -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
index 31fe79e31ab8d4940aa9d4e930c674e52ecee467..dfba05521748ff54d82e2084bef91dd5906b9c7e 100644 (file)
@@ -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 (file)
index a7af6f8..0000000
+++ /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;
-}
index f3c6ff596414e6f9bd1cf58071fadfd4c7a31b35..2fc20aa06f848fcebd8aa30d238942f5ec399690 100644 (file)
 #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
index 29033f319aea1f8f48e85374884f657a130519a4..58b78ba57439c76e89a9d0a911ac3960e744ebf1 100644 (file)
@@ -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);
index 6ac48de04c0e57ea9be72a4344fc767df2649c48..ab0d30e1e18fca244f9e2e1749b8d38de10fe6aa 100644 (file)
@@ -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;
 }
index 0c7e9ab2d88f79e99c434703b7d9e0e6fa9edcfb..0b79908dfe892e5bc635408538a8049c844a2888 100644 (file)
@@ -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.
index ba3cd0a35640db2672970612fa644c3aab70633d..ec337f64f52ddada251c9126561e5e38a38093e5 100644 (file)
@@ -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"
 
 /**
@@ -1100,6 +1101,62 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
        return string(buf, end, ip4_addr, spec);
 }
 
+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
index 474c644a0dc6deafea451935e6d44b72d5e1903e..963bc4add9af88838b494e6dd56b2bf2239548a2 100644 (file)
--- 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)
@@ -140,6 +142,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
@@ -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);
index e229970e4223ff02cb24b43b9e47e5ee211555d6..1cc6bfbd872ee17122b6e85859662696f595a363 100644 (file)
@@ -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
index 93d28c7e54201de5549dab1a3dd696d785a06302..7f855206e7fb2bb1f9a30fcf7745bff7a2ae3adb 100644 (file)
--- 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:
index c43d557941f807471a3c39963f77a8ba3d32dd8a..ace93454ce8ebe10f0b3cf5278aafd0a0d5fe4df 100644 (file)
 #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);
index 154aac8411c592816891e4897408e509d9b24785..eb2b2ea301309887972c148bb80aedf8a6731b9b 100644 (file)
--- 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;
index 6f5e621f220ae0d6c419cff55aa87094c12f59d0..88a1bc3804d148972761276b347e258873a1b59e 100644 (file)
@@ -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';
                }
index a64fa15790e53f8ad0eda7c53b73be8bd849f2aa..1d5341f3761dfe1e57cc6505493bf270cca672de 100644 (file)
@@ -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,
index b8a0924064ef79abae8999e05d4622df961209c0..b666959f17c0856f8303fee7467a5e7cc4ff4962 100644 (file)
@@ -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;
 
index 4c3ba1c8d682d16abe0912f80525a84d184130db..885b4aba369565a8edcf6aaaead9b921d043d2b8 100644 (file)
@@ -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);
index daad6022c689c47a66a47e7a89a83c0c848c53d6..d7197649dba689bae96edb10848e8c1c3d4a63f6 100644 (file)
@@ -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;
        }
 
index b4d691db955ed451954381e01baeed57ca588d11..791fac4fd74534e0481d409a182c2d5e5544deac 100644 (file)
@@ -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 &&
index a55c27b75ee5667a7046ad54855f8ddd90c57b05..459611577d3dfa29f72442dfe1dcdfe4f2c6a502 100644 (file)
@@ -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)
 {
index 4d08b398411fdec9b6707b4cd0db2fd73f1b13fa..374abf44363615004537cb895d3b55bc410ae99b 100755 (executable)
@@ -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;
index 5de5660cb7085ac899df9f9dc87989bc931f24be..fdebd66f8fc16c2db0189480318c5f8599aebdf0 100644 (file)
@@ -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"
index 8fac3fd697a6ec34c4908ca60386f2dee3c29bb0..ba8700428e21dd1612d8c6ae4ddde0e0e964433e 100644 (file)
@@ -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 (file)
index 0000000..fc7fd52
--- /dev/null
@@ -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