Merge branch 'akpm' (Andrew's patch-bomb)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 18 Dec 2012 04:58:12 +0000 (20:58 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 18 Dec 2012 04:58:12 +0000 (20:58 -0800)
Merge misc patches from Andrew Morton:
 "Incoming:

   - lots of misc stuff

   - backlight tree updates

   - lib/ updates

   - Oleg's percpu-rwsem changes

   - checkpatch

   - rtc

   - aoe

   - more checkpoint/restart support

  I still have a pile of MM stuff pending - Pekka should be merging
  later today after which that is good to go.  A number of other things
  are twiddling thumbs awaiting maintainer merges."

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (180 commits)
  scatterlist: don't BUG when we can trivially return a proper error.
  docs: update documentation about /proc/<pid>/fdinfo/<fd> fanotify output
  fs, fanotify: add @mflags field to fanotify output
  docs: add documentation about /proc/<pid>/fdinfo/<fd> output
  fs, notify: add procfs fdinfo helper
  fs, exportfs: add exportfs_encode_inode_fh() helper
  fs, exportfs: escape nil dereference if no s_export_op present
  fs, epoll: add procfs fdinfo helper
  fs, eventfd: add procfs fdinfo helper
  procfs: add ability to plug in auxiliary fdinfo providers
  tools/testing/selftests/kcmp/kcmp_test.c: print reason for failure in kcmp_test
  breakpoint selftests: print failure status instead of cause make error
  kcmp selftests: print fail status instead of cause make error
  kcmp selftests: make run_tests fix
  mem-hotplug selftests: print failure status instead of cause make error
  cpu-hotplug selftests: print failure status instead of cause make error
  mqueue selftests: print failure status instead of cause make error
  vm selftests: print failure status instead of cause make error
  ubifs: use prandom_bytes
  mtd: nandsim: use prandom_bytes
  ...

185 files changed:
.gitignore
Documentation/00-INDEX
Documentation/ABI/README
Documentation/DocBook/kernel-api.tmpl
Documentation/aoe/aoe.txt
Documentation/backlight/lp855x-driver.txt
Documentation/devicetree/bindings/rtc/imxdi-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-omap.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/filesystems/vfat.txt
Documentation/kernel-parameters.txt
Documentation/security/00-INDEX
Documentation/sparse.txt
MAINTAINERS
arch/Kconfig
arch/arm/mach-davinci/devices-da8xx.c
arch/arm64/include/asm/unistd.h
arch/arm64/kernel/sys_compat.c
arch/frv/kernel/setup.c
arch/frv/mm/init.c
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/sys_ppc32.c
arch/sparc/include/asm/unistd.h
arch/sparc/kernel/sys_sparc32.c
arch/tile/include/asm/compat.h
arch/tile/include/asm/unistd.h
arch/tile/kernel/compat.c
arch/x86/include/uapi/asm/hw_breakpoint.h
arch/x86/include/uapi/asm/setup.h
block/Kconfig
drivers/block/aoe/aoe.h
drivers/block/aoe/aoeblk.c
drivers/block/aoe/aoechr.c
drivers/block/aoe/aoecmd.c
drivers/block/aoe/aoedev.c
drivers/block/aoe/aoemain.c
drivers/block/aoe/aoenet.c
drivers/dma/dmatest.c
drivers/mtd/nand/nandsim.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/wireless/Kconfig
drivers/of/fdt.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/eeepc-wmi.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-da9055.c [new file with mode: 0644]
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-imxdi.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf8523.c [new file with mode: 0644]
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-tps65910.c
drivers/rtc/rtc-vt8500.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_io.h
drivers/usb/musb/tusb6010.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/atmel-pwm-bl.c
drivers/video/backlight/backlight.c
drivers/video/backlight/corgi_lcd.c
drivers/video/backlight/da903x_bl.c
drivers/video/backlight/da9052_bl.c
drivers/video/backlight/generic_bl.c
drivers/video/backlight/hp680_bl.c
drivers/video/backlight/ili9320.c
drivers/video/backlight/ili9320.h
drivers/video/backlight/jornada720_bl.c
drivers/video/backlight/l4f00242t03.c
drivers/video/backlight/lcd.c
drivers/video/backlight/lm3630_bl.c
drivers/video/backlight/lm3639_bl.c
drivers/video/backlight/lms283gf05.c
drivers/video/backlight/lp855x_bl.c
drivers/video/backlight/max8925_bl.c
drivers/video/backlight/omap1_bl.c
drivers/video/backlight/pandora_bl.c
drivers/video/backlight/pcf50633-backlight.c
drivers/video/backlight/platform_lcd.c
drivers/video/backlight/s6e63m0.c
drivers/video/backlight/tdo24m.c
drivers/video/backlight/tosa_bl.c
drivers/video/backlight/tosa_lcd.c
drivers/video/backlight/vgg2432a4.c
fs/bad_inode.c
fs/binfmt_elf.c
fs/binfmt_em86.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/block_dev.c
fs/btrfs/file.c
fs/ceph/dir.c
fs/ceph/file.c
fs/cifs/cifsfs.c
fs/configfs/dir.c
fs/eventfd.c
fs/eventpoll.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext3/dir.c
fs/ext4/dir.c
fs/ext4/file.c
fs/fat/fat.h
fs/fat/inode.c
fs/fat/misc.c
fs/fuse/file.c
fs/gfs2/file.c
fs/libfs.c
fs/nfs/dir.c
fs/nfs/file.c
fs/notify/Makefile
fs/notify/fanotify/fanotify_user.c
fs/notify/fdinfo.c [new file with mode: 0644]
fs/notify/fdinfo.h [new file with mode: 0644]
fs/notify/inode_mark.c
fs/notify/inotify/inotify_user.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/proc/array.c
fs/proc/fd.c
fs/proc/proc_devtree.c
fs/proc/task_mmu.c
fs/pstore/inode.c
fs/read_write.c
fs/seq_file.c
fs/signalfd.c
fs/ubifs/debug.c
fs/ubifs/dir.c
include/asm-generic/io.h
include/linux/backlight.h
include/linux/binfmts.h
include/linux/compat.h
include/linux/compiler.h
include/linux/exportfs.h
include/linux/fs.h
include/linux/ftrace.h
include/linux/init.h
include/linux/kernel.h
include/linux/percpu-rwsem.h
include/linux/platform_data/lp855x.h
include/linux/proc_fs.h
include/linux/ptrace.h
include/linux/random.h
include/linux/sched.h
include/linux/string.h
include/linux/syscalls.h
include/uapi/linux/ptrace.h
kernel/cgroup.c
kernel/compat.c
kernel/module.c
kernel/pid.c
kernel/printk.c
kernel/ptrace.c
kernel/trace/ftrace.c
kernel/trace/trace_uprobe.c
kernel/watchdog.c
lib/Kconfig
lib/Makefile
lib/dynamic_debug.c
lib/interval_tree_test_main.c
lib/kstrtox.c
lib/percpu-rwsem.c [new file with mode: 0644]
lib/random32.c
lib/rbtree_test.c
lib/scatterlist.c
lib/vsprintf.c
mm/memory.c
mm/shmem.c
scripts/checkpatch.pl
sound/Kconfig
sound/sound_core.c
tools/testing/selftests/breakpoints/Makefile
tools/testing/selftests/cpu-hotplug/Makefile
tools/testing/selftests/kcmp/Makefile
tools/testing/selftests/kcmp/kcmp_test.c
tools/testing/selftests/memory-hotplug/Makefile
tools/testing/selftests/mqueue/Makefile
tools/testing/selftests/vm/Makefile

index 92bd0e45dfa165cfdaddb3de4f91e2db61a7a927..3b8b9b33be380b75f9a4d19a4680723f3febfce7 100644 (file)
@@ -60,7 +60,6 @@ modules.builtin
 # Generated include files
 #
 include/config
-include/linux/version.h
 include/generated
 arch/*/include/generated
 
index ceb1ff735469995b560f0cdf07227407be682235..8afe64fb20099f0be31c863b7854614d4b250b87 100644 (file)
@@ -136,8 +136,6 @@ fault-injection/
        - dir with docs about the fault injection capabilities infrastructure.
 fb/
        - directory with info on the frame buffer graphics abstraction layer.
-feature-removal-schedule.txt
-       - list of files and features that are going to be removed.
 filesystems/
        - info on the vfs and the various filesystems that Linux supports.
 firmware_class/
index 9feaf16f1617320038422cc32cb885a21f9075cd..10069828568b4e6d6b698e99c3aaccfe16128e12 100644 (file)
@@ -36,9 +36,6 @@ The different levels of stability are:
        the kernel, but are marked to be removed at some later point in
        time.  The description of the interface will document the reason
        why it is obsolete and when it can be expected to be removed.
-       The file Documentation/feature-removal-schedule.txt may describe
-       some of these interfaces, giving a schedule for when they will
-       be removed.
 
   removed/
        This directory contains a list of the old interfaces that have
index 00687ee9d363ef0d7a57461ffa21e153ce831bcb..f75ab4c1b281119672df234624f1ae7aa80919c2 100644 (file)
@@ -58,6 +58,9 @@
 
      <sect1><title>String Conversions</title>
 !Elib/vsprintf.c
+!Finclude/linux/kernel.h kstrtol
+!Finclude/linux/kernel.h kstrtoul
+!Elib/kstrtox.c
      </sect1>
      <sect1><title>String Manipulation</title>
 <!-- All functions are exported at now
index bfc9cb19abcd56ca23f240c9854f67e0c9f3ec0f..c71487d399d14688206afbe818be88c093ffde29 100644 (file)
@@ -125,7 +125,9 @@ DRIVER OPTIONS
   The aoe_deadsecs module parameter determines the maximum number of
   seconds that the driver will wait for an AoE device to provide a
   response to an AoE command.  After aoe_deadsecs seconds have
-  elapsed, the AoE device will be marked as "down".
+  elapsed, the AoE device will be marked as "down".  A value of zero
+  is supported for testing purposes and makes the aoe driver keep
+  trying AoE commands forever.
 
   The aoe_maxout module parameter has a default of 128.  This is the
   maximum number of unresponded packets that will be sent to an AoE
index f5e4caafab7d6a07dbd030cc017fafbe2458af2b..1529394cfe8b3ed51ca44391b81ed16c8635325d 100644 (file)
@@ -35,11 +35,8 @@ For supporting platform specific data, the lp855x platform data can be used.
 * mode : Brightness control mode. PWM or register based.
 * device_control : Value of DEVICE CONTROL register.
 * initial_brightness : Initial value of backlight brightness.
-* pwm_data : Platform specific pwm generation functions.
+* period_ns : Platform specific PWM period value. unit is nano.
             Only valid when brightness is pwm input mode.
-            Functions should be implemented by PWM driver.
-            - pwm_set_intensity() : set duty of PWM
-            - pwm_get_intensity() : get current duty of PWM
 * load_new_rom_data :
        0 : use default configuration data
        1 : update values of eeprom or eprom registers on loading driver
@@ -71,8 +68,5 @@ static struct lp855x_platform_data lp8556_pdata = {
        .mode = PWM_BASED,
        .device_control = PWM_CONFIG(LP8556),
        .initial_brightness = INITIAL_BRT,
-       .pwm_data = {
-                    .pwm_set_intensity = platform_pwm_set_intensity,
-                    .pwm_get_intensity = platform_pwm_get_intensity,
-                    },
+       .period_ns = 1000000,
 };
diff --git a/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt
new file mode 100644 (file)
index 0000000..c9d80d7
--- /dev/null
@@ -0,0 +1,17 @@
+* i.MX25 Real Time Clock controller
+
+This binding supports the following chips: i.MX25, i.MX53
+
+Required properties:
+- compatible: should be: "fsl,imx25-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: rtc alarm interrupt
+
+Example:
+
+rtc@80056000 {
+       compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
+       reg = <0x80056000 2000>;
+       interrupts = <29>;
+};
diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
new file mode 100644 (file)
index 0000000..b47aa41
--- /dev/null
@@ -0,0 +1,17 @@
+TI Real Time Clock
+
+Required properties:
+- compatible: "ti,da830-rtc"
+- reg: Address range of rtc register set
+- interrupts: rtc timer, alarm interrupts in order
+- interrupt-parent: phandle for the interrupt controller
+
+Example:
+
+rtc@1c23000 {
+       compatible = "ti,da830-rtc";
+       reg = <0x23000 0x1000>;
+       interrupts = <19
+                     19>;
+       interrupt-parent = <&intc>;
+};
index 3844d21d6ca32223838b7856a2f353bf56ef2417..fd8d0d594fc7c9fd6bd1a5baa107968a9c9fab01 100644 (file)
@@ -41,6 +41,7 @@ Table of Contents
   3.5  /proc/<pid>/mountinfo - Information about mounts
   3.6  /proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
+  3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
 
   4    Configuring procfs
   4.1  Mount options
@@ -142,7 +143,7 @@ Table 1-1: Process specific entries in /proc
  pagemap       Page table
  stack         Report full stack trace, enable via CONFIG_STACKTRACE
  smaps         a extension based on maps, showing the memory consumption of
-               each mapping
+               each mapping and flags associated with it
 ..............................................................................
 
 For example, to get the status information of a process, all you have to do is
@@ -181,6 +182,7 @@ read the file /proc/PID/status:
   CapPrm: 0000000000000000
   CapEff: 0000000000000000
   CapBnd: ffffffffffffffff
+  Seccomp:        0
   voluntary_ctxt_switches:        0
   nonvoluntary_ctxt_switches:     1
 
@@ -237,6 +239,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
  CapPrm                      bitmap of permitted capabilities
  CapEff                      bitmap of effective capabilities
  CapBnd                      bitmap of capabilities bounding set
+ Seccomp                     seccomp mode, like prctl(PR_GET_SECCOMP, ...)
  Cpus_allowed                mask of CPUs on which this process may run
  Cpus_allowed_list           Same as previous, but in "list format"
  Mems_allowed                mask of memory nodes allowed to this process
@@ -415,8 +418,9 @@ Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 Locked:              374 kB
+VmFlags: rd ex mr mw me de
 
-The first of these lines shows the same information as is displayed for the
+the first of these lines shows the same information as is displayed for the
 mapping in /proc/PID/maps.  The remaining lines show the size of the mapping
 (size), the amount of the mapping that is currently resident in RAM (RSS), the
 process' proportional share of this mapping (PSS), the number of clean and
@@ -430,6 +434,41 @@ and a page is modified, the file page is replaced by a private anonymous copy.
 "Swap" shows how much would-be-anonymous memory is also used, but out on
 swap.
 
+"VmFlags" field deserves a separate description. This member represents the kernel
+flags associated with the particular virtual memory area in two letter encoded
+manner. The codes are the following:
+    rd  - readable
+    wr  - writeable
+    ex  - executable
+    sh  - shared
+    mr  - may read
+    mw  - may write
+    me  - may execute
+    ms  - may share
+    gd  - stack segment growns down
+    pf  - pure PFN range
+    dw  - disabled write to the mapped file
+    lo  - pages are locked in memory
+    io  - memory mapped I/O area
+    sr  - sequential read advise provided
+    rr  - random read advise provided
+    dc  - do not copy area on fork
+    de  - do not expand area on remapping
+    ac  - area is accountable
+    nr  - swap space is not reserved for the area
+    ht  - area uses huge tlb pages
+    nl  - non-linear mapping
+    ar  - architecture specific flag
+    dd  - do not include area into core dump
+    mm  - mixed map area
+    hg  - huge page advise flag
+    nh  - no-huge page advise flag
+    mg  - mergable advise flag
+
+Note that there is no guarantee that every flag and associated mnemonic will
+be present in all further kernel releases. Things get changed, the flags may
+be vanished or the reverse -- new added.
+
 This file is only present if the CONFIG_MMU kernel configuration option is
 enabled.
 
@@ -1595,6 +1634,93 @@ pids, so one need to either stop or freeze processes being inspected
 if precise results are needed.
 
 
+3.7    /proc/<pid>/fdinfo/<fd> - Information about opened file
+---------------------------------------------------------------
+This file provides information associated with an opened file. The regular
+files have at least two fields -- 'pos' and 'flags'. The 'pos' represents
+the current offset of the opened file in decimal form [see lseek(2) for
+details] and 'flags' denotes the octal O_xxx mask the file has been
+created with [see open(2) for details].
+
+A typical output is
+
+       pos:    0
+       flags:  0100002
+
+The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
+pair provide additional information particular to the objects they represent.
+
+       Eventfd files
+       ~~~~~~~~~~~~~
+       pos:    0
+       flags:  04002
+       eventfd-count:  5a
+
+       where 'eventfd-count' is hex value of a counter.
+
+       Signalfd files
+       ~~~~~~~~~~~~~~
+       pos:    0
+       flags:  04002
+       sigmask:        0000000000000200
+
+       where 'sigmask' is hex value of the signal mask associated
+       with a file.
+
+       Epoll files
+       ~~~~~~~~~~~
+       pos:    0
+       flags:  02
+       tfd:        5 events:       1d data: ffffffffffffffff
+
+       where 'tfd' is a target file descriptor number in decimal form,
+       'events' is events mask being watched and the 'data' is data
+       associated with a target [see epoll(7) for more details].
+
+       Fsnotify files
+       ~~~~~~~~~~~~~~
+       For inotify files the format is the following
+
+       pos:    0
+       flags:  02000000
+       inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:7e9e0000640d1b6d
+
+       where 'wd' is a watch descriptor in decimal form, ie a target file
+       descriptor number, 'ino' and 'sdev' are inode and device where the
+       target file resides and the 'mask' is the mask of events, all in hex
+       form [see inotify(7) for more details].
+
+       If the kernel was built with exportfs support, the path to the target
+       file is encoded as a file handle.  The file handle is provided by three
+       fields 'fhandle-bytes', 'fhandle-type' and 'f_handle', all in hex
+       format.
+
+       If the kernel is built without exportfs support the file handle won't be
+       printed out.
+
+       If there is no inotify mark attached yet the 'inotify' line will be omitted.
+
+       For fanotify files the format is
+
+       pos:    0
+       flags:  02
+       fanotify flags:10 event-flags:0
+       fanotify mnt_id:12 mflags:40 mask:38 ignored_mask:40000003
+       fanotify ino:4f969 sdev:800013 mflags:0 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:69f90400c275b5b4
+
+       where fanotify 'flags' and 'event-flags' are values used in fanotify_init
+       call, 'mnt_id' is the mount point identifier, 'mflags' is the value of
+       flags associated with mark which are tracked separately from events
+       mask. 'ino', 'sdev' are target inode and device, 'mask' is the events
+       mask and 'ignored_mask' is the mask of events which are to be ignored.
+       All in hex format. Incorporation of 'mflags', 'mask' and 'ignored_mask'
+       does provide information about flags and mask used in fanotify_mark
+       call [see fsnotify manpage for details].
+
+       While the first three lines are mandatory and always printed, the rest is
+       optional and may be omitted if no marks created yet.
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
index de1e6c4dccff047766f1bfc1801319ef28cdf0d1..d230dd9c99b07bad6cbbc8cd9445b798188b8684 100644 (file)
@@ -111,6 +111,15 @@ tz=UTC        -- Interpret timestamps as UTC rather than local time.
                  useful when mounting devices (like digital cameras)
                  that are set to UTC in order to avoid the pitfalls of
                  local time.
+time_offset=minutes
+             -- Set offset for conversion of timestamps from local time
+                used by FAT to UTC. I.e. <minutes> minutes will be subtracted
+                from each timestamp to convert it to UTC used internally by
+                Linux. This is useful when time zone set in sys_tz is
+                not the time zone used by the filesystem. Note that this
+                option still does not provide correct time stamps in all
+                cases in presence of DST - time stamps in a different DST
+                setting will be off by one hour.
 
 showexec      -- If set, the execute permission bits of the file will be
                 allowed only if the extension part of the name is .EXE,
index ea8e5b48557674a3fc7725234237798aeef68a04..ddd84d627185f4b83fcd27fff46054ad6f94ff69 100644 (file)
@@ -1503,9 +1503,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        mem=nn[KMG]     [KNL,BOOT] Force usage of a specific amount of memory
                        Amount of memory to be used when the kernel is not able
                        to see the whole system memory or for test.
-                       [X86-32] Use together with memmap= to avoid physical
-                       address space collisions. Without memmap= PCI devices
-                       could be placed at addresses belonging to unused RAM.
+                       [X86] Work as limiting max address. Use together
+                       with memmap= to avoid physical address space collisions.
+                       Without memmap= PCI devices could be placed at addresses
+                       belonging to unused RAM.
 
        mem=nopentium   [BUGS=X86-32] Disable usage of 4MB pages for kernel
                        memory.
index eeed1de546d4d178a8d6c8e91da1012b71d9c970..414235c1fcfcdd3f4a8ca191df7edf7cf21049ad 100644 (file)
@@ -12,6 +12,8 @@ apparmor.txt
        - documentation on the AppArmor security extension.
 credentials.txt
        - documentation about credentials in Linux.
+keys-ecryptfs.txt
+       - description of the encryption keys for the ecryptfs filesystem.
 keys-request-key.txt
        - description of the kernel key request service.
 keys-trusted-encrypted.txt
index 4909d41163564c0fcc7fefb4e6a4c6e25183bf3b..eceab1308a8c2fbde6722232db18bbb57a6e7f2e 100644 (file)
@@ -49,6 +49,24 @@ be generated without __CHECK_ENDIAN__.
 __bitwise - noisy stuff; in particular, __le*/__be* are that.  We really
 don't want to drown in noise unless we'd explicitly asked for it.
 
+Using sparse for lock checking
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following macros are undefined for gcc and defined during a sparse
+run to use the "context" tracking feature of sparse, applied to
+locking.  These annotations tell sparse when a lock is held, with
+regard to the annotated function's entry and exit.
+
+__must_hold - The specified lock is held on function entry and exit.
+
+__acquires - The specified lock is held on function exit, but not entry.
+
+__releases - The specified lock is held on function entry, but not exit.
+
+If the function enters and exits without the lock held, acquiring and
+releasing the lock inside the function in a balanced way, no
+annotation is needed.  The tree annotations above are for cases where
+sparse would otherwise report a context imbalance.
 
 Getting sparse
 ~~~~~~~~~~~~~~
index 6892b26025ba279712a6f616b6f0d7e1af83d3b7..4e2a1f67a1fcf00b553e8190947368d240d74b44 100644 (file)
@@ -1280,7 +1280,7 @@ F:        Documentation/hwmon/asc7621
 F:     drivers/hwmon/asc7621.c
 
 ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
-M:     Corentin Chary <corentincj@iksaif.net>
+M:     Corentin Chary <corentin.chary@gmail.com>
 L:     acpi4asus-user@lists.sourceforge.net
 L:     platform-driver-x86@vger.kernel.org
 W:     http://acpi4asus.sf.net
@@ -1929,7 +1929,7 @@ F:        scripts/checkpatch.pl
 
 CHINESE DOCUMENTATION
 M:     Harry Wei <harryxiyou@gmail.com>
-L:     xiyoulinuxkernelgroup@googlegroups.com
+L:     xiyoulinuxkernelgroup@googlegroups.com (subscribers-only)
 L:     linux-kernel@zh-kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/zh_CN/
@@ -2982,7 +2982,6 @@ L:        linux-ext4@vger.kernel.org
 S:     Maintained
 F:     Documentation/filesystems/ext3.txt
 F:     fs/ext3/
-F:     include/linux/ext3*
 
 EXT4 FILE SYSTEM
 M:     "Theodore Ts'o" <tytso@mit.edu>
@@ -3129,7 +3128,8 @@ W:        http://ieee1394.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git
 S:     Maintained
 F:     drivers/firewire/
-F:     include/linux/firewire*.h
+F:     include/linux/firewire.h
+F:     include/uapi/linux/firewire*.h
 F:     tools/firewire/
 
 FIRMWARE LOADER (request_firmware)
@@ -4314,7 +4314,6 @@ M:        Jan Kara <jack@suse.cz>
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 F:     fs/jbd/
-F:     include/linux/ext3_jbd.h
 F:     include/linux/jbd.h
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
@@ -6492,7 +6491,7 @@ F:        drivers/media/pci/saa7146/
 F:     include/media/saa7146*
 
 SAMSUNG LAPTOP DRIVER
-M:     Corentin Chary <corentincj@iksaif.net>
+M:     Corentin Chary <corentin.chary@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/samsung-laptop.c
@@ -7546,6 +7545,13 @@ S:       Maintained
 F:     sound/soc/codecs/lm49453*
 F:     sound/soc/codecs/isabelle*
 
+TI LP855x BACKLIGHT DRIVER
+M:     Milo Kim <milo.kim@ti.com>
+S:     Maintained
+F:     Documentation/backlight/lp855x-driver.txt
+F:     drivers/video/backlight/lp855x_bl.c
+F:     include/linux/platform_data/lp855x.h
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M:     Peter Ujfalusi <peter.ujfalusi@ti.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
index 34884faf98cd26f3f24c6483dd98b10855387232..54ffd0f9df21b7d9f28789104dd48e5bdcf5a965 100644 (file)
@@ -80,6 +80,7 @@ config UPROBES
        bool "Transparent user-space probes (EXPERIMENTAL)"
        depends on UPROBE_EVENT && PERF_EVENTS
        default n
+       select PERCPU_RWSEM
        help
          Uprobes is the user-space counterpart to kprobes: they
          enable instrumentation applications (such as 'perf probe')
index fcdbe437409e3a5141b5b7231a143fecf7c933a4..2d5502d84a223aaf9b0a05ccb80d284393c9a815 100644 (file)
@@ -725,7 +725,7 @@ static struct resource da8xx_rtc_resources[] = {
 };
 
 static struct platform_device da8xx_rtc_device = {
-       .name           = "omap_rtc",
+       .name           = "da830-rtc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(da8xx_rtc_resources),
        .resource       = da8xx_rtc_resources,
@@ -734,17 +734,6 @@ static struct platform_device da8xx_rtc_device = {
 int da8xx_register_rtc(void)
 {
        int ret;
-       void __iomem *base;
-
-       base = ioremap(DA8XX_RTC_BASE, SZ_4K);
-       if (WARN_ON(!base))
-               return -ENOMEM;
-
-       /* Unlock the rtc's registers */
-       __raw_writel(0x83e70b13, base + 0x6c);
-       __raw_writel(0x95a4f1e0, base + 0x70);
-
-       iounmap(base);
 
        ret = platform_device_register(&da8xx_rtc_device);
        if (!ret)
index d69aeea6da1e83fd6fc36c435007f0104ba96af0..76fb7dd3350aef410b3946095ae98665e5e6a92c 100644 (file)
@@ -20,6 +20,7 @@
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
index f7b05edf8ce36c925196b59dcf4c03ac12259b73..26e9c4eeaba82a20f539991c754d5e40cb161e3a 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/unistd32.h>
 
-asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
-                                               struct compat_timespec __user *interval)
-{
-       struct timespec t;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-
-       set_fs(KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
-       set_fs(old_fs);
-       if (put_compat_timespec(&t, interval))
-               return -EFAULT;
-       return ret;
-}
-
 static inline void
 do_compat_cache_op(unsigned long start, unsigned long end, int flags)
 {
index b8993c87d3de8473d95141560fdb82aef0aa1085..3cb3392f799e02886e8a93b88907a2ca7a9f0215 100644 (file)
@@ -804,9 +804,9 @@ void __init setup_arch(char **cmdline_p)
 
        BUG_ON(memory_start == memory_end);
 
-       init_mm.start_code = (unsigned long) &_stext;
-       init_mm.end_code = (unsigned long) &_etext;
-       init_mm.end_data = (unsigned long) &_edata;
+       init_mm.start_code = (unsigned long) _stext;
+       init_mm.end_code = (unsigned long) _etext;
+       init_mm.end_data = (unsigned long) _edata;
 #if 0 /* DAVIDM - don't set brk just incase someone decides to use it */
        init_mm.brk = (unsigned long) &_end;
 #else
@@ -814,10 +814,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 #ifdef DEBUG
-       printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n",
-              (int) &_stext, (int) &_etext,
-              (int) &_sdata, (int) &_edata,
-              (int) &_sbss, (int) &_ebss);
+       printk("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n",
+              _stext, _etext, _sdata, _edata, __bss_start, __bss_stop);
 #endif
 
 #ifdef CONFIG_VT
index a19effcccb34cbf1a60e0404e18a01758ba84d61..92e97b0894a68bbebcc138bf93305b69624c0ee7 100644 (file)
@@ -146,7 +146,7 @@ void __init mem_init(void)
 
 #else
        codek = (_etext - _stext) >> 10;
-       datak = 0; //(_ebss - _sdata) >> 10;
+       datak = 0; //(__bss_stop - _sdata) >> 10;
 #endif
 
        tmp = nr_free_pages() << PAGE_SHIFT;
index c4231973edd351eacf480dacbdb3d1a529b1b08c..3c82daf8be998a7db1e65d8d3d0479d654c6761b 100644 (file)
@@ -320,28 +320,28 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
                ppc_md.log_error(buf, err_type, fatal);
 }
 
-#define __define_machine_initcall(mach,level,fn,id) \
+#define __define_machine_initcall(mach, fn, id) \
        static int __init __machine_initcall_##mach##_##fn(void) { \
                if (machine_is(mach)) return fn(); \
                return 0; \
        } \
-       __define_initcall(level,__machine_initcall_##mach##_##fn,id);
-
-#define machine_core_initcall(mach,fn)         __define_machine_initcall(mach,"1",fn,1)
-#define machine_core_initcall_sync(mach,fn)    __define_machine_initcall(mach,"1s",fn,1s)
-#define machine_postcore_initcall(mach,fn)     __define_machine_initcall(mach,"2",fn,2)
-#define machine_postcore_initcall_sync(mach,fn)        __define_machine_initcall(mach,"2s",fn,2s)
-#define machine_arch_initcall(mach,fn)         __define_machine_initcall(mach,"3",fn,3)
-#define machine_arch_initcall_sync(mach,fn)    __define_machine_initcall(mach,"3s",fn,3s)
-#define machine_subsys_initcall(mach,fn)       __define_machine_initcall(mach,"4",fn,4)
-#define machine_subsys_initcall_sync(mach,fn)  __define_machine_initcall(mach,"4s",fn,4s)
-#define machine_fs_initcall(mach,fn)           __define_machine_initcall(mach,"5",fn,5)
-#define machine_fs_initcall_sync(mach,fn)      __define_machine_initcall(mach,"5s",fn,5s)
-#define machine_rootfs_initcall(mach,fn)       __define_machine_initcall(mach,"rootfs",fn,rootfs)
-#define machine_device_initcall(mach,fn)       __define_machine_initcall(mach,"6",fn,6)
-#define machine_device_initcall_sync(mach,fn)  __define_machine_initcall(mach,"6s",fn,6s)
-#define machine_late_initcall(mach,fn)         __define_machine_initcall(mach,"7",fn,7)
-#define machine_late_initcall_sync(mach,fn)    __define_machine_initcall(mach,"7s",fn,7s)
+       __define_initcall(__machine_initcall_##mach##_##fn, id);
+
+#define machine_core_initcall(mach, fn)                __define_machine_initcall(mach, fn, 1)
+#define machine_core_initcall_sync(mach, fn)   __define_machine_initcall(mach, fn, 1s)
+#define machine_postcore_initcall(mach, fn)    __define_machine_initcall(mach, fn, 2)
+#define machine_postcore_initcall_sync(mach, fn)       __define_machine_initcall(mach, fn, 2s)
+#define machine_arch_initcall(mach, fn)                __define_machine_initcall(mach, fn, 3)
+#define machine_arch_initcall_sync(mach, fn)   __define_machine_initcall(mach, fn, 3s)
+#define machine_subsys_initcall(mach, fn)      __define_machine_initcall(mach, fn, 4)
+#define machine_subsys_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 4s)
+#define machine_fs_initcall(mach, fn)          __define_machine_initcall(mach, fn, 5)
+#define machine_fs_initcall_sync(mach, fn)     __define_machine_initcall(mach, fn, 5s)
+#define machine_rootfs_initcall(mach, fn)      __define_machine_initcall(mach, fn, rootfs)
+#define machine_device_initcall(mach, fn)      __define_machine_initcall(mach, fn, 6)
+#define machine_device_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 6s)
+#define machine_late_initcall(mach, fn)                __define_machine_initcall(mach, fn, 7)
+#define machine_late_initcall_sync(mach, fn)   __define_machine_initcall(mach, fn, 7s)
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MACHDEP_H */
index 840838769853e653f1ee950d9fdb4ed619f54ede..cec8aae5cbf8a85fc0f7db35734222e287e7cd48 100644 (file)
@@ -164,7 +164,7 @@ COMPAT_SYS_SPU(sched_getscheduler)
 SYSCALL_SPU(sched_yield)
 COMPAT_SYS_SPU(sched_get_priority_max)
 COMPAT_SYS_SPU(sched_get_priority_min)
-COMPAT_SYS_SPU(sched_rr_get_interval)
+SYSX_SPU(sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval_wrapper,sys_sched_rr_get_interval)
 COMPAT_SYS_SPU(nanosleep)
 SYSCALL_SPU(mremap)
 SYSCALL_SPU(setresuid)
index 76fe846ec40e7fe771e70c25d0f01bbe75ea4789..bcbbe413c6069a885f8c755acee5baab38cf1220 100644 (file)
@@ -54,6 +54,7 @@
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
index 9c2ed90ece8f4cdb93b75456f70376b944d52703..8a93778ed9f5ac86178d0e8a397acefc8a55a729 100644 (file)
@@ -175,19 +175,10 @@ asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 a
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
  * and the register representation of a signed int (msr in 64-bit mode) is performed.
  */
-asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
-{
-       struct timespec t;
-       int ret;
-       mm_segment_t old_fs = get_fs ();
-
-       /* The __user pointer cast is valid because of the set_fs() */
-       set_fs (KERNEL_DS);
-       ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
-       set_fs (old_fs);
-       if (put_compat_timespec(&t, interval))
-               return -EFAULT;
-       return ret;
+asmlinkage long compat_sys_sched_rr_get_interval_wrapper(u32 pid,
+                                                        struct compat_timespec __user *interval)
+{
+       return compat_sys_sched_rr_get_interval((int)pid, interval);
 }
 
 /* Note: it is necessary to treat mode as an unsigned int,
index c3e5d8b6417123b19ff0383abb063d85d82db243..497386a7ed28d754e5efcc2a5c9d530e8cb56142 100644 (file)
@@ -45,6 +45,7 @@
 #define __ARCH_WANT_COMPAT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_EXECVE
 
index 03c7e929ec34d41eedd7fad7378795c806be5081..4a4cdc633f6b84453748042cbd6fb19129f62d88 100644 (file)
@@ -211,20 +211,6 @@ asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
        return sys_sysfs(option, arg1, arg2);
 }
 
-asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
-{
-       struct timespec t;
-       int ret;
-       mm_segment_t old_fs = get_fs ();
-       
-       set_fs (KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
-       set_fs (old_fs);
-       if (put_compat_timespec(&t, interval))
-               return -EFAULT;
-       return ret;
-}
-
 asmlinkage long compat_sys_rt_sigprocmask(int how,
                                          compat_sigset_t __user *set,
                                          compat_sigset_t __user *oset,
index ca61fb4296b34d835e1e147d40cbc9c84a385a9d..88f3c227afd9ab6b838074fbe5b33ae4fde38052 100644 (file)
@@ -296,8 +296,6 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
 long compat_sys_fallocate(int fd, int mode,
                          u32 offset_lo, u32 offset_hi,
                          u32 len_lo, u32 len_hi);
-long compat_sys_sched_rr_get_interval(compat_pid_t pid,
-                                     struct compat_timespec __user *interval);
 
 /* Assembly trampoline to avoid clobbering r0. */
 long _compat_sys_rt_sigreturn(void);
index b51c6ee3cd6c2f701c88cd8d45647cc038bd822f..fe841e7d4963e5e88ccdf08193788d535be4da9e 100644 (file)
@@ -14,6 +14,7 @@
 /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */
 #ifdef CONFIG_COMPAT
 #define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #define __ARCH_WANT_SYS_EXECVE
index 9cd7cb6041c0ab84700a7bdc05d2a2431ef6c204..7f72401b4f458347d8cba0cc7fd4ab637a61b616 100644 (file)
@@ -76,24 +76,6 @@ long compat_sys_fallocate(int fd, int mode,
                             ((loff_t)len_hi << 32) | len_lo);
 }
 
-
-
-long compat_sys_sched_rr_get_interval(compat_pid_t pid,
-                                     struct compat_timespec __user *interval)
-{
-       struct timespec t;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-
-       set_fs(KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid,
-                                       (struct timespec __force __user *)&t);
-       set_fs(old_fs);
-       if (put_compat_timespec(&t, interval))
-               return -EFAULT;
-       return ret;
-}
-
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..79a9626b5500c171eaa6dbeef1681e91f922e9dc 100644 (file)
@@ -0,0 +1 @@
+/* */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..79a9626b5500c171eaa6dbeef1681e91f922e9dc 100644 (file)
@@ -0,0 +1 @@
+/* */
index a7e40a7c821427cd27f6c7019411030ea00e33e8..4a85ccf8d4cfca02daab96709e35cc14a92a35b5 100644 (file)
@@ -4,6 +4,7 @@
 menuconfig BLOCK
        bool "Enable the block layer" if EXPERT
        default y
+       select PERCPU_RWSEM
        help
         Provide block layer support for the kernel.
 
index d2ed7f18d1acfa6303b67999b0b39a93e575f49b..175649468c9518b6b7553abc018c0de4ac5cada1 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "50"
+#define VERSION "81"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -10,7 +10,7 @@
 #define AOE_PARTITIONS (16)
 #endif
 
-#define WHITESPACE " \t\v\f\n"
+#define WHITESPACE " \t\v\f\n,"
 
 enum {
        AOECMD_ATA,
@@ -73,21 +73,29 @@ enum {
        DEVFL_TKILL = (1<<1),   /* flag for timer to know when to kill self */
        DEVFL_EXT = (1<<2),     /* device accepts lba48 commands */
        DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */
-       DEVFL_KICKME = (1<<4),  /* slow polling network card catch */
-       DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */
+       DEVFL_GD_NOW = (1<<4),  /* allocating gendisk */
+       DEVFL_KICKME = (1<<5),  /* slow polling network card catch */
+       DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
+       DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */
+       DEVFL_FREED = (1<<8),   /* device has been cleaned up */
 };
 
 enum {
        DEFAULTBCNT = 2 * 512,  /* 2 sectors */
        MIN_BUFS = 16,
-       NTARGETS = 8,
+       NTARGETS = 4,
        NAOEIFS = 8,
        NSKBPOOLMAX = 256,
        NFACTIVE = 61,
 
        TIMERTICK = HZ / 10,
-       MINTIMER = HZ >> 2,
-       MAXTIMER = HZ << 1,
+       RTTSCALE = 8,
+       RTTDSCALE = 3,
+       RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE,
+       RTTDEV_INIT = RTTAVG_INIT / 4,
+
+       HARD_SCORN_SECS = 10,   /* try another remote port after this */
+       MAX_TAINT = 1000,       /* cap on aoetgt taint */
 };
 
 struct buf {
@@ -100,10 +108,17 @@ struct buf {
        struct request *rq;
 };
 
+enum frame_flags {
+       FFL_PROBE = 1,
+};
+
 struct frame {
        struct list_head head;
        u32 tag;
+       struct timeval sent;    /* high-res time packet was sent */
+       u32 sent_jiffs;         /* low-res jiffies-based sent time */
        ulong waited;
+       ulong waited_total;
        struct aoetgt *t;               /* parent target I belong to */
        sector_t lba;
        struct sk_buff *skb;            /* command skb freed on module exit */
@@ -112,6 +127,7 @@ struct frame {
        struct bio_vec *bv;
        ulong bcnt;
        ulong bv_off;
+       char flags;
 };
 
 struct aoeif {
@@ -122,28 +138,31 @@ struct aoeif {
 
 struct aoetgt {
        unsigned char addr[6];
-       ushort nframes;
+       ushort nframes;         /* cap on frames to use */
        struct aoedev *d;                       /* parent device I belong to */
        struct list_head ffree;                 /* list of free frames */
        struct aoeif ifs[NAOEIFS];
        struct aoeif *ifp;      /* current aoeif in use */
-       ushort nout;
-       ushort maxout;
-       ulong falloc;
-       ulong lastwadj;         /* last window adjustment */
+       ushort nout;            /* number of AoE commands outstanding */
+       ushort maxout;          /* current value for max outstanding */
+       ushort next_cwnd;       /* incr maxout after decrementing to zero */
+       ushort ssthresh;        /* slow start threshold */
+       ulong falloc;           /* number of allocated frames */
+       int taint;              /* how much we want to avoid this aoetgt */
        int minbcnt;
        int wpkts, rpkts;
+       char nout_probes;
 };
 
 struct aoedev {
        struct aoedev *next;
        ulong sysminor;
        ulong aoemajor;
+       u32 rttavg;             /* scaled AoE round trip time average */
+       u32 rttdev;             /* scaled round trip time mean deviation */
        u16 aoeminor;
        u16 flags;
        u16 nopen;              /* (bd_openers isn't available without sleeping) */
-       u16 rttavg;             /* round trip average of requests/responses */
-       u16 mintimer;
        u16 fw_ver;             /* version of blade's firmware */
        u16 lasttag;            /* last tag sent */
        u16 useme;
@@ -151,7 +170,7 @@ struct aoedev {
        struct work_struct work;/* disk create work struct */
        struct gendisk *gd;
        struct request_queue *blkq;
-       struct hd_geometry geo; 
+       struct hd_geometry geo;
        sector_t ssize;
        struct timer_list timer;
        spinlock_t lock;
@@ -164,11 +183,12 @@ struct aoedev {
        } ip;
        ulong maxbcnt;
        struct list_head factive[NFACTIVE];     /* hash of active frames */
-       struct aoetgt *targets[NTARGETS];
+       struct list_head rexmitq; /* deferred retransmissions */
+       struct aoetgt **targets;
+       ulong ntargets;         /* number of allocated aoetgt pointers */
        struct aoetgt **tgt;    /* target in use when working */
-       struct aoetgt *htgt;    /* target needing rexmit assistance */
-       ulong ntargets;
        ulong kicked;
+       char ident[512];
 };
 
 /* kthread tracking */
@@ -195,6 +215,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
 struct sk_buff *aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
 void aoecmd_sleepwork(struct work_struct *);
+void aoecmd_wreset(struct aoetgt *t);
 void aoecmd_cleanslate(struct aoedev *);
 void aoecmd_exit(void);
 int aoecmd_init(void);
index 00dfc5008ad4bddd8a8efa036eb1bbbc8cc8ec23..a129f8c8073db35469f4c0f8232ed3eb44f51d05 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
+#include <linux/moduleparam.h>
+#include <scsi/sg.h>
 #include "aoe.h"
 
 static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
 
+/* GPFS needs a larger value than the default. */
+static int aoe_maxsectors;
+module_param(aoe_maxsectors, int, 0644);
+MODULE_PARM_DESC(aoe_maxsectors,
+       "When nonzero, set the maximum number of sectors per I/O request");
+
 static ssize_t aoedisk_show_state(struct device *dev,
                                  struct device_attribute *attr, char *page)
 {
@@ -59,7 +67,7 @@ static ssize_t aoedisk_show_netif(struct device *dev,
        nd = nds;
        ne = nd + ARRAY_SIZE(nds);
        t = d->targets;
-       te = t + NTARGETS;
+       te = t + d->ntargets;
        for (; t < te && *t; t++) {
                ifp = (*t)->ifs;
                e = ifp + NAOEIFS;
@@ -91,6 +99,14 @@ static ssize_t aoedisk_show_fwver(struct device *dev,
 
        return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
 }
+static ssize_t aoedisk_show_payload(struct device *dev,
+                                   struct device_attribute *attr, char *page)
+{
+       struct gendisk *disk = dev_to_disk(dev);
+       struct aoedev *d = disk->private_data;
+
+       return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt);
+}
 
 static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
 static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
@@ -99,12 +115,14 @@ static struct device_attribute dev_attr_firmware_version = {
        .attr = { .name = "firmware-version", .mode = S_IRUGO },
        .show = aoedisk_show_fwver,
 };
+static DEVICE_ATTR(payload, S_IRUGO, aoedisk_show_payload, NULL);
 
 static struct attribute *aoe_attrs[] = {
        &dev_attr_state.attr,
        &dev_attr_mac.attr,
        &dev_attr_netif.attr,
        &dev_attr_firmware_version.attr,
+       &dev_attr_payload.attr,
        NULL,
 };
 
@@ -129,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)
        struct aoedev *d = bdev->bd_disk->private_data;
        ulong flags;
 
+       if (!virt_addr_valid(d)) {
+               pr_crit("aoe: invalid device pointer in %s\n",
+                       __func__);
+               WARN_ON(1);
+               return -ENODEV;
+       }
+       if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL)
+               return -ENODEV;
+
        mutex_lock(&aoeblk_mutex);
        spin_lock_irqsave(&d->lock, flags);
-       if (d->flags & DEVFL_UP) {
+       if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) {
                d->nopen++;
                spin_unlock_irqrestore(&d->lock, flags);
                mutex_unlock(&aoeblk_mutex);
@@ -195,9 +222,38 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
 }
 
+static int
+aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
+{
+       struct aoedev *d;
+
+       if (!arg)
+               return -EINVAL;
+
+       d = bdev->bd_disk->private_data;
+       if ((d->flags & DEVFL_UP) == 0) {
+               pr_err("aoe: disk not up\n");
+               return -ENODEV;
+       }
+
+       if (cmd == HDIO_GET_IDENTITY) {
+               if (!copy_to_user((void __user *) arg, &d->ident,
+                       sizeof(d->ident)))
+                       return 0;
+               return -EFAULT;
+       }
+
+       /* udev calls scsi_id, which uses SG_IO, resulting in noise */
+       if (cmd != SG_IO)
+               pr_info("aoe: unknown ioctl 0x%x\n", cmd);
+
+       return -ENOTTY;
+}
+
 static const struct block_device_operations aoe_bdops = {
        .open = aoeblk_open,
        .release = aoeblk_release,
+       .ioctl = aoeblk_ioctl,
        .getgeo = aoeblk_getgeo,
        .owner = THIS_MODULE,
 };
@@ -212,6 +268,18 @@ aoeblk_gdalloc(void *vp)
        struct request_queue *q;
        enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
        ulong flags;
+       int late = 0;
+
+       spin_lock_irqsave(&d->lock, flags);
+       if (d->flags & DEVFL_GDALLOC
+       && !(d->flags & DEVFL_TKILL)
+       && !(d->flags & DEVFL_GD_NOW))
+               d->flags |= DEVFL_GD_NOW;
+       else
+               late = 1;
+       spin_unlock_irqrestore(&d->lock, flags);
+       if (late)
+               return;
 
        gd = alloc_disk(AOE_PARTITIONS);
        if (gd == NULL) {
@@ -231,23 +299,24 @@ aoeblk_gdalloc(void *vp)
        if (q == NULL) {
                pr_err("aoe: cannot allocate block queue for %ld.%d\n",
                        d->aoemajor, d->aoeminor);
-               mempool_destroy(mp);
-               goto err_disk;
+               goto err_mempool;
        }
 
-       d->blkq = blk_alloc_queue(GFP_KERNEL);
-       if (!d->blkq)
-               goto err_mempool;
-       d->blkq->backing_dev_info.name = "aoe";
-       if (bdi_init(&d->blkq->backing_dev_info))
-               goto err_blkq;
        spin_lock_irqsave(&d->lock, flags);
-       blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS);
+       WARN_ON(!(d->flags & DEVFL_GD_NOW));
+       WARN_ON(!(d->flags & DEVFL_GDALLOC));
+       WARN_ON(d->flags & DEVFL_TKILL);
+       WARN_ON(d->gd);
+       WARN_ON(d->flags & DEVFL_UP);
+       blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS);
+       q->backing_dev_info.name = "aoe";
        q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
        d->bufpool = mp;
        d->blkq = gd->queue = q;
        q->queuedata = d;
        d->gd = gd;
+       if (aoe_maxsectors)
+               blk_queue_max_hw_sectors(q, aoe_maxsectors);
        gd->major = AOE_MAJOR;
        gd->first_minor = d->sysminor;
        gd->fops = &aoe_bdops;
@@ -263,18 +332,21 @@ aoeblk_gdalloc(void *vp)
 
        add_disk(gd);
        aoedisk_add_sysfs(d);
+
+       spin_lock_irqsave(&d->lock, flags);
+       WARN_ON(!(d->flags & DEVFL_GD_NOW));
+       d->flags &= ~DEVFL_GD_NOW;
+       spin_unlock_irqrestore(&d->lock, flags);
        return;
 
-err_blkq:
-       blk_cleanup_queue(d->blkq);
-       d->blkq = NULL;
 err_mempool:
-       mempool_destroy(d->bufpool);
+       mempool_destroy(mp);
 err_disk:
        put_disk(gd);
 err:
        spin_lock_irqsave(&d->lock, flags);
-       d->flags &= ~DEVFL_GDALLOC;
+       d->flags &= ~DEVFL_GD_NOW;
+       schedule_work(&d->work);
        spin_unlock_irqrestore(&d->lock, flags);
 }
 
index ed57a890c6431ce882c84486481967c2103f1724..42e67ad6bd207dabd505c779e131b9465dad3e82 100644 (file)
@@ -39,6 +39,11 @@ struct ErrMsg {
 };
 
 static DEFINE_MUTEX(aoechr_mutex);
+
+/* A ring buffer of error messages, to be read through
+ * "/dev/etherd/err".  When no messages are present,
+ * readers will block waiting for messages to appear.
+ */
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
 static struct completion emsgs_comp;
@@ -282,7 +287,7 @@ aoechr_init(void)
        int n, i;
 
        n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
-       if (n < 0) { 
+       if (n < 0) {
                printk(KERN_ERR "aoe: can't register char device\n");
                return n;
        }
index 9fe4f1865558abce9ccd7ebf1ee10a56284caf61..25ef5c014fcaa4255e0e3009991b6a9ac1ff18c7 100644 (file)
@@ -22,6 +22,7 @@
 #define MAXIOC (8192)  /* default meant to avoid most soft lockups */
 
 static void ktcomplete(struct frame *, struct sk_buff *);
+static int count_targets(struct aoedev *d, int *untainted);
 
 static struct buf *nextbuf(struct aoedev *);
 
@@ -29,7 +30,7 @@ static int aoe_deadsecs = 60 * 3;
 module_param(aoe_deadsecs, int, 0644);
 MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
 
-static int aoe_maxout = 16;
+static int aoe_maxout = 64;
 module_param(aoe_maxout, int, 0644);
 MODULE_PARM_DESC(aoe_maxout,
        "Only aoe_maxout outstanding packets for every MAC on eX.Y.");
@@ -43,6 +44,8 @@ static struct {
        spinlock_t lock;
 } iocq;
 
+static struct page *empty_page;
+
 static struct sk_buff *
 new_skb(ulong len)
 {
@@ -58,6 +61,23 @@ new_skb(ulong len)
        return skb;
 }
 
+static struct frame *
+getframe_deferred(struct aoedev *d, u32 tag)
+{
+       struct list_head *head, *pos, *nx;
+       struct frame *f;
+
+       head = &d->rexmitq;
+       list_for_each_safe(pos, nx, head) {
+               f = list_entry(pos, struct frame, head);
+               if (f->tag == tag) {
+                       list_del(pos);
+                       return f;
+               }
+       }
+       return NULL;
+}
+
 static struct frame *
 getframe(struct aoedev *d, u32 tag)
 {
@@ -162,8 +182,10 @@ aoe_freetframe(struct frame *f)
 
        t = f->t;
        f->buf = NULL;
+       f->lba = 0;
        f->bv = NULL;
        f->r_skb = NULL;
+       f->flags = 0;
        list_add(&f->head, &t->ffree);
 }
 
@@ -217,20 +239,25 @@ newframe(struct aoedev *d)
        struct frame *f;
        struct aoetgt *t, **tt;
        int totout = 0;
+       int use_tainted;
+       int has_untainted;
 
-       if (d->targets[0] == NULL) {    /* shouldn't happen, but I'm paranoid */
+       if (!d->targets || !d->targets[0]) {
                printk(KERN_ERR "aoe: NULL TARGETS!\n");
                return NULL;
        }
        tt = d->tgt;    /* last used target */
-       for (;;) {
+       for (use_tainted = 0, has_untainted = 0;;) {
                tt++;
-               if (tt >= &d->targets[NTARGETS] || !*tt)
+               if (tt >= &d->targets[d->ntargets] || !*tt)
                        tt = d->targets;
                t = *tt;
-               totout += t->nout;
+               if (!t->taint) {
+                       has_untainted = 1;
+                       totout += t->nout;
+               }
                if (t->nout < t->maxout
-               && t != d->htgt
+               && (use_tainted || !t->taint)
                && t->ifp->nd) {
                        f = newtframe(d, t);
                        if (f) {
@@ -239,8 +266,12 @@ newframe(struct aoedev *d)
                                return f;
                        }
                }
-               if (tt == d->tgt)       /* we've looped and found nada */
-                       break;
+               if (tt == d->tgt) {     /* we've looped and found nada */
+                       if (!use_tainted && !has_untainted)
+                               use_tainted = 1;
+                       else
+                               break;
+               }
        }
        if (totout == 0) {
                d->kicked++;
@@ -277,21 +308,68 @@ fhash(struct frame *f)
        list_add_tail(&f->head, &d->factive[n]);
 }
 
+static void
+ata_rw_frameinit(struct frame *f)
+{
+       struct aoetgt *t;
+       struct aoe_hdr *h;
+       struct aoe_atahdr *ah;
+       struct sk_buff *skb;
+       char writebit, extbit;
+
+       skb = f->skb;
+       h = (struct aoe_hdr *) skb_mac_header(skb);
+       ah = (struct aoe_atahdr *) (h + 1);
+       skb_put(skb, sizeof(*h) + sizeof(*ah));
+       memset(h, 0, skb->len);
+
+       writebit = 0x10;
+       extbit = 0x4;
+
+       t = f->t;
+       f->tag = aoehdr_atainit(t->d, t, h);
+       fhash(f);
+       t->nout++;
+       f->waited = 0;
+       f->waited_total = 0;
+       if (f->buf)
+               f->lba = f->buf->sector;
+
+       /* set up ata header */
+       ah->scnt = f->bcnt >> 9;
+       put_lba(ah, f->lba);
+       if (t->d->flags & DEVFL_EXT) {
+               ah->aflags |= AOEAFL_EXT;
+       } else {
+               extbit = 0;
+               ah->lba3 &= 0x0f;
+               ah->lba3 |= 0xe0;       /* LBA bit + obsolete 0xa0 */
+       }
+       if (f->buf && bio_data_dir(f->buf->bio) == WRITE) {
+               skb_fillup(skb, f->bv, f->bv_off, f->bcnt);
+               ah->aflags |= AOEAFL_WRITE;
+               skb->len += f->bcnt;
+               skb->data_len = f->bcnt;
+               skb->truesize += f->bcnt;
+               t->wpkts++;
+       } else {
+               t->rpkts++;
+               writebit = 0;
+       }
+
+       ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit;
+       skb->dev = t->ifp->nd;
+}
+
 static int
 aoecmd_ata_rw(struct aoedev *d)
 {
        struct frame *f;
-       struct aoe_hdr *h;
-       struct aoe_atahdr *ah;
        struct buf *buf;
        struct aoetgt *t;
        struct sk_buff *skb;
        struct sk_buff_head queue;
        ulong bcnt, fbcnt;
-       char writebit, extbit;
-
-       writebit = 0x10;
-       extbit = 0x4;
 
        buf = nextbuf(d);
        if (buf == NULL)
@@ -326,50 +404,18 @@ aoecmd_ata_rw(struct aoedev *d)
        } while (fbcnt);
 
        /* initialize the headers & frame */
-       skb = f->skb;
-       h = (struct aoe_hdr *) skb_mac_header(skb);
-       ah = (struct aoe_atahdr *) (h+1);
-       skb_put(skb, sizeof *h + sizeof *ah);
-       memset(h, 0, skb->len);
-       f->tag = aoehdr_atainit(d, t, h);
-       fhash(f);
-       t->nout++;
-       f->waited = 0;
        f->buf = buf;
        f->bcnt = bcnt;
-       f->lba = buf->sector;
-
-       /* set up ata header */
-       ah->scnt = bcnt >> 9;
-       put_lba(ah, buf->sector);
-       if (d->flags & DEVFL_EXT) {
-               ah->aflags |= AOEAFL_EXT;
-       } else {
-               extbit = 0;
-               ah->lba3 &= 0x0f;
-               ah->lba3 |= 0xe0;       /* LBA bit + obsolete 0xa0 */
-       }
-       if (bio_data_dir(buf->bio) == WRITE) {
-               skb_fillup(skb, f->bv, f->bv_off, bcnt);
-               ah->aflags |= AOEAFL_WRITE;
-               skb->len += bcnt;
-               skb->data_len = bcnt;
-               skb->truesize += bcnt;
-               t->wpkts++;
-       } else {
-               t->rpkts++;
-               writebit = 0;
-       }
-
-       ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit;
+       ata_rw_frameinit(f);
 
        /* mark all tracking fields and load out */
        buf->nframesout += 1;
        buf->sector += bcnt >> 9;
 
-       skb->dev = t->ifp->nd;
-       skb = skb_clone(skb, GFP_ATOMIC);
+       skb = skb_clone(f->skb, GFP_ATOMIC);
        if (skb) {
+               do_gettimeofday(&f->sent);
+               f->sent_jiffs = (u32) jiffies;
                __skb_queue_head_init(&queue);
                __skb_queue_tail(&queue, skb);
                aoenet_xmit(&queue);
@@ -442,11 +488,14 @@ resend(struct aoedev *d, struct frame *f)
        h = (struct aoe_hdr *) skb_mac_header(skb);
        ah = (struct aoe_atahdr *) (h+1);
 
-       snprintf(buf, sizeof buf,
-               "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n",
-               "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n,
-               h->src, h->dst, t->nout);
-       aoechr_error(buf);
+       if (!(f->flags & FFL_PROBE)) {
+               snprintf(buf, sizeof(buf),
+                       "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n",
+                       "retransmit", d->aoemajor, d->aoeminor,
+                       f->tag, jiffies, n,
+                       h->src, h->dst, t->nout);
+               aoechr_error(buf);
+       }
 
        f->tag = n;
        fhash(f);
@@ -458,11 +507,45 @@ resend(struct aoedev *d, struct frame *f)
        skb = skb_clone(skb, GFP_ATOMIC);
        if (skb == NULL)
                return;
+       do_gettimeofday(&f->sent);
+       f->sent_jiffs = (u32) jiffies;
        __skb_queue_head_init(&queue);
        __skb_queue_tail(&queue, skb);
        aoenet_xmit(&queue);
 }
 
+static int
+tsince_hr(struct frame *f)
+{
+       struct timeval now;
+       int n;
+
+       do_gettimeofday(&now);
+       n = now.tv_usec - f->sent.tv_usec;
+       n += (now.tv_sec - f->sent.tv_sec) * USEC_PER_SEC;
+
+       if (n < 0)
+               n = -n;
+
+       /* For relatively long periods, use jiffies to avoid
+        * discrepancies caused by updates to the system time.
+        *
+        * On system with HZ of 1000, 32-bits is over 49 days
+        * worth of jiffies, or over 71 minutes worth of usecs.
+        *
+        * Jiffies overflow is handled by subtraction of unsigned ints:
+        * (gdb) print (unsigned) 2 - (unsigned) 0xfffffffe
+        * $3 = 4
+        * (gdb)
+        */
+       if (n > USEC_PER_SEC / 4) {
+               n = ((u32) jiffies) - f->sent_jiffs;
+               n *= USEC_PER_SEC / HZ;
+       }
+
+       return n;
+}
+
 static int
 tsince(u32 tag)
 {
@@ -472,7 +555,7 @@ tsince(u32 tag)
        n -= tag & 0xffff;
        if (n < 0)
                n += 1<<16;
-       return n;
+       return jiffies_to_usecs(n + 1);
 }
 
 static struct aoeif *
@@ -503,70 +586,189 @@ ejectif(struct aoetgt *t, struct aoeif *ifp)
        dev_put(nd);
 }
 
-static int
-sthtith(struct aoedev *d)
+static struct frame *
+reassign_frame(struct frame *f)
 {
-       struct frame *f, *nf;
-       struct list_head *nx, *pos, *head;
+       struct frame *nf;
        struct sk_buff *skb;
-       struct aoetgt *ht = d->htgt;
-       int i;
 
-       for (i = 0; i < NFACTIVE; i++) {
-               head = &d->factive[i];
-               list_for_each_safe(pos, nx, head) {
-                       f = list_entry(pos, struct frame, head);
-                       if (f->t != ht)
-                               continue;
+       nf = newframe(f->t->d);
+       if (!nf)
+               return NULL;
+       if (nf->t == f->t) {
+               aoe_freetframe(nf);
+               return NULL;
+       }
 
-                       nf = newframe(d);
-                       if (!nf)
-                               return 0;
+       skb = nf->skb;
+       nf->skb = f->skb;
+       nf->buf = f->buf;
+       nf->bcnt = f->bcnt;
+       nf->lba = f->lba;
+       nf->bv = f->bv;
+       nf->bv_off = f->bv_off;
+       nf->waited = 0;
+       nf->waited_total = f->waited_total;
+       nf->sent = f->sent;
+       nf->sent_jiffs = f->sent_jiffs;
+       f->skb = skb;
+
+       return nf;
+}
 
-                       /* remove frame from active list */
-                       list_del(pos);
+static void
+probe(struct aoetgt *t)
+{
+       struct aoedev *d;
+       struct frame *f;
+       struct sk_buff *skb;
+       struct sk_buff_head queue;
+       size_t n, m;
+       int frag;
 
-                       /* reassign all pertinent bits to new outbound frame */
-                       skb = nf->skb;
-                       nf->skb = f->skb;
-                       nf->buf = f->buf;
-                       nf->bcnt = f->bcnt;
-                       nf->lba = f->lba;
-                       nf->bv = f->bv;
-                       nf->bv_off = f->bv_off;
-                       nf->waited = 0;
-                       f->skb = skb;
+       d = t->d;
+       f = newtframe(d, t);
+       if (!f) {
+               pr_err("%s %pm for e%ld.%d: %s\n",
+                       "aoe: cannot probe remote address",
+                       t->addr,
+                       (long) d->aoemajor, d->aoeminor,
+                       "no frame available");
+               return;
+       }
+       f->flags |= FFL_PROBE;
+       ifrotate(t);
+       f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT;
+       ata_rw_frameinit(f);
+       skb = f->skb;
+       for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) {
+               if (n < PAGE_SIZE)
+                       m = n;
+               else
+                       m = PAGE_SIZE;
+               skb_fill_page_desc(skb, frag, empty_page, 0, m);
+       }
+       skb->len += f->bcnt;
+       skb->data_len = f->bcnt;
+       skb->truesize += f->bcnt;
+
+       skb = skb_clone(f->skb, GFP_ATOMIC);
+       if (skb) {
+               do_gettimeofday(&f->sent);
+               f->sent_jiffs = (u32) jiffies;
+               __skb_queue_head_init(&queue);
+               __skb_queue_tail(&queue, skb);
+               aoenet_xmit(&queue);
+       }
+}
+
+static long
+rto(struct aoedev *d)
+{
+       long t;
+
+       t = 2 * d->rttavg >> RTTSCALE;
+       t += 8 * d->rttdev >> RTTDSCALE;
+       if (t == 0)
+               t = 1;
+
+       return t;
+}
+
+static void
+rexmit_deferred(struct aoedev *d)
+{
+       struct aoetgt *t;
+       struct frame *f;
+       struct frame *nf;
+       struct list_head *pos, *nx, *head;
+       int since;
+       int untainted;
+
+       count_targets(d, &untainted);
+
+       head = &d->rexmitq;
+       list_for_each_safe(pos, nx, head) {
+               f = list_entry(pos, struct frame, head);
+               t = f->t;
+               if (t->taint) {
+                       if (!(f->flags & FFL_PROBE)) {
+                               nf = reassign_frame(f);
+                               if (nf) {
+                                       if (t->nout_probes == 0
+                                       && untainted > 0) {
+                                               probe(t);
+                                               t->nout_probes++;
+                                       }
+                                       list_replace(&f->head, &nf->head);
+                                       pos = &nf->head;
+                                       aoe_freetframe(f);
+                                       f = nf;
+                                       t = f->t;
+                               }
+                       } else if (untainted < 1) {
+                               /* don't probe w/o other untainted aoetgts */
+                               goto stop_probe;
+                       } else if (tsince_hr(f) < t->taint * rto(d)) {
+                               /* reprobe slowly when taint is high */
+                               continue;
+                       }
+               } else if (f->flags & FFL_PROBE) {
+stop_probe:            /* don't probe untainted aoetgts */
+                       list_del(pos);
                        aoe_freetframe(f);
-                       ht->nout--;
-                       nf->t->nout++;
-                       resend(d, nf);
+                       /* leaving d->kicked, because this is routine */
+                       f->t->d->flags |= DEVFL_KICKME;
+                       continue;
                }
+               if (t->nout >= t->maxout)
+                       continue;
+               list_del(pos);
+               t->nout++;
+               if (f->flags & FFL_PROBE)
+                       t->nout_probes++;
+               since = tsince_hr(f);
+               f->waited += since;
+               f->waited_total += since;
+               resend(d, f);
        }
-       /* We've cleaned up the outstanding so take away his
-        * interfaces so he won't be used.  We should remove him from
-        * the target array here, but cleaning up a target is
-        * involved.  PUNT!
-        */
-       memset(ht->ifs, 0, sizeof ht->ifs);
-       d->htgt = NULL;
-       return 1;
 }
 
-static inline unsigned char
-ata_scnt(unsigned char *packet) {
-       struct aoe_hdr *h;
-       struct aoe_atahdr *ah;
+/* An aoetgt accumulates demerits quickly, and successful
+ * probing redeems the aoetgt slowly.
+ */
+static void
+scorn(struct aoetgt *t)
+{
+       int n;
 
-       h = (struct aoe_hdr *) packet;
-       ah = (struct aoe_atahdr *) (h+1);
-       return ah->scnt;
+       n = t->taint++;
+       t->taint += t->taint * 2;
+       if (n > t->taint)
+               t->taint = n;
+       if (t->taint > MAX_TAINT)
+               t->taint = MAX_TAINT;
+}
+
+static int
+count_targets(struct aoedev *d, int *untainted)
+{
+       int i, good;
+
+       for (i = good = 0; i < d->ntargets && d->targets[i]; ++i)
+               if (d->targets[i]->taint == 0)
+                       good++;
+
+       if (untainted)
+               *untainted = good;
+       return i;
 }
 
 static void
 rexmit_timer(ulong vp)
 {
        struct aoedev *d;
-       struct aoetgt *t, **tt, **te;
+       struct aoetgt *t;
        struct aoeif *ifp;
        struct frame *f;
        struct list_head *head, *pos, *nx;
@@ -574,15 +776,18 @@ rexmit_timer(ulong vp)
        register long timeout;
        ulong flags, n;
        int i;
+       int utgts;      /* number of aoetgt descriptors (not slots) */
+       int since;
 
        d = (struct aoedev *) vp;
 
-       /* timeout is always ~150% of the moving average */
-       timeout = d->rttavg;
-       timeout += timeout >> 1;
-
        spin_lock_irqsave(&d->lock, flags);
 
+       /* timeout based on observed timings and variations */
+       timeout = rto(d);
+
+       utgts = count_targets(d, NULL);
+
        if (d->flags & DEVFL_TKILL) {
                spin_unlock_irqrestore(&d->lock, flags);
                return;
@@ -593,67 +798,61 @@ rexmit_timer(ulong vp)
                head = &d->factive[i];
                list_for_each_safe(pos, nx, head) {
                        f = list_entry(pos, struct frame, head);
-                       if (tsince(f->tag) < timeout)
+                       if (tsince_hr(f) < timeout)
                                break;  /* end of expired frames */
                        /* move to flist for later processing */
                        list_move_tail(pos, &flist);
                }
        }
-       /* window check */
-       tt = d->targets;
-       te = tt + d->ntargets;
-       for (; tt < te && (t = *tt); tt++) {
-               if (t->nout == t->maxout
-               && t->maxout < t->nframes
-               && (jiffies - t->lastwadj)/HZ > 10) {
-                       t->maxout++;
-                       t->lastwadj = jiffies;
-               }
-       }
-
-       if (!list_empty(&flist)) {      /* retransmissions necessary */
-               n = d->rttavg <<= 1;
-               if (n > MAXTIMER)
-                       d->rttavg = MAXTIMER;
-       }
 
        /* process expired frames */
        while (!list_empty(&flist)) {
                pos = flist.next;
                f = list_entry(pos, struct frame, head);
-               n = f->waited += timeout;
-               n /= HZ;
-               if (n > aoe_deadsecs) {
+               since = tsince_hr(f);
+               n = f->waited_total + since;
+               n /= USEC_PER_SEC;
+               if (aoe_deadsecs
+               && n > aoe_deadsecs
+               && !(f->flags & FFL_PROBE)) {
                        /* Waited too long.  Device failure.
                         * Hang all frames on first hash bucket for downdev
                         * to clean up.
                         */
                        list_splice(&flist, &d->factive[0]);
                        aoedev_downdev(d);
-                       break;
+                       goto out;
                }
-               list_del(pos);
 
                t = f->t;
-               if (n > aoe_deadsecs/2)
-                       d->htgt = t; /* see if another target can help */
-
-               if (t->nout == t->maxout) {
-                       if (t->maxout > 1)
-                               t->maxout--;
-                       t->lastwadj = jiffies;
+               n = f->waited + since;
+               n /= USEC_PER_SEC;
+               if (aoe_deadsecs && utgts > 0
+               && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS))
+                       scorn(t); /* avoid this target */
+
+               if (t->maxout != 1) {
+                       t->ssthresh = t->maxout / 2;
+                       t->maxout = 1;
                }
 
-               ifp = getif(t, f->skb->dev);
-               if (ifp && ++ifp->lost > (t->nframes << 1)
-               && (ifp != t->ifs || t->ifs[1].nd)) {
-                       ejectif(t, ifp);
-                       ifp = NULL;
+               if (f->flags & FFL_PROBE) {
+                       t->nout_probes--;
+               } else {
+                       ifp = getif(t, f->skb->dev);
+                       if (ifp && ++ifp->lost > (t->nframes << 1)
+                       && (ifp != t->ifs || t->ifs[1].nd)) {
+                               ejectif(t, ifp);
+                               ifp = NULL;
+                       }
                }
-               resend(d, f);
+               list_move_tail(pos, &d->rexmitq);
+               t->nout--;
        }
+       rexmit_deferred(d);
 
-       if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) {
+out:
+       if ((d->flags & DEVFL_KICKME) && d->blkq) {
                d->flags &= ~DEVFL_KICKME;
                d->blkq->request_fn(d->blkq);
        }
@@ -774,8 +973,7 @@ nextbuf(struct aoedev *d)
 void
 aoecmd_work(struct aoedev *d)
 {
-       if (d->htgt && !sthtith(d))
-               return;
+       rexmit_deferred(d);
        while (aoecmd_ata_rw(d))
                ;
 }
@@ -808,6 +1006,17 @@ aoecmd_sleepwork(struct work_struct *work)
        }
 }
 
+static void
+ata_ident_fixstring(u16 *id, int ns)
+{
+       u16 s;
+
+       while (ns-- > 0) {
+               s = *id;
+               *id++ = s >> 8 | s << 8;
+       }
+}
+
 static void
 ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
 {
@@ -843,6 +1052,11 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
                d->geo.sectors = get_unaligned_le16(&id[56 << 1]);
        }
 
+       ata_ident_fixstring((u16 *) &id[10<<1], 10);    /* serial */
+       ata_ident_fixstring((u16 *) &id[23<<1], 4);     /* firmware */
+       ata_ident_fixstring((u16 *) &id[27<<1], 20);    /* model */
+       memcpy(d->ident, id, sizeof(d->ident));
+
        if (d->ssize != ssize)
                printk(KERN_INFO
                        "aoe: %pm e%ld.%d v%04x has %llu sectors\n",
@@ -862,26 +1076,28 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
 }
 
 static void
-calc_rttavg(struct aoedev *d, int rtt)
+calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt)
 {
        register long n;
 
        n = rtt;
-       if (n < 0) {
-               n = -rtt;
-               if (n < MINTIMER)
-                       n = MINTIMER;
-               else if (n > MAXTIMER)
-                       n = MAXTIMER;
-               d->mintimer += (n - d->mintimer) >> 1;
-       } else if (n < d->mintimer)
-               n = d->mintimer;
-       else if (n > MAXTIMER)
-               n = MAXTIMER;
-
-       /* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */
-       n -= d->rttavg;
-       d->rttavg += n >> 2;
+
+       /* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */
+       n -= d->rttavg >> RTTSCALE;
+       d->rttavg += n;
+       if (n < 0)
+               n = -n;
+       n -= d->rttdev >> RTTDSCALE;
+       d->rttdev += n;
+
+       if (!t || t->maxout >= t->nframes)
+               return;
+       if (t->maxout < t->ssthresh)
+               t->maxout += 1;
+       else if (t->nout == t->maxout && t->next_cwnd-- == 0) {
+               t->maxout += 1;
+               t->next_cwnd = t->maxout;
+       }
 }
 
 static struct aoetgt *
@@ -890,7 +1106,7 @@ gettgt(struct aoedev *d, char *addr)
        struct aoetgt **t, **e;
 
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0)
                        return *t;
@@ -966,19 +1182,22 @@ ktiocomplete(struct frame *f)
        struct aoeif *ifp;
        struct aoedev *d;
        long n;
+       int untainted;
 
        if (f == NULL)
                return;
 
        t = f->t;
        d = t->d;
+       skb = f->r_skb;
+       buf = f->buf;
+       if (f->flags & FFL_PROBE)
+               goto out;
+       if (!skb)               /* just fail the buf. */
+               goto noskb;
 
        hout = (struct aoe_hdr *) skb_mac_header(f->skb);
        ahout = (struct aoe_atahdr *) (hout+1);
-       buf = f->buf;
-       skb = f->r_skb;
-       if (skb == NULL)
-               goto noskb;     /* just fail the buf. */
 
        hin = (struct aoe_hdr *) skb->data;
        skb_pull(skb, sizeof(*hin));
@@ -988,9 +1207,9 @@ ktiocomplete(struct frame *f)
                pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
                        ahout->cmdstat, ahin->cmdstat,
                        d->aoemajor, d->aoeminor);
-noskb: if (buf)
+noskb:         if (buf)
                        clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
-               goto badrsp;
+               goto out;
        }
 
        n = ahout->scnt << 9;
@@ -998,8 +1217,10 @@ noskb:    if (buf)
        case ATA_CMD_PIO_READ:
        case ATA_CMD_PIO_READ_EXT:
                if (skb->len < n) {
-                       pr_err("aoe: runt data size in read.  skb->len=%d need=%ld\n",
-                               skb->len, n);
+                       pr_err("%s e%ld.%d.  skb->len=%d need=%ld\n",
+                               "aoe: runt data size in read from",
+                               (long) d->aoemajor, d->aoeminor,
+                              skb->len, n);
                        clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
                        break;
                }
@@ -1010,13 +1231,13 @@ noskb:  if (buf)
                ifp = getif(t, skb->dev);
                if (ifp)
                        ifp->lost = 0;
-               if (d->htgt == t) /* I'll help myself, thank you. */
-                       d->htgt = NULL;
                spin_unlock_irq(&d->lock);
                break;
        case ATA_CMD_ID_ATA:
                if (skb->len < 512) {
-                       pr_info("aoe: runt data size in ataid.  skb->len=%d\n",
+                       pr_info("%s e%ld.%d.  skb->len=%d need=512\n",
+                               "aoe: runt data size in ataid from",
+                               (long) d->aoemajor, d->aoeminor,
                                skb->len);
                        break;
                }
@@ -1032,16 +1253,23 @@ noskb:  if (buf)
                        be16_to_cpu(get_unaligned(&hin->major)),
                        hin->minor);
        }
-badrsp:
+out:
        spin_lock_irq(&d->lock);
+       if (t->taint > 0
+       && --t->taint > 0
+       && t->nout_probes == 0) {
+               count_targets(d, &untainted);
+               if (untainted > 0) {
+                       probe(t);
+                       t->nout_probes++;
+               }
+       }
 
        aoe_freetframe(f);
 
        if (buf && --buf->nframesout == 0 && buf->resid == 0)
                aoe_end_buf(d, buf);
 
-       aoecmd_work(d);
-
        spin_unlock_irq(&d->lock);
        aoedev_put(d);
        dev_kfree_skb(skb);
@@ -1141,7 +1369,6 @@ aoecmd_ata_rsp(struct sk_buff *skb)
        struct aoedev *d;
        struct aoe_hdr *h;
        struct frame *f;
-       struct aoetgt *t;
        u32 n;
        ulong flags;
        char ebuf[128];
@@ -1162,23 +1389,32 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
        n = be32_to_cpu(get_unaligned(&h->tag));
        f = getframe(d, n);
-       if (f == NULL) {
-               calc_rttavg(d, -tsince(n));
-               spin_unlock_irqrestore(&d->lock, flags);
-               aoedev_put(d);
-               snprintf(ebuf, sizeof ebuf,
-                       "%15s e%d.%d    tag=%08x@%08lx\n",
-                       "unexpected rsp",
-                       get_unaligned_be16(&h->major),
-                       h->minor,
-                       get_unaligned_be32(&h->tag),
-                       jiffies);
-               aoechr_error(ebuf);
-               return skb;
+       if (f) {
+               calc_rttavg(d, f->t, tsince_hr(f));
+               f->t->nout--;
+               if (f->flags & FFL_PROBE)
+                       f->t->nout_probes--;
+       } else {
+               f = getframe_deferred(d, n);
+               if (f) {
+                       calc_rttavg(d, NULL, tsince_hr(f));
+               } else {
+                       calc_rttavg(d, NULL, tsince(n));
+                       spin_unlock_irqrestore(&d->lock, flags);
+                       aoedev_put(d);
+                       snprintf(ebuf, sizeof(ebuf),
+                                "%15s e%d.%d    tag=%08x@%08lx s=%pm d=%pm\n",
+                                "unexpected rsp",
+                                get_unaligned_be16(&h->major),
+                                h->minor,
+                                get_unaligned_be32(&h->tag),
+                                jiffies,
+                                h->src,
+                                h->dst);
+                       aoechr_error(ebuf);
+                       return skb;
+               }
        }
-       t = f->t;
-       calc_rttavg(d, tsince(f->tag));
-       t->nout--;
        aoecmd_work(d);
 
        spin_unlock_irqrestore(&d->lock, flags);
@@ -1201,7 +1437,7 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
        aoecmd_cfg_pkts(aoemajor, aoeminor, &queue);
        aoenet_xmit(&queue);
 }
+
 struct sk_buff *
 aoecmd_ata_id(struct aoedev *d)
 {
@@ -1227,6 +1463,7 @@ aoecmd_ata_id(struct aoedev *d)
        fhash(f);
        t->nout++;
        f->waited = 0;
+       f->waited_total = 0;
 
        /* set up ata header */
        ah->scnt = 1;
@@ -1235,41 +1472,69 @@ aoecmd_ata_id(struct aoedev *d)
 
        skb->dev = t->ifp->nd;
 
-       d->rttavg = MAXTIMER;
+       d->rttavg = RTTAVG_INIT;
+       d->rttdev = RTTDEV_INIT;
        d->timer.function = rexmit_timer;
 
-       return skb_clone(skb, GFP_ATOMIC);
+       skb = skb_clone(skb, GFP_ATOMIC);
+       if (skb) {
+               do_gettimeofday(&f->sent);
+               f->sent_jiffs = (u32) jiffies;
+       }
+
+       return skb;
 }
+
+static struct aoetgt **
+grow_targets(struct aoedev *d)
+{
+       ulong oldn, newn;
+       struct aoetgt **tt;
+
+       oldn = d->ntargets;
+       newn = oldn * 2;
+       tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC);
+       if (!tt)
+               return NULL;
+       memmove(tt, d->targets, sizeof(*d->targets) * oldn);
+       d->tgt = tt + (d->tgt - d->targets);
+       kfree(d->targets);
+       d->targets = tt;
+       d->ntargets = newn;
+
+       return &d->targets[oldn];
+}
+
 static struct aoetgt *
 addtgt(struct aoedev *d, char *addr, ulong nframes)
 {
        struct aoetgt *t, **tt, **te;
 
        tt = d->targets;
-       te = tt + NTARGETS;
+       te = tt + d->ntargets;
        for (; tt < te && *tt; tt++)
                ;
 
        if (tt == te) {
-               printk(KERN_INFO
-                       "aoe: device addtgt failure; too many targets\n");
-               return NULL;
+               tt = grow_targets(d);
+               if (!tt)
+                       goto nomem;
        }
        t = kzalloc(sizeof(*t), GFP_ATOMIC);
-       if (!t) {
-               printk(KERN_INFO "aoe: cannot allocate memory to add target\n");
-               return NULL;
-       }
-
-       d->ntargets++;
+       if (!t)
+               goto nomem;
        t->nframes = nframes;
        t->d = d;
        memcpy(t->addr, addr, sizeof t->addr);
        t->ifp = t->ifs;
-       t->maxout = t->nframes;
+       aoecmd_wreset(t);
+       t->maxout = t->nframes / 2;
        INIT_LIST_HEAD(&t->ffree);
        return *tt = t;
+
+ nomem:
+       pr_info("aoe: cannot allocate memory to add target\n");
+       return NULL;
 }
 
 static void
@@ -1279,7 +1544,7 @@ setdbcnt(struct aoedev *d)
        int bcnt = 0;
 
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                if (bcnt == 0 || bcnt > (*t)->minbcnt)
                        bcnt = (*t)->minbcnt;
@@ -1373,7 +1638,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
        spin_lock_irqsave(&d->lock, flags);
 
        t = gettgt(d, h->src);
-       if (!t) {
+       if (t) {
+               t->nframes = n;
+               if (n < t->maxout)
+                       aoecmd_wreset(t);
+       } else {
                t = addtgt(d, h->src, n);
                if (!t)
                        goto bail;
@@ -1401,18 +1670,27 @@ bail:
        }
 }
 
+void
+aoecmd_wreset(struct aoetgt *t)
+{
+       t->maxout = 1;
+       t->ssthresh = t->nframes / 2;
+       t->next_cwnd = t->nframes;
+}
+
 void
 aoecmd_cleanslate(struct aoedev *d)
 {
        struct aoetgt **t, **te;
 
-       d->mintimer = MINTIMER;
+       d->rttavg = RTTAVG_INIT;
+       d->rttdev = RTTDEV_INIT;
        d->maxbcnt = 0;
 
        t = d->targets;
-       te = t + NTARGETS;
+       te = t + d->ntargets;
        for (; t < te && *t; t++)
-               (*t)->maxout = (*t)->nframes;
+               aoecmd_wreset(*t);
 }
 
 void
@@ -1460,6 +1738,14 @@ aoe_flush_iocq(void)
 int __init
 aoecmd_init(void)
 {
+       void *p;
+
+       /* get_zeroed_page returns page with ref count 1 */
+       p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+       if (!p)
+               return -ENOMEM;
+       empty_page = virt_to_page(p);
+
        INIT_LIST_HEAD(&iocq.head);
        spin_lock_init(&iocq.lock);
        init_waitqueue_head(&ktiowq);
@@ -1475,4 +1761,7 @@ aoecmd_exit(void)
 {
        aoe_ktstop(&kts);
        aoe_flush_iocq();
+
+       free_page((unsigned long) page_address(empty_page));
+       empty_page = NULL;
 }
index 90e5b537f94bf3875afe7f73404a626a9994c37a..98f2965778b9ce18a4a58aaf91544d5b35a3d134 100644 (file)
@@ -15,7 +15,6 @@
 #include "aoe.h"
 
 static void dummy_timer(ulong);
-static void aoedev_freedev(struct aoedev *);
 static void freetgt(struct aoedev *d, struct aoetgt *t);
 static void skbpoolfree(struct aoedev *d);
 
@@ -69,25 +68,34 @@ minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin)
                NPERSHELF = 16,
        };
 
+       if (aoemin >= NPERSHELF) {
+               pr_err("aoe: %s %d slots per shelf\n",
+                       "static minor device numbers support only",
+                       NPERSHELF);
+               error = -1;
+               goto out;
+       }
+
        n = aoemaj * NPERSHELF + aoemin;
-       if (aoemin >= NPERSHELF || n >= N_DEVS) {
+       if (n >= N_DEVS) {
                pr_err("aoe: %s with e%ld.%d\n",
                        "cannot use static minor device numbers",
                        aoemaj, aoemin);
                error = -1;
-       } else {
-               spin_lock_irqsave(&used_minors_lock, flags);
-               if (test_bit(n, used_minors)) {
-                       pr_err("aoe: %s %lu\n",
-                               "existing device already has static minor number",
-                               n);
-                       error = -1;
-               } else
-                       set_bit(n, used_minors);
-               spin_unlock_irqrestore(&used_minors_lock, flags);
+               goto out;
        }
 
-       *sysminor = n;
+       spin_lock_irqsave(&used_minors_lock, flags);
+       if (test_bit(n, used_minors)) {
+               pr_err("aoe: %s %lu\n",
+                       "existing device already has static minor number",
+                       n);
+               error = -1;
+       } else
+               set_bit(n, used_minors);
+       spin_unlock_irqrestore(&used_minors_lock, flags);
+       *sysminor = n * AOE_PARTITIONS;
+out:
        return error;
 }
 
@@ -170,41 +178,50 @@ aoe_failip(struct aoedev *d)
                aoe_end_request(d, rq, 0);
 }
 
+static void
+downdev_frame(struct list_head *pos)
+{
+       struct frame *f;
+
+       f = list_entry(pos, struct frame, head);
+       list_del(pos);
+       if (f->buf) {
+               f->buf->nframesout--;
+               aoe_failbuf(f->t->d, f->buf);
+       }
+       aoe_freetframe(f);
+}
+
 void
 aoedev_downdev(struct aoedev *d)
 {
        struct aoetgt *t, **tt, **te;
-       struct frame *f;
        struct list_head *head, *pos, *nx;
        struct request *rq;
        int i;
 
        d->flags &= ~DEVFL_UP;
 
-       /* clean out active buffers */
+       /* clean out active and to-be-retransmitted buffers */
        for (i = 0; i < NFACTIVE; i++) {
                head = &d->factive[i];
-               list_for_each_safe(pos, nx, head) {
-                       f = list_entry(pos, struct frame, head);
-                       list_del(pos);
-                       if (f->buf) {
-                               f->buf->nframesout--;
-                               aoe_failbuf(d, f->buf);
-                       }
-                       aoe_freetframe(f);
-               }
+               list_for_each_safe(pos, nx, head)
+                       downdev_frame(pos);
        }
+       head = &d->rexmitq;
+       list_for_each_safe(pos, nx, head)
+               downdev_frame(pos);
+
        /* reset window dressings */
        tt = d->targets;
-       te = tt + NTARGETS;
+       te = tt + d->ntargets;
        for (; tt < te && (t = *tt); tt++) {
-               t->maxout = t->nframes;
+               aoecmd_wreset(t);
                t->nout = 0;
        }
 
        /* clean out the in-process request (if any) */
        aoe_failip(d);
-       d->htgt = NULL;
 
        /* fast fail all pending I/O */
        if (d->blkq) {
@@ -218,12 +235,48 @@ aoedev_downdev(struct aoedev *d)
                set_capacity(d->gd, 0);
 }
 
+/* return whether the user asked for this particular
+ * device to be flushed
+ */
+static int
+user_req(char *s, size_t slen, struct aoedev *d)
+{
+       char *p;
+       size_t lim;
+
+       if (!d->gd)
+               return 0;
+       p = strrchr(d->gd->disk_name, '/');
+       if (!p)
+               p = d->gd->disk_name;
+       else
+               p += 1;
+       lim = sizeof(d->gd->disk_name);
+       lim -= p - d->gd->disk_name;
+       if (slen < lim)
+               lim = slen;
+
+       return !strncmp(s, p, lim);
+}
+
 static void
-aoedev_freedev(struct aoedev *d)
+freedev(struct aoedev *d)
 {
        struct aoetgt **t, **e;
+       int freeing = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&d->lock, flags);
+       if (d->flags & DEVFL_TKILL
+       && !(d->flags & DEVFL_FREEING)) {
+               d->flags |= DEVFL_FREEING;
+               freeing = 1;
+       }
+       spin_unlock_irqrestore(&d->lock, flags);
+       if (!freeing)
+               return;
 
-       cancel_work_sync(&d->work);
+       del_timer_sync(&d->timer);
        if (d->gd) {
                aoedisk_rm_sysfs(d);
                del_gendisk(d->gd);
@@ -231,61 +284,113 @@ aoedev_freedev(struct aoedev *d)
                blk_cleanup_queue(d->blkq);
        }
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                freetgt(d, *t);
        if (d->bufpool)
                mempool_destroy(d->bufpool);
        skbpoolfree(d);
        minor_free(d->sysminor);
-       kfree(d);
+
+       spin_lock_irqsave(&d->lock, flags);
+       d->flags |= DEVFL_FREED;
+       spin_unlock_irqrestore(&d->lock, flags);
 }
 
-int
-aoedev_flush(const char __user *str, size_t cnt)
+enum flush_parms {
+       NOT_EXITING = 0,
+       EXITING = 1,
+};
+
+static int
+flush(const char __user *str, size_t cnt, int exiting)
 {
        ulong flags;
        struct aoedev *d, **dd;
-       struct aoedev *rmd = NULL;
        char buf[16];
        int all = 0;
+       int specified = 0;      /* flush a specific device */
+       unsigned int skipflags;
+
+       skipflags = DEVFL_GDALLOC | DEVFL_NEWSIZE | DEVFL_TKILL;
 
-       if (cnt >= 3) {
+       if (!exiting && cnt >= 3) {
                if (cnt > sizeof buf)
                        cnt = sizeof buf;
                if (copy_from_user(buf, str, cnt))
                        return -EFAULT;
                all = !strncmp(buf, "all", 3);
+               if (!all)
+                       specified = 1;
        }
 
+       flush_scheduled_work();
+       /* pass one: without sleeping, do aoedev_downdev */
        spin_lock_irqsave(&devlist_lock, flags);
-       dd = &devlist;
-       while ((d = *dd)) {
+       for (d = devlist; d; d = d->next) {
                spin_lock(&d->lock);
-               if ((!all && (d->flags & DEVFL_UP))
-               || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
+               if (exiting) {
+                       /* unconditionally take each device down */
+               } else if (specified) {
+                       if (!user_req(buf, cnt, d))
+                               goto cont;
+               } else if ((!all && (d->flags & DEVFL_UP))
+               || d->flags & skipflags
                || d->nopen
-               || d->ref) {
-                       spin_unlock(&d->lock);
-                       dd = &d->next;
-                       continue;
-               }
-               *dd = d->next;
+               || d->ref)
+                       goto cont;
+
                aoedev_downdev(d);
                d->flags |= DEVFL_TKILL;
+cont:
                spin_unlock(&d->lock);
-               d->next = rmd;
-               rmd = d;
        }
        spin_unlock_irqrestore(&devlist_lock, flags);
-       while ((d = rmd)) {
-               rmd = d->next;
-               del_timer_sync(&d->timer);
-               aoedev_freedev(d);      /* must be able to sleep */
+
+       /* pass two: call freedev, which might sleep,
+        * for aoedevs marked with DEVFL_TKILL
+        */
+restart:
+       spin_lock_irqsave(&devlist_lock, flags);
+       for (d = devlist; d; d = d->next) {
+               spin_lock(&d->lock);
+               if (d->flags & DEVFL_TKILL
+               && !(d->flags & DEVFL_FREEING)) {
+                       spin_unlock(&d->lock);
+                       spin_unlock_irqrestore(&devlist_lock, flags);
+                       freedev(d);
+                       goto restart;
+               }
+               spin_unlock(&d->lock);
        }
+
+       /* pass three: remove aoedevs marked with DEVFL_FREED */
+       for (dd = &devlist, d = *dd; d; d = *dd) {
+               struct aoedev *doomed = NULL;
+
+               spin_lock(&d->lock);
+               if (d->flags & DEVFL_FREED) {
+                       *dd = d->next;
+                       doomed = d;
+               } else {
+                       dd = &d->next;
+               }
+               spin_unlock(&d->lock);
+               if (doomed)
+                       kfree(doomed->targets);
+               kfree(doomed);
+       }
+       spin_unlock_irqrestore(&devlist_lock, flags);
+
        return 0;
 }
 
+int
+aoedev_flush(const char __user *str, size_t cnt)
+{
+       return flush(str, cnt, NOT_EXITING);
+}
+
 /* This has been confirmed to occur once with Tms=3*1000 due to the
  * driver changing link and not processing its transmit ring.  The
  * problem is hard enough to solve by returning an error that I'm
@@ -332,13 +437,20 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
        struct aoedev *d;
        int i;
        ulong flags;
-       ulong sysminor;
+       ulong sysminor = 0;
 
        spin_lock_irqsave(&devlist_lock, flags);
 
        for (d=devlist; d; d=d->next)
                if (d->aoemajor == maj && d->aoeminor == min) {
+                       spin_lock(&d->lock);
+                       if (d->flags & DEVFL_TKILL) {
+                               spin_unlock(&d->lock);
+                               d = NULL;
+                               goto out;
+                       }
                        d->ref++;
+                       spin_unlock(&d->lock);
                        break;
                }
        if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0)
@@ -346,6 +458,13 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
        d = kcalloc(1, sizeof *d, GFP_ATOMIC);
        if (!d)
                goto out;
+       d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC);
+       if (!d->targets) {
+               kfree(d);
+               d = NULL;
+               goto out;
+       }
+       d->ntargets = NTARGETS;
        INIT_WORK(&d->work, aoecmd_sleepwork);
        spin_lock_init(&d->lock);
        skb_queue_head_init(&d->skbpool);
@@ -359,10 +478,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
        d->ref = 1;
        for (i = 0; i < NFACTIVE; i++)
                INIT_LIST_HEAD(&d->factive[i]);
+       INIT_LIST_HEAD(&d->rexmitq);
        d->sysminor = sysminor;
        d->aoemajor = maj;
        d->aoeminor = min;
-       d->mintimer = MINTIMER;
+       d->rttavg = RTTAVG_INIT;
+       d->rttdev = RTTDEV_INIT;
        d->next = devlist;
        devlist = d;
  out:
@@ -396,21 +517,9 @@ freetgt(struct aoedev *d, struct aoetgt *t)
 void
 aoedev_exit(void)
 {
-       struct aoedev *d;
-       ulong flags;
-
+       flush_scheduled_work();
        aoe_flush_iocq();
-       while ((d = devlist)) {
-               devlist = d->next;
-
-               spin_lock_irqsave(&d->lock, flags);
-               aoedev_downdev(d);
-               d->flags |= DEVFL_TKILL;
-               spin_unlock_irqrestore(&d->lock, flags);
-
-               del_timer_sync(&d->timer);
-               aoedev_freedev(d);
-       }
+       flush(NULL, 0, EXITING);
 }
 
 int __init
index 04793c2c701b7b0bf707a576a5a9e1a01bccc376..4b987c2fefbe5ececb3ded4002c3075167a3082c 100644 (file)
@@ -105,7 +105,7 @@ aoe_init(void)
        aoechr_exit();
  chr_fail:
        aoedev_exit();
-       
+
        printk(KERN_INFO "aoe: initialisation failure.\n");
        return ret;
 }
index 162c6471275c6792454871732e1d4d21cefa04ac..71d3ea8d30062cc85b7edba1e4f8270673f6a829 100644 (file)
@@ -31,7 +31,7 @@ enum {
 
 static char aoe_iflist[IFLISTSZ];
 module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600);
-MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\"");
+MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=dev1[,dev2...]");
 
 static wait_queue_head_t txwq;
 static struct ktstate kts;
@@ -52,13 +52,18 @@ static struct sk_buff_head skbtxq;
 
 /* enters with txlock held */
 static int
-tx(void)
+tx(void) __must_hold(&txlock)
 {
        struct sk_buff *skb;
+       struct net_device *ifp;
 
        while ((skb = skb_dequeue(&skbtxq))) {
                spin_unlock_irq(&txlock);
-               dev_queue_xmit(skb);
+               ifp = skb->dev;
+               if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit())
+                       pr_warn("aoe: packet could not be sent on %s.  %s\n",
+                               ifp ? ifp->name : "netif",
+                               "consider increasing tx_queue_len");
                spin_lock_irq(&txlock);
        }
        return 0;
@@ -119,8 +124,8 @@ aoenet_xmit(struct sk_buff_head *queue)
        }
 }
 
-/* 
- * (1) len doesn't include the header by default.  I want this. 
+/*
+ * (1) len doesn't include the header by default.  I want this.
  */
 static int
 aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
index 24225f0fdcd85f93d5feccae6d935e1563a679fb..64b048d7fba751de8f5faf7b73062ea104aeea15 100644 (file)
@@ -228,6 +228,20 @@ static void dmatest_callback(void *arg)
        wake_up_all(done->wait);
 }
 
+static inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len,
+                            unsigned int count)
+{
+       while (count--)
+               dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE);
+}
+
+static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len,
+                            unsigned int count)
+{
+       while (count--)
+               dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL);
+}
+
 /*
  * This function repeatedly tests DMA transfers of various lengths and
  * offsets for a given operation type until it is told to exit by
@@ -353,15 +367,35 @@ static int dmatest_func(void *data)
 
                        dma_srcs[i] = dma_map_single(dev->dev, buf, len,
                                                     DMA_TO_DEVICE);
+                       ret = dma_mapping_error(dev->dev, dma_srcs[i]);
+                       if (ret) {
+                               unmap_src(dev->dev, dma_srcs, len, i);
+                               pr_warn("%s: #%u: mapping error %d with "
+                                       "src_off=0x%x len=0x%x\n",
+                                       thread_name, total_tests - 1, ret,
+                                       src_off, len);
+                               failed_tests++;
+                               continue;
+                       }
                }
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                for (i = 0; i < dst_cnt; i++) {
                        dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
                                                     test_buf_size,
                                                     DMA_BIDIRECTIONAL);
+                       ret = dma_mapping_error(dev->dev, dma_dsts[i]);
+                       if (ret) {
+                               unmap_src(dev->dev, dma_srcs, len, src_cnt);
+                               unmap_dst(dev->dev, dma_dsts, test_buf_size, i);
+                               pr_warn("%s: #%u: mapping error %d with "
+                                       "dst_off=0x%x len=0x%x\n",
+                                       thread_name, total_tests - 1, ret,
+                                       dst_off, test_buf_size);
+                               failed_tests++;
+                               continue;
+                       }
                }
 
-
                if (thread->type == DMA_MEMCPY)
                        tx = dev->device_prep_dma_memcpy(chan,
                                                         dma_dsts[0] + dst_off,
@@ -383,13 +417,8 @@ static int dmatest_func(void *data)
                }
 
                if (!tx) {
-                       for (i = 0; i < src_cnt; i++)
-                               dma_unmap_single(dev->dev, dma_srcs[i], len,
-                                                DMA_TO_DEVICE);
-                       for (i = 0; i < dst_cnt; i++)
-                               dma_unmap_single(dev->dev, dma_dsts[i],
-                                                test_buf_size,
-                                                DMA_BIDIRECTIONAL);
+                       unmap_src(dev->dev, dma_srcs, len, src_cnt);
+                       unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt);
                        pr_warning("%s: #%u: prep error with src_off=0x%x "
                                        "dst_off=0x%x len=0x%x\n",
                                        thread_name, total_tests - 1,
@@ -443,9 +472,7 @@ static int dmatest_func(void *data)
                }
 
                /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
-               for (i = 0; i < dst_cnt; i++)
-                       dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size,
-                                        DMA_BIDIRECTIONAL);
+               unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt);
 
                error_count = 0;
 
index a932c485eb04f9c7b40c14c924c7aa172be71244..c3c13e64a2f0c55117397ba9436ea35946669fd4 100644 (file)
@@ -1397,10 +1397,7 @@ int do_read_error(struct nandsim *ns, int num)
        unsigned int page_no = ns->regs.row;
 
        if (read_error(page_no)) {
-               int i;
-               memset(ns->buf.byte, 0xFF, num);
-               for (i = 0; i < num; ++i)
-                       ns->buf.byte[i] = random32();
+               prandom_bytes(ns->buf.byte, num);
                NS_WARN("simulating read error in page %u\n", page_no);
                return 1;
        }
index a2998bea5d4b42690ca1334322d5ebe396ef0805..01588b66a38c0fea2d489b869d730fb8966c3419 100644 (file)
@@ -1832,7 +1832,6 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
                        bool config_hash)
 {
        struct bnx2x_config_rss_params params = {NULL};
-       int i;
 
        /* Although RSS is meaningless when there is a single HW queue we
         * still need it enabled in order to have HW Rx hash generated.
@@ -1864,9 +1863,7 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 
        if (config_hash) {
                /* RSS keys */
-               for (i = 0; i < sizeof(params.rss_key) / 4; i++)
-                       params.rss_key[i] = random32();
-
+               prandom_bytes(params.rss_key, sizeof(params.rss_key));
                __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
        }
 
index 6deaae18db575e166216c097ff01cbc8e7893b07..28aa05f60c26f51c567080f5efae7461a1ee974b 100644 (file)
@@ -156,11 +156,7 @@ config PRISM54
        ---help---
          This enables support for FullMAC PCI/Cardbus prism54 devices. This
          driver is now deprecated in favor for the SoftMAC driver, p54pci.
-         p54pci supports FullMAC PCI/Cardbus devices as well. For details on
-         the scheduled removal of this driver on the kernel see the feature
-         removal schedule:
-
-         Documentation/feature-removal-schedule.txt
+         p54pci supports FullMAC PCI/Cardbus devices as well.
 
          For more information refer to the p54 wiki:
 
index a65c39c473bf36368493bd794222ab45d328706c..808be06bb67e7d4eeaf4f7250fae2dace0cc0f8d 100644 (file)
@@ -488,14 +488,8 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
                depth++;
                pathp = (char *)p;
                p = ALIGN(p + strlen(pathp) + 1, 4);
-               if ((*pathp) == '/') {
-                       const char *lp, *np;
-                       for (lp = NULL, np = pathp; *np; np++)
-                               if ((*np) == '/')
-                                       lp = np+1;
-                       if (lp != NULL)
-                               pathp = lp;
-               }
+               if (*pathp == '/')
+                       pathp = kbasename(pathp);
                rc = it(p, pathp, depth, data);
                if (rc != 0)
                        break;
index 6b0ebdeae916c727393aab1472e431bfd13e715a..be790402e0f1ad07e5df973923103e545f30a295 100644 (file)
@@ -32,7 +32,7 @@
 
 #define        ASUS_NB_WMI_FILE        "asus-nb-wmi"
 
-MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
+MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
 MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
 MODULE_LICENSE("GPL");
 
index c0e9ff489b2417f2469e7abc7d2289e4b971c8a2..f80ae4d10f6818537a61f975bc468ea3d6e342b9 100644 (file)
@@ -51,7 +51,7 @@
 
 #include "asus-wmi.h"
 
-MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
+MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>, "
              "Yong Wang <yong.y.wang@intel.com>");
 MODULE_DESCRIPTION("Asus Generic WMI Driver");
 MODULE_LICENSE("GPL");
index 5838332ea5bd2f67c6e0f5c875a459027b8032e9..60cb76a5b51362ca4d3d840360ef871b3f62e20f 100644 (file)
@@ -39,7 +39,7 @@
 
 #define        EEEPC_WMI_FILE  "eeepc-wmi"
 
-MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
+MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
 MODULE_LICENSE("GPL");
 
index 19c03ab2bdcb3f2d585c7b38948b5de3bff113c1..d0cea02b5dfc5b58ca4ee3751f1c5737b221739d 100644 (file)
@@ -269,6 +269,15 @@ config RTC_DRV_X1205
          This driver can also be built as a module. If so, the module
          will be called rtc-x1205.
 
+config RTC_DRV_PCF8523
+       tristate "NXP PCF8523"
+       help
+         If you say yes here you get support for the NXP PCF8523 RTC
+         chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-pcf8523.
+
 config RTC_DRV_PCF8563
        tristate "Philips PCF8563/Epson RTC8564"
        help
@@ -600,6 +609,16 @@ config RTC_DRV_DA9052
          Say y here to support the RTC driver for Dialog Semiconductor
          DA9052-BC and DA9053-AA/Bx PMICs.
 
+config RTC_DRV_DA9055
+       tristate "Dialog Semiconductor DA9055 RTC"
+       depends on MFD_DA9055
+       help
+         If you say yes here you will get support for the
+         RTC of the Dialog DA9055 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-da9055
+
 config RTC_DRV_EFI
        tristate "EFI RTC"
        depends on IA64
@@ -768,7 +787,7 @@ config RTC_DRV_DAVINCI
 
 config RTC_DRV_IMXDI
        tristate "Freescale IMX DryIce Real Time Clock"
-       depends on SOC_IMX25
+       depends on ARCH_MXC
        help
           Support for Freescale IMX DryIce RTC
 
@@ -777,11 +796,13 @@ config RTC_DRV_IMXDI
 
 config RTC_DRV_OMAP
        tristate "TI OMAP1"
-       depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
+       depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
        help
-         Say "yes" here to support the real time clock on TI OMAP1 and
-         DA8xx/OMAP-L13x chips.  This driver can also be built as a
-         module called rtc-omap.
+         Say "yes" here to support the on chip real time clock
+         present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x.
+
+         This driver can also be built as a module, if so, module
+         will be called rtc-omap.
 
 config HAVE_S3C_RTC
        bool
index 56297f0fd3884fde9d85cd305cd4b16b439053d2..c3f62c80dc062687b435f24cc3dcbf8d4fd89794 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_RTC_DRV_BQ4802)  += rtc-bq4802.o
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_COH901331)        += rtc-coh901331.o
 obj-$(CONFIG_RTC_DRV_DA9052)   += rtc-da9052.o
+obj-$(CONFIG_RTC_DRV_DA9055)   += rtc-da9055.o
 obj-$(CONFIG_RTC_DRV_DAVINCI)  += rtc-davinci.o
 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
 obj-$(CONFIG_RTC_DRV_VRTC)     += rtc-mrst.o
@@ -76,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_MV)      += rtc-mv.o
 obj-$(CONFIG_RTC_DRV_NUC900)   += rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)     += rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCAP)     += rtc-pcap.o
+obj-$(CONFIG_RTC_DRV_PCF8523)  += rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)  += rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)  += rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PCF2123)  += rtc-pcf2123.o
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
new file mode 100644 (file)
index 0000000..96bafc5
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Real time clock driver for DA9055
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: Dajun Dajun Chen <dajun.chen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+struct da9055_rtc {
+       struct rtc_device *rtc;
+       struct da9055 *da9055;
+       int alarm_enable;
+};
+
+static int da9055_rtc_enable_alarm(struct da9055_rtc *rtc, bool enable)
+{
+       int ret;
+       if (enable) {
+               ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y,
+                                       DA9055_RTC_ALM_EN,
+                                       DA9055_RTC_ALM_EN);
+               if (ret != 0)
+                       dev_err(rtc->da9055->dev, "Failed to enable ALM: %d\n",
+                               ret);
+               rtc->alarm_enable = 1;
+       } else {
+               ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y,
+                                       DA9055_RTC_ALM_EN, 0);
+               if (ret != 0)
+                       dev_err(rtc->da9055->dev,
+                               "Failed to disable ALM: %d\n", ret);
+               rtc->alarm_enable = 0;
+       }
+       return ret;
+}
+
+static irqreturn_t da9055_rtc_alm_irq(int irq, void *data)
+{
+       struct da9055_rtc *rtc = data;
+
+       da9055_rtc_enable_alarm(rtc, 0);
+       rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
+{
+       int ret;
+       uint8_t v[5];
+
+       ret = da9055_group_read(da9055, DA9055_REG_ALARM_MI, 5, v);
+       if (ret != 0) {
+               dev_err(da9055->dev, "Failed to group read ALM: %d\n", ret);
+               return ret;
+       }
+
+       rtc_tm->tm_year = (v[4] & DA9055_RTC_ALM_YEAR) + 100;
+       rtc_tm->tm_mon  = (v[3] & DA9055_RTC_ALM_MONTH) - 1;
+       rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY;
+       rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR;
+       rtc_tm->tm_min  = v[0] & DA9055_RTC_ALM_MIN;
+
+       return rtc_valid_tm(rtc_tm);
+}
+
+static int da9055_set_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
+{
+       int ret;
+       uint8_t v[2];
+
+       rtc_tm->tm_year -= 100;
+       rtc_tm->tm_mon += 1;
+
+       ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MI,
+                               DA9055_RTC_ALM_MIN, rtc_tm->tm_min);
+       if (ret != 0) {
+               dev_err(da9055->dev, "Failed to write ALRM MIN: %d\n", ret);
+               return ret;
+       }
+
+       v[0] = rtc_tm->tm_hour;
+       v[1] = rtc_tm->tm_mday;
+
+       ret = da9055_group_write(da9055, DA9055_REG_ALARM_H, 2, v);
+       if (ret < 0)
+               return ret;
+
+       ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO,
+                               DA9055_RTC_ALM_MONTH, rtc_tm->tm_mon);
+       if (ret < 0)
+               dev_err(da9055->dev, "Failed to write ALM Month:%d\n", ret);
+
+       ret = da9055_reg_update(da9055, DA9055_REG_ALARM_Y,
+                               DA9055_RTC_ALM_YEAR, rtc_tm->tm_year);
+       if (ret < 0)
+               dev_err(da9055->dev, "Failed to write ALM Year:%d\n", ret);
+
+       return ret;
+}
+
+static int da9055_rtc_get_alarm_status(struct da9055 *da9055)
+{
+       int ret;
+
+       ret = da9055_reg_read(da9055, DA9055_REG_ALARM_Y);
+       if (ret < 0) {
+               dev_err(da9055->dev, "Failed to read ALM: %d\n", ret);
+               return ret;
+       }
+       ret &= DA9055_RTC_ALM_EN;
+       return (ret > 0) ? 1 : 0;
+}
+
+static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
+{
+       struct da9055_rtc *rtc = dev_get_drvdata(dev);
+       uint8_t v[6];
+       int ret;
+
+       ret = da9055_reg_read(rtc->da9055, DA9055_REG_COUNT_S);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Registers are only valid when RTC_READ
+        * status bit is asserted
+        */
+       if (!(ret & DA9055_RTC_READ))
+               return -EBUSY;
+
+       ret = da9055_group_read(rtc->da9055, DA9055_REG_COUNT_S, 6, v);
+       if (ret < 0) {
+               dev_err(rtc->da9055->dev, "Failed to read RTC time : %d\n",
+                       ret);
+               return ret;
+       }
+
+       rtc_tm->tm_year = (v[5] & DA9055_RTC_YEAR) + 100;
+       rtc_tm->tm_mon  = (v[4] & DA9055_RTC_MONTH) - 1;
+       rtc_tm->tm_mday = v[3] & DA9055_RTC_DAY;
+       rtc_tm->tm_hour = v[2] & DA9055_RTC_HOUR;
+       rtc_tm->tm_min  = v[1] & DA9055_RTC_MIN;
+       rtc_tm->tm_sec  = v[0] & DA9055_RTC_SEC;
+
+       return rtc_valid_tm(rtc_tm);
+}
+
+static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct da9055_rtc *rtc;
+       uint8_t v[6];
+
+       rtc = dev_get_drvdata(dev);
+
+       v[0] = tm->tm_sec;
+       v[1] = tm->tm_min;
+       v[2] = tm->tm_hour;
+       v[3] = tm->tm_mday;
+       v[4] = tm->tm_mon + 1;
+       v[5] = tm->tm_year - 100;
+
+       return da9055_group_write(rtc->da9055, DA9055_REG_COUNT_S, 6, v);
+}
+
+static int da9055_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       int ret;
+       struct rtc_time *tm = &alrm->time;
+       struct da9055_rtc *rtc = dev_get_drvdata(dev);
+
+       ret = da9055_read_alarm(rtc->da9055, tm);
+
+       if (ret)
+               return ret;
+
+       alrm->enabled = da9055_rtc_get_alarm_status(rtc->da9055);
+
+       return 0;
+}
+
+static int da9055_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       int ret;
+       struct rtc_time *tm = &alrm->time;
+       struct da9055_rtc *rtc = dev_get_drvdata(dev);
+
+       ret = da9055_rtc_enable_alarm(rtc, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = da9055_set_alarm(rtc->da9055, tm);
+       if (ret)
+               return ret;
+
+       ret = da9055_rtc_enable_alarm(rtc, 1);
+
+       return ret;
+}
+
+static int da9055_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct da9055_rtc *rtc = dev_get_drvdata(dev);
+
+       return da9055_rtc_enable_alarm(rtc, enabled);
+}
+
+static const struct rtc_class_ops da9055_rtc_ops = {
+       .read_time      = da9055_rtc_read_time,
+       .set_time       = da9055_rtc_set_time,
+       .read_alarm     = da9055_rtc_read_alarm,
+       .set_alarm      = da9055_rtc_set_alarm,
+       .alarm_irq_enable = da9055_rtc_alarm_irq_enable,
+};
+
+static int __init da9055_rtc_device_init(struct da9055 *da9055,
+                                       struct da9055_pdata *pdata)
+{
+       int ret;
+
+       /* Enable RTC and the internal Crystal */
+       ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
+                               DA9055_RTC_EN, DA9055_RTC_EN);
+       if (ret < 0)
+               return ret;
+       ret = da9055_reg_update(da9055, DA9055_REG_EN_32K,
+                               DA9055_CRYSTAL_EN, DA9055_CRYSTAL_EN);
+       if (ret < 0)
+               return ret;
+
+       /* Enable RTC in Power Down mode */
+       ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
+                               DA9055_RTC_MODE_PD, DA9055_RTC_MODE_PD);
+       if (ret < 0)
+               return ret;
+
+       /* Enable RTC in Reset mode */
+       if (pdata && pdata->reset_enable) {
+               ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
+                                       DA9055_RTC_MODE_SD,
+                                       DA9055_RTC_MODE_SD <<
+                                       DA9055_RTC_MODE_SD_SHIFT);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /* Disable the RTC TICK ALM */
+       ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO,
+                               DA9055_RTC_TICK_WAKE_MASK, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int da9055_rtc_probe(struct platform_device *pdev)
+{
+       struct da9055_rtc *rtc;
+       struct da9055_pdata *pdata = NULL;
+       int ret, alm_irq;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+
+       rtc->da9055 = dev_get_drvdata(pdev->dev.parent);
+       pdata = rtc->da9055->dev->platform_data;
+       platform_set_drvdata(pdev, rtc);
+
+       ret = da9055_rtc_device_init(rtc->da9055, pdata);
+       if (ret < 0)
+               goto err_rtc;
+
+       ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y);
+       if (ret < 0)
+               goto err_rtc;
+
+       if (ret & DA9055_RTC_ALM_EN)
+               rtc->alarm_enable = 1;
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+                                       &da9055_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc)) {
+               ret = PTR_ERR(rtc->rtc);
+               goto err_rtc;
+       }
+
+       alm_irq = platform_get_irq_byname(pdev, "ALM");
+       alm_irq = regmap_irq_get_virq(rtc->da9055->irq_data, alm_irq);
+       ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL,
+                                       da9055_rtc_alm_irq,
+                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       "ALM", rtc);
+       if (ret != 0)
+               dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret);
+
+err_rtc:
+       return ret;
+
+}
+
+static int da9055_rtc_remove(struct platform_device *pdev)
+{
+       struct da9055_rtc *rtc = pdev->dev.platform_data;
+
+       rtc_device_unregister(rtc->rtc);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/* Turn off the alarm if it should not be a wake source. */
+static int da9055_rtc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
+
+       if (!device_may_wakeup(&pdev->dev)) {
+               /* Disable the ALM IRQ */
+               ret = da9055_rtc_enable_alarm(rtc, 0);
+               if (ret < 0)
+                       dev_err(&pdev->dev, "Failed to disable RTC ALM\n");
+       }
+
+       return 0;
+}
+
+/* Enable the alarm if it should be enabled (in case it was disabled to
+ * prevent use as a wake source).
+ */
+static int da9055_rtc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
+
+       if (!device_may_wakeup(&pdev->dev)) {
+               if (rtc->alarm_enable) {
+                       ret = da9055_rtc_enable_alarm(rtc, 1);
+                       if (ret < 0)
+                               dev_err(&pdev->dev,
+                                       "Failed to restart RTC ALM\n");
+               }
+       }
+
+       return 0;
+}
+
+/* Unconditionally disable the alarm */
+static int da9055_rtc_freeze(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
+
+       ret = da9055_rtc_enable_alarm(rtc, 0);
+       if (ret < 0)
+               dev_err(&pdev->dev, "Failed to freeze RTC ALMs\n");
+
+       return 0;
+
+}
+#else
+#define da9055_rtc_suspend NULL
+#define da9055_rtc_resume NULL
+#define da9055_rtc_freeze NULL
+#endif
+
+static const struct dev_pm_ops da9055_rtc_pm_ops = {
+       .suspend = da9055_rtc_suspend,
+       .resume = da9055_rtc_resume,
+
+       .freeze = da9055_rtc_freeze,
+       .thaw = da9055_rtc_resume,
+       .restore = da9055_rtc_resume,
+
+       .poweroff = da9055_rtc_suspend,
+};
+
+static struct platform_driver da9055_rtc_driver = {
+       .probe  = da9055_rtc_probe,
+       .remove = da9055_rtc_remove,
+       .driver = {
+               .name   = "da9055-rtc",
+               .owner  = THIS_MODULE,
+               .pm = &da9055_rtc_pm_ops,
+       },
+};
+
+module_platform_driver(da9055_rtc_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-rtc");
index 14c2109dbaa3dbed844144864fa7b7a3d4190ec8..07cd03eae60605f1c993ce585182ad0dd5f33c96 100644 (file)
@@ -485,7 +485,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
        struct resource *res, *mem;
        int ret = 0;
 
-       davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL);
+       davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL);
        if (!davinci_rtc) {
                dev_dbg(dev, "could not allocate memory for private data\n");
                return -ENOMEM;
@@ -494,15 +494,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
        davinci_rtc->irq = platform_get_irq(pdev, 0);
        if (davinci_rtc->irq < 0) {
                dev_err(dev, "no RTC irq\n");
-               ret = davinci_rtc->irq;
-               goto fail1;
+               return davinci_rtc->irq;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "no mem resource\n");
-               ret = -EINVAL;
-               goto fail1;
+               return -EINVAL;
        }
 
        davinci_rtc->pbase = res->start;
@@ -513,8 +511,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
        if (!mem) {
                dev_err(dev, "RTC registers at %08x are not free\n",
                        davinci_rtc->pbase);
-               ret = -EBUSY;
-               goto fail1;
+               return -EBUSY;
        }
 
        davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size);
@@ -529,8 +526,9 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
        davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
                                    &davinci_rtc_ops, THIS_MODULE);
        if (IS_ERR(davinci_rtc->rtc)) {
-               dev_err(dev, "unable to register RTC device, err %ld\n",
-                               PTR_ERR(davinci_rtc->rtc));
+               ret = PTR_ERR(davinci_rtc->rtc);
+               dev_err(dev, "unable to register RTC device, err %d\n",
+                               ret);
                goto fail3;
        }
 
@@ -566,9 +564,6 @@ fail3:
        iounmap(davinci_rtc->base);
 fail2:
        release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
-fail1:
-       kfree(davinci_rtc);
-
        return ret;
 }
 
@@ -589,8 +584,6 @@ static int __devexit davinci_rtc_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       kfree(davinci_rtc);
-
        return 0;
 }
 
index cace6d3aed9a59261bba613af9649b34699fb7a8..9a86b4bd86993d41005d4e336f216377c6751af3 100644 (file)
@@ -379,25 +379,6 @@ static long rtc_dev_ioctl(struct file *file,
                err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
                break;
 
-#if 0
-       case RTC_EPOCH_SET:
-#ifndef rtc_epoch
-               /*
-                * There were no RTC clocks before 1900.
-                */
-               if (arg < 1900) {
-                       err = -EINVAL;
-                       break;
-               }
-               rtc_epoch = arg;
-               err = 0;
-#endif
-               break;
-
-       case RTC_EPOCH_READ:
-               err = put_user(rtc_epoch, (unsigned long __user *)uarg);
-               break;
-#endif
        case RTC_WKALM_SET:
                mutex_unlock(&rtc->ops_lock);
                if (copy_from_user(&alarm, uarg, sizeof(alarm)))
index 4eed51044c5dd331f576fc1b1b71655e5f932366..18a4f0dd78a32cd9d2ff3a2c322cd22fa72113b0 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/rtc.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 
 /* DryIce Register Definitions */
 
@@ -495,10 +496,20 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id dryice_dt_ids[] = {
+       { .compatible = "fsl,imx25-rtc" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, dryice_dt_ids);
+#endif
+
 static struct platform_driver dryice_rtc_driver = {
        .driver = {
                   .name = "imxdi_rtc",
                   .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(dryice_dt_ids),
                   },
        .remove = __devexit_p(dryice_rtc_remove),
 };
index 0b614e32653d81a0f397ca1dfe9a7f1f370add69..600971407aace469fcbd22d679dce74bbc525d5c 100644 (file)
@@ -20,6 +20,9 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/io.h>
 
@@ -38,6 +41,8 @@
  * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment.
  */
 
+#define        DRIVER_NAME                     "omap_rtc"
+
 #define OMAP_RTC_BASE                  0xfffb4800
 
 /* RTC registers */
@@ -64,6 +69,9 @@
 #define OMAP_RTC_COMP_MSB_REG          0x50
 #define OMAP_RTC_OSC_REG               0x54
 
+#define OMAP_RTC_KICK0_REG             0x6c
+#define OMAP_RTC_KICK1_REG             0x70
+
 /* OMAP_RTC_CTRL_REG bit fields: */
 #define OMAP_RTC_CTRL_SPLIT            (1<<7)
 #define OMAP_RTC_CTRL_DISABLE          (1<<6)
 #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
 
+/* OMAP_RTC_KICKER values */
+#define        KICK0_VALUE                     0x83e70b13
+#define        KICK1_VALUE                     0x95a4f1e0
+
+#define        OMAP_RTC_HAS_KICKER             0x1
+
 static void __iomem    *rtc_base;
 
-#define rtc_read(addr)         __raw_readb(rtc_base + (addr))
-#define rtc_write(val, addr)   __raw_writeb(val, rtc_base + (addr))
+#define rtc_read(addr)         readb(rtc_base + (addr))
+#define rtc_write(val, addr)   writeb(val, rtc_base + (addr))
+
+#define rtc_writel(val, addr)  writel(val, rtc_base + (addr))
 
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
@@ -285,11 +301,38 @@ static struct rtc_class_ops omap_rtc_ops = {
 static int omap_rtc_alarm;
 static int omap_rtc_timer;
 
+#define        OMAP_RTC_DATA_DA830_IDX 1
+
+static struct platform_device_id omap_rtc_devtype[] = {
+       {
+               .name   = DRIVER_NAME,
+       }, {
+               .name   = "da830-rtc",
+               .driver_data = OMAP_RTC_HAS_KICKER,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, omap_rtc_devtype);
+
+static const struct of_device_id omap_rtc_of_match[] = {
+       {       .compatible     = "ti,da830-rtc",
+               .data           = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
+
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
        struct resource         *res, *mem;
        struct rtc_device       *rtc;
        u8                      reg, new_ctrl;
+       const struct platform_device_id *id_entry;
+       const struct of_device_id *of_id;
+
+       of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
+       if (of_id)
+               pdev->id_entry = of_id->data;
 
        omap_rtc_timer = platform_get_irq(pdev, 0);
        if (omap_rtc_timer <= 0) {
@@ -322,6 +365,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
                goto fail;
        }
 
+       /* Enable the clock/module so that we can access the registers */
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
+       id_entry = platform_get_device_id(pdev);
+       if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) {
+               rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
+               rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
+       }
+
        rtc = rtc_device_register(pdev->name, &pdev->dev,
                        &omap_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -398,6 +451,10 @@ fail2:
 fail1:
        rtc_device_unregister(rtc);
 fail0:
+       if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
+               rtc_writel(0, OMAP_RTC_KICK0_REG);
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        iounmap(rtc_base);
 fail:
        release_mem_region(mem->start, resource_size(mem));
@@ -408,6 +465,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device       *rtc = platform_get_drvdata(pdev);
        struct resource         *mem = dev_get_drvdata(&rtc->dev);
+       const struct platform_device_id *id_entry =
+                               platform_get_device_id(pdev);
 
        device_init_wakeup(&pdev->dev, 0);
 
@@ -420,6 +479,13 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
                free_irq(omap_rtc_alarm, rtc);
 
        rtc_device_unregister(rtc);
+       if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
+               rtc_writel(0, OMAP_RTC_KICK0_REG);
+
+       /* Disable the clock/module */
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+
        iounmap(rtc_base);
        release_mem_region(mem->start, resource_size(mem));
        return 0;
@@ -442,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
        else
                rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
 
+       /* Disable the clock/module */
+       pm_runtime_put_sync(&pdev->dev);
+
        return 0;
 }
 
 static int omap_rtc_resume(struct platform_device *pdev)
 {
+       /* Enable the clock/module so that we can access the registers */
+       pm_runtime_get_sync(&pdev->dev);
+
        if (device_may_wakeup(&pdev->dev))
                disable_irq_wake(omap_rtc_alarm);
        else
@@ -471,9 +543,11 @@ static struct platform_driver omap_rtc_driver = {
        .resume         = omap_rtc_resume,
        .shutdown       = omap_rtc_shutdown,
        .driver         = {
-               .name   = "omap_rtc",
+               .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(omap_rtc_of_match),
        },
+       .id_table       = omap_rtc_devtype,
 };
 
 static int __init rtc_init(void)
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
new file mode 100644 (file)
index 0000000..be05a64
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bcd.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#define DRIVER_NAME "rtc-pcf8523"
+
+#define REG_CONTROL1 0x00
+#define REG_CONTROL1_CAP_SEL (1 << 7)
+#define REG_CONTROL1_STOP    (1 << 5)
+
+#define REG_CONTROL3 0x02
+#define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */
+#define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */
+#define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */
+#define REG_CONTROL3_PM_MASK 0xe0
+
+#define REG_SECONDS  0x03
+#define REG_SECONDS_OS (1 << 7)
+
+#define REG_MINUTES  0x04
+#define REG_HOURS    0x05
+#define REG_DAYS     0x06
+#define REG_WEEKDAYS 0x07
+#define REG_MONTHS   0x08
+#define REG_YEARS    0x09
+
+struct pcf8523 {
+       struct rtc_device *rtc;
+};
+
+static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)
+{
+       struct i2c_msg msgs[2];
+       u8 value = 0;
+       int err;
+
+       msgs[0].addr = client->addr;
+       msgs[0].flags = 0;
+       msgs[0].len = sizeof(reg);
+       msgs[0].buf = &reg;
+
+       msgs[1].addr = client->addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = sizeof(value);
+       msgs[1].buf = &value;
+
+       err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (err < 0)
+               return err;
+
+       *valuep = value;
+
+       return 0;
+}
+
+static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
+{
+       u8 buffer[2] = { reg, value };
+       struct i2c_msg msg;
+       int err;
+
+       msg.addr = client->addr;
+       msg.flags = 0;
+       msg.len = sizeof(buffer);
+       msg.buf = buffer;
+
+       err = i2c_transfer(client->adapter, &msg, 1);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
+{
+       u8 value;
+       int err;
+
+       err = pcf8523_read(client, REG_CONTROL1, &value);
+       if (err < 0)
+               return err;
+
+       if (!high)
+               value &= ~REG_CONTROL1_CAP_SEL;
+       else
+               value |= REG_CONTROL1_CAP_SEL;
+
+       err = pcf8523_write(client, REG_CONTROL1, value);
+       if (err < 0)
+               return err;
+
+       return err;
+}
+
+static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
+{
+       u8 value;
+       int err;
+
+       err = pcf8523_read(client, REG_CONTROL3, &value);
+       if (err < 0)
+               return err;
+
+       value = (value & ~REG_CONTROL3_PM_MASK) | pm;
+
+       err = pcf8523_write(client, REG_CONTROL3, value);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int pcf8523_stop_rtc(struct i2c_client *client)
+{
+       u8 value;
+       int err;
+
+       err = pcf8523_read(client, REG_CONTROL1, &value);
+       if (err < 0)
+               return err;
+
+       value |= REG_CONTROL1_STOP;
+
+       err = pcf8523_write(client, REG_CONTROL1, value);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int pcf8523_start_rtc(struct i2c_client *client)
+{
+       u8 value;
+       int err;
+
+       err = pcf8523_read(client, REG_CONTROL1, &value);
+       if (err < 0)
+               return err;
+
+       value &= ~REG_CONTROL1_STOP;
+
+       err = pcf8523_write(client, REG_CONTROL1, value);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       u8 start = REG_SECONDS, regs[7];
+       struct i2c_msg msgs[2];
+       int err;
+
+       msgs[0].addr = client->addr;
+       msgs[0].flags = 0;
+       msgs[0].len = 1;
+       msgs[0].buf = &start;
+
+       msgs[1].addr = client->addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = sizeof(regs);
+       msgs[1].buf = regs;
+
+       err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (err < 0)
+               return err;
+
+       if (regs[0] & REG_SECONDS_OS) {
+               /*
+                * If the oscillator was stopped, try to clear the flag. Upon
+                * power-up the flag is always set, but if we cannot clear it
+                * the oscillator isn't running properly for some reason. The
+                * sensible thing therefore is to return an error, signalling
+                * that the clock cannot be assumed to be correct.
+                */
+
+               regs[0] &= ~REG_SECONDS_OS;
+
+               err = pcf8523_write(client, REG_SECONDS, regs[0]);
+               if (err < 0)
+                       return err;
+
+               err = pcf8523_read(client, REG_SECONDS, &regs[0]);
+               if (err < 0)
+                       return err;
+
+               if (regs[0] & REG_SECONDS_OS)
+                       return -EAGAIN;
+       }
+
+       tm->tm_sec = bcd2bin(regs[0] & 0x7f);
+       tm->tm_min = bcd2bin(regs[1] & 0x7f);
+       tm->tm_hour = bcd2bin(regs[2] & 0x3f);
+       tm->tm_mday = bcd2bin(regs[3] & 0x3f);
+       tm->tm_wday = regs[4] & 0x7;
+       tm->tm_mon = bcd2bin(regs[5] & 0x1f);
+       tm->tm_year = bcd2bin(regs[6]) + 100;
+
+       return rtc_valid_tm(tm);
+}
+
+static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct i2c_msg msg;
+       u8 regs[8];
+       int err;
+
+       err = pcf8523_stop_rtc(client);
+       if (err < 0)
+               return err;
+
+       regs[0] = REG_SECONDS;
+       regs[1] = bin2bcd(tm->tm_sec);
+       regs[2] = bin2bcd(tm->tm_min);
+       regs[3] = bin2bcd(tm->tm_hour);
+       regs[4] = bin2bcd(tm->tm_mday);
+       regs[5] = tm->tm_wday;
+       regs[6] = bin2bcd(tm->tm_mon);
+       regs[7] = bin2bcd(tm->tm_year - 100);
+
+       msg.addr = client->addr;
+       msg.flags = 0;
+       msg.len = sizeof(regs);
+       msg.buf = regs;
+
+       err = i2c_transfer(client->adapter, &msg, 1);
+       if (err < 0) {
+               /*
+                * If the time cannot be set, restart the RTC anyway. Note
+                * that errors are ignored if the RTC cannot be started so
+                * that we have a chance to propagate the original error.
+                */
+               pcf8523_start_rtc(client);
+               return err;
+       }
+
+       return pcf8523_start_rtc(client);
+}
+
+static const struct rtc_class_ops pcf8523_rtc_ops = {
+       .read_time = pcf8523_rtc_read_time,
+       .set_time = pcf8523_rtc_set_time,
+};
+
+static int pcf8523_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct pcf8523 *pcf;
+       int err;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
+
+       pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL);
+       if (!pcf)
+               return -ENOMEM;
+
+       err = pcf8523_select_capacitance(client, true);
+       if (err < 0)
+               return err;
+
+       err = pcf8523_set_pm(client, 0);
+       if (err < 0)
+               return err;
+
+       pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev,
+                                      &pcf8523_rtc_ops, THIS_MODULE);
+       if (IS_ERR(pcf->rtc))
+               return PTR_ERR(pcf->rtc);
+
+       i2c_set_clientdata(client, pcf);
+
+       return 0;
+}
+
+static int pcf8523_remove(struct i2c_client *client)
+{
+       struct pcf8523 *pcf = i2c_get_clientdata(client);
+
+       rtc_device_unregister(pcf->rtc);
+
+       return 0;
+}
+
+static const struct i2c_device_id pcf8523_id[] = {
+       { "pcf8523", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8523_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pcf8523_of_match[] = {
+       { .compatible = "nxp,pcf8523" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pcf8523_of_match);
+#endif
+
+static struct i2c_driver pcf8523_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(pcf8523_of_match),
+       },
+       .probe = pcf8523_probe,
+       .remove = pcf8523_remove,
+       .id_table = pcf8523_id,
+};
+module_i2c_driver(pcf8523_driver);
+
+MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
+MODULE_DESCRIPTION("NXP PCF8523 RTC driver");
+MODULE_LICENSE("GPL v2");
index a7a2a998fa91fd2b626b2a241dbeef7ff212341e..4bd9414aee650e2b08449323a5840497a5b9c48c 100644 (file)
@@ -47,8 +47,6 @@ struct s3c_rtc_drv_data {
 /* I have yet to find an S3C implementation with more than one
  * of these rtc blocks in */
 
-static struct resource *s3c_rtc_mem;
-
 static struct clk *rtc_clk;
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
@@ -427,21 +425,13 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
-       free_irq(s3c_rtc_alarmno, rtc);
-       free_irq(s3c_rtc_tickno, rtc);
-
        platform_set_drvdata(dev, NULL);
        rtc_device_unregister(rtc);
 
        s3c_rtc_setaie(&dev->dev, 0);
 
-       clk_put(rtc_clk);
        rtc_clk = NULL;
 
-       iounmap(s3c_rtc_base);
-       release_resource(s3c_rtc_mem);
-       kfree(s3c_rtc_mem);
-
        return 0;
 }
 
@@ -496,28 +486,18 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       s3c_rtc_mem = request_mem_region(res->start, resource_size(res),
-                                        pdev->name);
-
-       if (s3c_rtc_mem == NULL) {
-               dev_err(&pdev->dev, "failed to reserve memory region\n");
-               ret = -ENOENT;
-               goto err_nores;
-       }
-
-       s3c_rtc_base = ioremap(res->start, resource_size(res));
+       s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res);
        if (s3c_rtc_base == NULL) {
-               dev_err(&pdev->dev, "failed ioremap()\n");
-               ret = -EINVAL;
-               goto err_nomap;
+               dev_err(&pdev->dev, "failed to ioremap memory region\n");
+               return -EINVAL;
        }
 
-       rtc_clk = clk_get(&pdev->dev, "rtc");
+       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;
-               goto err_clk;
+               return ret;
        }
 
        clk_enable(rtc_clk);
@@ -576,28 +556,24 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 
        s3c_rtc_setfreq(&pdev->dev, 1);
 
-       ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
+       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_alarm_irq;
        }
 
-       ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
+       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);
-               free_irq(s3c_rtc_alarmno, rtc);
-               goto err_tick_irq;
+               goto err_alarm_irq;
        }
 
        clk_disable(rtc_clk);
 
        return 0;
 
- err_tick_irq:
-       free_irq(s3c_rtc_alarmno, rtc);
-
  err_alarm_irq:
        platform_set_drvdata(pdev, NULL);
        rtc_device_unregister(rtc);
@@ -605,15 +581,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
  err_nortc:
        s3c_rtc_enable(pdev, 0);
        clk_disable(rtc_clk);
-       clk_put(rtc_clk);
 
- err_clk:
-       iounmap(s3c_rtc_base);
-
- err_nomap:
-       release_resource(s3c_rtc_mem);
-
- err_nores:
        return ret;
 }
 
@@ -695,8 +663,6 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
-#else
-#define s3c_rtc_dt_match NULL
 #endif
 
 static struct platform_device_id s3c_rtc_driver_ids[] = {
@@ -727,7 +693,7 @@ static struct platform_driver s3c_rtc_driver = {
        .driver         = {
                .name   = "s3c-rtc",
                .owner  = THIS_MODULE,
-               .of_match_table = s3c_rtc_dt_match,
+               .of_match_table = of_match_ptr(s3c_rtc_dt_match),
        },
 };
 
index bb507d23f6cea09e3c2ab80fec144e1acbb1c4a9..141fc945295f0796a46f2f4cb79d1535bbfe7bf7 100644 (file)
@@ -363,35 +363,42 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "no resource defined\n");
                return -EBUSY;
        }
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "rtc region already claimed\n");
-               return -EBUSY;
-       }
 
-       config = kzalloc(sizeof(*config), GFP_KERNEL);
+       config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
        if (!config) {
                dev_err(&pdev->dev, "out of memory\n");
-               status = -ENOMEM;
-               goto err_release_region;
+               return -ENOMEM;
        }
 
-       config->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(config->clk)) {
-               status = PTR_ERR(config->clk);
-               goto err_kfree;
+       /* alarm irqs */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no update irq?\n");
+               return irq;
        }
 
-       status = clk_enable(config->clk);
-       if (status < 0)
-               goto err_clk_put;
+       status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name,
+                       config);
+       if (status) {
+               dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n",
+                               irq);
+               return status;
+       }
 
-       config->ioaddr = ioremap(res->start, resource_size(res));
+       config->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
        if (!config->ioaddr) {
-               dev_err(&pdev->dev, "ioremap fail\n");
-               status = -ENOMEM;
-               goto err_disable_clock;
+               dev_err(&pdev->dev, "request-ioremap fail\n");
+               return -ENOMEM;
        }
 
+       config->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(config->clk))
+               return PTR_ERR(config->clk);
+
+       status = clk_prepare_enable(config->clk);
+       if (status < 0)
+               return status;
+
        spin_lock_init(&config->lock);
        platform_set_drvdata(pdev, config);
 
@@ -401,42 +408,19 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
                                PTR_ERR(config->rtc));
                status = PTR_ERR(config->rtc);
-               goto err_iounmap;
-       }
-
-       /* alarm irqs */
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "no update irq?\n");
-               status = irq;
-               goto err_clear_platdata;
+               goto err_disable_clock;
        }
 
-       status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config);
-       if (status) {
-               dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \
-                               claimed\n", irq);
-               goto err_clear_platdata;
-       }
+       config->rtc->uie_unsupported = 1;
 
        if (!device_can_wakeup(&pdev->dev))
                device_init_wakeup(&pdev->dev, 1);
 
        return 0;
 
-err_clear_platdata:
-       platform_set_drvdata(pdev, NULL);
-       rtc_device_unregister(config->rtc);
-err_iounmap:
-       iounmap(config->ioaddr);
 err_disable_clock:
-       clk_disable(config->clk);
-err_clk_put:
-       clk_put(config->clk);
-err_kfree:
-       kfree(config);
-err_release_region:
-       release_mem_region(res->start, resource_size(res));
+       platform_set_drvdata(pdev, NULL);
+       clk_disable_unprepare(config->clk);
 
        return status;
 }
@@ -444,24 +428,11 @@ err_release_region:
 static int __devexit spear_rtc_remove(struct platform_device *pdev)
 {
        struct spear_rtc_config *config = platform_get_drvdata(pdev);
-       int irq;
-       struct resource *res;
 
-       /* leave rtc running, but disable irqs */
+       rtc_device_unregister(config->rtc);
        spear_rtc_disable_interrupt(config);
+       clk_disable_unprepare(config->clk);
        device_init_wakeup(&pdev->dev, 0);
-       irq = platform_get_irq(pdev, 0);
-       if (irq)
-               free_irq(irq, pdev);
-       clk_disable(config->clk);
-       clk_put(config->clk);
-       iounmap(config->ioaddr);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res)
-               release_mem_region(res->start, resource_size(res));
-       platform_set_drvdata(pdev, NULL);
-       rtc_device_unregister(config->rtc);
-       kfree(config);
 
        return 0;
 }
index 7e96254bd365eae1f73b5fc296f7e705b58e05ee..974b9ae252ab5f116d9fa6faa21d587029a3f18a 100644 (file)
@@ -152,24 +152,24 @@ static int __init test_init(void)
 
        if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {
                err = -ENOMEM;
-               goto exit_free_test0;
+               goto exit_put_test0;
        }
 
        if ((err = platform_device_add(test0)))
-               goto exit_free_test1;
+               goto exit_put_test1;
 
        if ((err = platform_device_add(test1)))
-               goto exit_device_unregister;
+               goto exit_del_test0;
 
        return 0;
 
-exit_device_unregister:
-       platform_device_unregister(test0);
+exit_del_test0:
+       platform_device_del(test0);
 
-exit_free_test1:
+exit_put_test1:
        platform_device_put(test1);
 
-exit_free_test0:
+exit_put_test0:
        platform_device_put(test0);
 
 exit_driver_unregister:
index 073108dcf9e7b5660f1a4f9fb7074605bf247845..22eb4ebfa1a64cf295b80b02cb09339de15c56ab 100644 (file)
@@ -247,6 +247,13 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
                return ret;
 
        dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n");
+
+       /* Enable RTC digital power domain */
+       ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL,
+               DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT);
+       if (ret < 0)
+               return ret;
+
        rtc_reg = TPS65910_RTC_CTRL_STOP_RTC;
        ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg);
        if (ret < 0)
@@ -261,7 +268,7 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
-               "rtc-tps65910", &pdev->dev);
+               dev_name(&pdev->dev), &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "IRQ is not free.\n");
                return ret;
index 07bf19364a74732baf2f34dfa3c1fdb984e8cb8a..14e2d8cfcc83de0e55ba39cc2630da0d12e30b1e 100644 (file)
@@ -210,7 +210,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
        struct vt8500_rtc *vt8500_rtc;
        int ret;
 
-       vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL);
+       vt8500_rtc = devm_kzalloc(&pdev->dev,
+                          sizeof(struct vt8500_rtc), GFP_KERNEL);
        if (!vt8500_rtc)
                return -ENOMEM;
 
@@ -220,15 +221,13 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
        vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!vt8500_rtc->res) {
                dev_err(&pdev->dev, "No I/O memory resource defined\n");
-               ret = -ENXIO;
-               goto err_free;
+               return -ENXIO;
        }
 
        vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);
        if (vt8500_rtc->irq_alarm < 0) {
                dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
-               ret = -ENXIO;
-               goto err_free;
+               return -ENXIO;
        }
 
        vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start,
@@ -236,8 +235,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
                                             "vt8500-rtc");
        if (vt8500_rtc->res == NULL) {
                dev_err(&pdev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto err_free;
+               return -EBUSY;
        }
 
        vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start,
@@ -278,8 +276,6 @@ err_unmap:
 err_release:
        release_mem_region(vt8500_rtc->res->start,
                           resource_size(vt8500_rtc->res));
-err_free:
-       kfree(vt8500_rtc);
        return ret;
 }
 
@@ -297,7 +293,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev)
        release_mem_region(vt8500_rtc->res->start,
                           resource_size(vt8500_rtc->res));
 
-       kfree(vt8500_rtc);
        platform_set_drvdata(pdev, NULL);
 
        return 0;
index 2ebe03a4b51d077d382a2971eefa75d557ff8ff6..4a909d7cfde12859d8500eef059d9e51533243f3 100644 (file)
@@ -2144,7 +2144,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
         */
        port_id = fip->port_id;
        if (fip->probe_tries)
-               port_id = prandom32(&fip->rnd_state) & 0xffff;
+               port_id = prandom_u32_state(&fip->rnd_state) & 0xffff;
        else if (!port_id)
                port_id = fip->lp->wwpn & 0xffff;
        if (!port_id || port_id == 0xffff)
@@ -2169,7 +2169,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
 static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
 {
        fip->probe_tries = 0;
-       prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
+       prandom_seed_state(&fip->rnd_state, fip->lp->wwpn);
        fcoe_ctlr_vn_restart(fip);
 }
 
index 57cc9c6eaa9fcf2f3f4528a94df7e3024595f64e..f1c6c5470b92550831cbe6551cf8cb090b2d491d 100644 (file)
@@ -251,7 +251,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
                /* best case is 32bit-aligned source address */
                if ((0x02 & (unsigned long) src) == 0) {
                        if (len >= 4) {
-                               writesl(fifo, src + index, len >> 2);
+                               iowrite32_rep(fifo, src + index, len >> 2);
                                index += len & ~0x03;
                        }
                        if (len & 0x02) {
@@ -260,7 +260,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
                        }
                } else {
                        if (len >= 2) {
-                               writesw(fifo, src + index, len >> 1);
+                               iowrite16_rep(fifo, src + index, len >> 1);
                                index += len & ~0x01;
                        }
                }
@@ -268,7 +268,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
                        musb_writeb(fifo, 0, src[index]);
        } else  {
                /* byte aligned */
-               writesb(fifo, src, len);
+               iowrite8_rep(fifo, src, len);
        }
 }
 
@@ -294,7 +294,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
                /* best case is 32bit-aligned destination address */
                if ((0x02 & (unsigned long) dst) == 0) {
                        if (len >= 4) {
-                               readsl(fifo, dst, len >> 2);
+                               ioread32_rep(fifo, dst, len >> 2);
                                index = len & ~0x03;
                        }
                        if (len & 0x02) {
@@ -303,7 +303,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
                        }
                } else {
                        if (len >= 2) {
-                               readsw(fifo, dst, len >> 1);
+                               ioread16_rep(fifo, dst, len >> 1);
                                index = len & ~0x01;
                        }
                }
@@ -311,7 +311,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
                        dst[index] = musb_readb(fifo, 0);
        } else  {
                /* byte aligned */
-               readsb(fifo, dst, len);
+               ioread8_rep(fifo, dst, len);
        }
 }
 #endif
index 565ad1617832197d1a6a134fa511b9def991ca6e..eebeed78edd60667fcf86ddf90bcda336ae84b98 100644 (file)
 
 #include <linux/io.h>
 
-#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
-       && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
-       && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
-       && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K) \
-       && !defined(CONFIG_XTENSA)
-static inline void readsl(const void __iomem *addr, void *buf, int len)
-       { insl((unsigned long)addr, buf, len); }
-static inline void readsw(const void __iomem *addr, void *buf, int len)
-       { insw((unsigned long)addr, buf, len); }
-static inline void readsb(const void __iomem *addr, void *buf, int len)
-       { insb((unsigned long)addr, buf, len); }
-
-static inline void writesl(const void __iomem *addr, const void *buf, int len)
-       { outsl((unsigned long)addr, buf, len); }
-static inline void writesw(const void __iomem *addr, const void *buf, int len)
-       { outsw((unsigned long)addr, buf, len); }
-static inline void writesb(const void __iomem *addr, const void *buf, int len)
-       { outsb((unsigned long)addr, buf, len); }
-
-#endif
-
 #ifndef CONFIG_BLACKFIN
 
 /* NOTE:  these offsets are all in bytes */
index 8bde6fc5eb75525c2c2522ad3fa766c341f26f31..3969813c217d2d2af276c8f6e49b234b59a3aa22 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/prefetch.h>
 #include <linux/usb.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/nop-usb-xceiv.h>
@@ -198,7 +199,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf)
                /* Best case is 32bit-aligned destination address */
                if ((0x02 & (unsigned long) buf) == 0) {
                        if (len >= 4) {
-                               writesl(fifo, buf, len >> 2);
+                               iowrite32_rep(fifo, buf, len >> 2);
                                buf += (len & ~0x03);
                                len &= 0x03;
                        }
@@ -245,7 +246,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
                /* Best case is 32bit-aligned destination address */
                if ((0x02 & (unsigned long) buf) == 0) {
                        if (len >= 4) {
-                               readsl(fifo, buf, len >> 2);
+                               ioread32_rep(fifo, buf, len >> 2);
                                buf += (len & ~0x03);
                                len &= 0x03;
                        }
index b7ec34c57f46d7f3c0b345935c3e4857e3a0b104..c072ed9aea3624148b57bff3ad742b4f278a060e 100644 (file)
@@ -117,8 +117,8 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        data->current_brightness = value;
        return 0;
 out:
-       dev_dbg(chip->dev, "set brightness %d failure with return "
-               "value:%d\n", value, ret);
+       dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n",
+               value, ret);
        return ret;
 }
 
@@ -208,22 +208,19 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle");
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for duty cycle\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_duty_cycle = res->start;
        res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on");
        if (!res) {
                dev_err(&pdev->dev, "No REG resorce for always on\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_always_on = res->start;
        res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current");
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for current\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_current = res->start;
 
@@ -231,8 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        sprintf(name, "backlight-%d", pdev->id);
        data->port = pdev->id;
        data->chip = chip;
-       data->i2c = (chip->id == CHIP_PM8606) ? chip->client    \
-                       : chip->companion;
+       data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
        data->current_brightness = MAX_BRIGHTNESS;
        if (pm860x_backlight_dt_init(pdev, data, name)) {
                if (pdata) {
@@ -263,8 +259,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        return 0;
 out_brt:
        backlight_device_unregister(bl);
-out:
-       devm_kfree(&pdev->dev, data);
        return ret;
 }
 
index df1cbb7ef6ca0370551904b190ba968315ee92c7..de5e5e74e2a70531a03d8204c282df6cc0d25332 100644 (file)
@@ -106,10 +106,9 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
        pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
                        pwmbl->pdata->pwm_compare_max);
 
-       dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
-                       "(%lu Hz)\n", pwmbl->pwmc.mck /
-                       pwmbl->pdata->pwm_compare_max /
-                       (1 << prescale));
+       dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n",
+               pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max /
+               (1 << prescale));
 
        return pwm_channel_enable(&pwmbl->pwmc);
 }
index 297db2fa91f58e556873a114b812c214e650dca8..345f6660d4b39bd7f312e8958760e3c54d51ae24 100644 (file)
@@ -370,6 +370,35 @@ void backlight_device_unregister(struct backlight_device *bd)
 }
 EXPORT_SYMBOL(backlight_device_unregister);
 
+#ifdef CONFIG_OF
+static int of_parent_match(struct device *dev, void *data)
+{
+       return dev->parent && dev->parent->of_node == data;
+}
+
+/**
+ * of_find_backlight_by_node() - find backlight device by device-tree node
+ * @node: device-tree node of the backlight device
+ *
+ * Returns a pointer to the backlight device corresponding to the given DT
+ * node or NULL if no such backlight device exists or if the device hasn't
+ * been probed yet.
+ *
+ * This function obtains a reference on the backlight device and it is the
+ * caller's responsibility to drop the reference by calling put_device() on
+ * the backlight device's .dev field.
+ */
+struct backlight_device *of_find_backlight_by_node(struct device_node *node)
+{
+       struct device *dev;
+
+       dev = class_find_device(backlight_class, NULL, node, of_parent_match);
+
+       return dev ? to_backlight_device(dev) : NULL;
+}
+EXPORT_SYMBOL(of_find_backlight_by_node);
+#endif
+
 static void __exit backlight_class_exit(void)
 {
        class_destroy(backlight_class);
index eaaebf21993e2cfe8207669df94eff1e72bf829f..e323fcbe884e6c2e21069d96592cf38f14db7972 100644 (file)
@@ -6,8 +6,8 @@
  *  Based on Sharp's 2.4 Backlight Driver
  *
  *  Copyright (c) 2008 Marvell International Ltd.
- *     Converted to SPI device based LCD/Backlight device driver
- *     by Eric Miao <eric.miao@marvell.com>
+ *     Converted to SPI device based LCD/Backlight device driver
+ *     by Eric Miao <eric.miao@marvell.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -192,7 +192,7 @@ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
 {
        int adj;
 
-       switch(mode) {
+       switch (mode) {
        case CORGI_LCD_MODE_VGA:
                /* Setting for VGA */
                adj = sharpsl_param.phadadj;
@@ -409,10 +409,10 @@ static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity)
        cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted;
 
        if (gpio_is_valid(lcd->gpio_backlight_cont))
-               gpio_set_value(lcd->gpio_backlight_cont, cont);
+               gpio_set_value_cansleep(lcd->gpio_backlight_cont, cont);
 
        if (gpio_is_valid(lcd->gpio_backlight_on))
-               gpio_set_value(lcd->gpio_backlight_on, intensity);
+               gpio_set_value_cansleep(lcd->gpio_backlight_on, intensity);
 
        if (lcd->kick_battery)
                lcd->kick_battery();
@@ -495,8 +495,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
                err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on,
                                        "BL_ON");
                if (err) {
-                       dev_err(&spi->dev, "failed to request GPIO%d for "
-                               "backlight_on\n", pdata->gpio_backlight_on);
+                       dev_err(&spi->dev,
+                               "failed to request GPIO%d for backlight_on\n",
+                               pdata->gpio_backlight_on);
                        return err;
                }
 
@@ -508,8 +509,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
                err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont,
                                        "BL_CONT");
                if (err) {
-                       dev_err(&spi->dev, "failed to request GPIO%d for "
-                               "backlight_cont\n", pdata->gpio_backlight_cont);
+                       dev_err(&spi->dev,
+                               "failed to request GPIO%d for backlight_cont\n",
+                               pdata->gpio_backlight_cont);
                        return err;
                }
 
index 573c7ece0fde88f7b1990bd3989f17ccd8a86ed9..8179cef0730f1175a09f986cda970d12bd338b82 100644 (file)
@@ -2,10 +2,10 @@
  * Backlight driver for Dialog Semiconductor DA9030/DA9034
  *
  * Copyright (C) 2008 Compulab, Ltd.
- *     Mike Rapoport <mike@compulab.co.il>
+ *     Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- *     Eric Miao <eric.miao@marvell.com>
+ *     Eric Miao <eric.miao@marvell.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -164,15 +164,14 @@ static int da903x_backlight_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int da903x_backlight_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct backlight_device *bl = dev_get_drvdata(dev);
+
        return da903x_backlight_set(bl, 0);
 }
 
 static int da903x_backlight_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct backlight_device *bl = dev_get_drvdata(dev);
 
        backlight_update_status(bl);
        return 0;
@@ -199,7 +198,7 @@ static struct platform_driver da903x_backlight_driver = {
 module_platform_driver(da903x_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-             "Mike Rapoport <mike@compulab.co.il>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:da903x-backlight");
index ac196181fe45a88ae45965ac7d18cb91570b1eb3..842da5a3ac4f2fde626b7c23ef7975ab01870eec 100644 (file)
@@ -34,7 +34,7 @@ enum {
        DA9052_TYPE_WLED3,
 };
 
-static unsigned char wled_bank[] = {
+static const unsigned char wled_bank[] = {
        DA9052_LED1_CONF_REG,
        DA9052_LED2_CONF_REG,
        DA9052_LED3_CONF_REG,
index 8c660fcd250da09f446e07f9e0dfce3b5677a128..0ae155be9c89ad43685e2303bce941c6954273e1 100644 (file)
@@ -97,8 +97,8 @@ static int genericbl_probe(struct platform_device *pdev)
        props.max_brightness = machinfo->max_intensity;
        bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
                                       &props);
-       if (IS_ERR (bd))
-               return PTR_ERR (bd);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
 
        platform_set_drvdata(pdev, bd);
 
index c99966342448d265be5aea25f21a25b895a7c3bb..5cefd73526f861a70d46044a379e0f42982d833b 100644 (file)
@@ -26,7 +26,7 @@
 #define HP680_DEFAULT_INTENSITY 10
 
 static int hp680bl_suspended;
-static int current_intensity = 0;
+static int current_intensity;
 static DEFINE_SPINLOCK(bl_lock);
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
@@ -168,7 +168,7 @@ static int __init hp680bl_init(void)
 static void __exit hp680bl_exit(void)
 {
        platform_device_unregister(hp680bl_device);
-       platform_driver_unregister(&hp680bl_driver);
+       platform_driver_unregister(&hp680bl_driver);
 }
 
 module_init(hp680bl_init);
index 66cc313185ad586792d199e96a00ec82c3dd849b..1235bf9defc42f70b0ef615acb12a36c405ac89e 100644 (file)
@@ -45,7 +45,7 @@ static inline int ili9320_write_spi(struct ili9320 *ili,
        /* second message is the data to transfer */
 
        data[0] = spi->id | ILI9320_SPI_DATA  | ILI9320_SPI_WRITE;
-       data[1] = value >> 8;
+       data[1] = value >> 8;
        data[2] = value;
 
        return spi_sync(spi->dev, &spi->message);
@@ -56,11 +56,10 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
        dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
        return ili->write(ili, reg, value);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_write);
 
 int ili9320_write_regs(struct ili9320 *ili,
-                      struct ili9320_reg *values,
+                      const struct ili9320_reg *values,
                       int nr_values)
 {
        int index;
@@ -74,7 +73,6 @@ int ili9320_write_regs(struct ili9320 *ili,
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_write_regs);
 
 static void ili9320_reset(struct ili9320 *lcd)
@@ -260,7 +258,6 @@ int ili9320_probe_spi(struct spi_device *spi,
 
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_probe_spi);
 
 int ili9320_remove(struct ili9320 *ili)
@@ -271,7 +268,6 @@ int ili9320_remove(struct ili9320 *ili)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_remove);
 
 #ifdef CONFIG_PM
@@ -296,20 +292,17 @@ int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_suspend);
 
 int ili9320_resume(struct ili9320 *lcd)
 {
        dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
 
-       if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+       if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP)
                ili9320_write(lcd, ILI9320_POWER1, 0x00);
-       }
 
        return ili9320_power(lcd, FB_BLANK_UNBLANK);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_resume);
 #endif
 
@@ -318,7 +311,6 @@ void ili9320_shutdown(struct ili9320 *lcd)
 {
        ili9320_power(lcd, FB_BLANK_POWERDOWN);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_shutdown);
 
 MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
index e388eca7cac5ca89069684d17d6bcaba75ab3a68..e0db738f7bb9fddd7dd4dc11787ac4f7a8307170 100644 (file)
@@ -63,7 +63,7 @@ extern int ili9320_write(struct ili9320 *ili,
                         unsigned int reg, unsigned int value);
 
 extern int ili9320_write_regs(struct ili9320 *ili,
-                             struct ili9320_reg *values,
+                             const struct ili9320_reg *values,
                              int nr_values);
 
 /* Device probe */
index 16f593b64427a606093f1c14dce6498ab791a5cb..fef6ce4fad7168b3c16fc17ae2efb83e2ba443de 100644 (file)
@@ -48,7 +48,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
 
        jornada_ssp_end();
 
-       return (BL_MAX_BRIGHT - ret);
+       return BL_MAX_BRIGHT - ret;
 }
 
 static int jornada_bl_update_status(struct backlight_device *bd)
@@ -77,18 +77,23 @@ static int jornada_bl_update_status(struct backlight_device *bd)
                        goto out;
                }
 
-               /* at this point we expect that the mcu has accepted
-                  our command and is waiting for our new value
-                  please note that maximum brightness is 255,
-                  but due to physical layout it is equal to 0, so we simply
-                  invert the value (MAX VALUE - NEW VALUE). */
-               if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
+               /*
+                * at this point we expect that the mcu has accepted
+                * our command and is waiting for our new value
+                * please note that maximum brightness is 255,
+                * but due to physical layout it is equal to 0, so we simply
+                * invert the value (MAX VALUE - NEW VALUE).
+                */
+               if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness)
+                       != TXDUMMY) {
                        pr_err("set brightness failed\n");
                        ret = -ETIMEDOUT;
                }
 
-               /* If infact we get an TXDUMMY as output we are happy and dont
-                  make any further comments about it */
+               /*
+                * If infact we get an TXDUMMY as output we are happy and dont
+                * make any further comments about it
+                */
 out:
        jornada_ssp_end();
 
@@ -121,9 +126,11 @@ static int jornada_bl_probe(struct platform_device *pdev)
 
        bd->props.power = FB_BLANK_UNBLANK;
        bd->props.brightness = BL_DEF_BRIGHT;
-       /* note. make sure max brightness is set otherwise
-          you will get seemingly non-related errors when
-          trying to change brightness */
+       /*
+        * note. make sure max brightness is set otherwise
+        * you will get seemingly non-related errors when
+        * trying to change brightness
+        */
        jornada_bl_update_status(bd);
 
        platform_set_drvdata(pdev, bd);
index f5aa0a5961d63e8f8e9cc3c355815970ce7c6584..9a35196d12d70062d22e82cb7033341cff61501a 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- *     Inspired by Marek Vasut work in l4f00242t03.c
+ *     Inspired by Marek Vasut work in l4f00242t03.c
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -33,7 +33,6 @@ struct l4f00242t03_priv {
        struct regulator *core_reg;
 };
 
-
 static void l4f00242t03_reset(unsigned int gpio)
 {
        pr_debug("l4f00242t03_reset.\n");
index a5d0d024bb92939ec9cdefbd6788febabebfb337..34fb6bd798c84bb82e79b7f651a380b0547955cd 100644 (file)
@@ -108,7 +108,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
 static ssize_t lcd_store_power(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       int rc = -ENXIO;
+       int rc;
        struct lcd_device *ld = to_lcd_device(dev);
        unsigned long power;
 
@@ -116,6 +116,8 @@ static ssize_t lcd_store_power(struct device *dev,
        if (rc)
                return rc;
 
+       rc = -ENXIO;
+
        mutex_lock(&ld->ops_lock);
        if (ld->ops && ld->ops->set_power) {
                pr_debug("set power to %lu\n", power);
@@ -144,7 +146,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
 static ssize_t lcd_store_contrast(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       int rc = -ENXIO;
+       int rc;
        struct lcd_device *ld = to_lcd_device(dev);
        unsigned long contrast;
 
@@ -152,6 +154,8 @@ static ssize_t lcd_store_contrast(struct device *dev,
        if (rc)
                return rc;
 
+       rc = -ENXIO;
+
        mutex_lock(&ld->ops_lock);
        if (ld->ops && ld->ops->set_contrast) {
                pr_debug("set contrast to %lu\n", contrast);
index 0207bc0a440763212ee078a591a1f3831533b137..a6d637b5c68f2dc7d2c69e4868726e6d52768a2f 100644 (file)
@@ -37,7 +37,7 @@ enum lm3630_leds {
        BLED_2
 };
 
-static const char *bled_name[] = {
+static const char * const bled_name[] = {
        [BLED_ALL] = "lm3630_bled",     /*Bank1 controls all string */
        [BLED_1] = "lm3630_bled1",      /*Bank1 controls bled1 */
        [BLED_2] = "lm3630_bled2",      /*Bank1 or 2 controls bled2 */
index b0e1e8ba4d9f86f7daf0b63d658f0d9026c5496e..7ab2d2a04e41a8aca4dc6e9e14a104fbebbe3cd3 100644 (file)
@@ -214,7 +214,7 @@ out_input:
 
 }
 
-static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store);
+static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store);
 
 /* torch */
 static void lm3639_torch_brightness_set(struct led_classdev *cdev,
index b29c7071c9db3b3432dc953d2c02fa113ddbdb1f..55819b3847014c56dab005851de06dc070f71042 100644 (file)
@@ -31,7 +31,7 @@ struct lms283gf05_seq {
 };
 
 /* Magic sequences supplied by manufacturer, for details refer to datasheet */
-static struct lms283gf05_seq disp_initseq[] = {
+static const struct lms283gf05_seq disp_initseq[] = {
        /* REG, VALUE, DELAY */
        { 0x07, 0x0000, 0 },
        { 0x13, 0x0000, 10 },
@@ -78,7 +78,7 @@ static struct lms283gf05_seq disp_initseq[] = {
        { 0x22, 0x0000, 0 }
 };
 
-static struct lms283gf05_seq disp_pdwnseq[] = {
+static const struct lms283gf05_seq disp_pdwnseq[] = {
        { 0x07, 0x0016, 30 },
 
        { 0x07, 0x0004, 0 },
@@ -104,7 +104,7 @@ static void lms283gf05_reset(unsigned long gpio, bool inverted)
 }
 
 static void lms283gf05_toggle(struct spi_device *spi,
-                       struct lms283gf05_seq *seq, int sz)
+                               const struct lms283gf05_seq *seq, int sz)
 {
        char buf[3];
        int i;
@@ -158,13 +158,10 @@ static int lms283gf05_probe(struct spi_device *spi)
        int ret = 0;
 
        if (pdata != NULL) {
-               ret = devm_gpio_request(&spi->dev, pdata->reset_gpio,
-                                       "LMS285GF05 RESET");
-               if (ret)
-                       return ret;
-
-               ret = gpio_direction_output(pdata->reset_gpio,
-                                               !pdata->reset_inverted);
+               ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio,
+                               GPIOF_DIR_OUT | (!pdata->reset_inverted ?
+                               GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+                               "LMS285GF05 RESET");
                if (ret)
                        return ret;
        }
index fd985e0681e959a8c8716fe9cca582bf7b3d7804..6e4db0c874c862c237ee29a527c9c9d00ba4ad46 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/backlight.h>
 #include <linux/err.h>
 #include <linux/platform_data/lp855x.h>
+#include <linux/pwm.h>
 
 /* Registers */
 #define BRIGHTNESS_CTRL                0x00
@@ -34,22 +35,19 @@ struct lp855x {
        struct i2c_client *client;
        struct backlight_device *bl;
        struct device *dev;
-       struct mutex xfer_lock;
        struct lp855x_platform_data *pdata;
+       struct pwm_device *pwm;
 };
 
 static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
 {
        int ret;
 
-       mutex_lock(&lp->xfer_lock);
        ret = i2c_smbus_read_byte_data(lp->client, reg);
        if (ret < 0) {
-               mutex_unlock(&lp->xfer_lock);
                dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
                return ret;
        }
-       mutex_unlock(&lp->xfer_lock);
 
        *data = (u8)ret;
        return 0;
@@ -57,13 +55,7 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
 
 static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data)
 {
-       int ret;
-
-       mutex_lock(&lp->xfer_lock);
-       ret = i2c_smbus_write_byte_data(lp->client, reg, data);
-       mutex_unlock(&lp->xfer_lock);
-
-       return ret;
+       return i2c_smbus_write_byte_data(lp->client, reg, data);
 }
 
 static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
@@ -121,6 +113,28 @@ static int lp855x_init_registers(struct lp855x *lp)
        return ret;
 }
 
+static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
+{
+       unsigned int period = lp->pdata->period_ns;
+       unsigned int duty = br * period / max_br;
+       struct pwm_device *pwm;
+
+       /* request pwm device with the consumer name */
+       if (!lp->pwm) {
+               pwm = devm_pwm_get(lp->dev, lp->chipname);
+               if (IS_ERR(pwm))
+                       return;
+
+               lp->pwm = pwm;
+       }
+
+       pwm_config(lp->pwm, duty, period);
+       if (duty)
+               pwm_enable(lp->pwm);
+       else
+               pwm_disable(lp->pwm);
+}
+
 static int lp855x_bl_update_status(struct backlight_device *bl)
 {
        struct lp855x *lp = bl_get_data(bl);
@@ -130,12 +144,10 @@ static int lp855x_bl_update_status(struct backlight_device *bl)
                bl->props.brightness = 0;
 
        if (mode == PWM_BASED) {
-               struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
                int br = bl->props.brightness;
                int max_br = bl->props.max_brightness;
 
-               if (pd->pwm_set_intensity)
-                       pd->pwm_set_intensity(br, max_br);
+               lp855x_pwm_ctrl(lp, br, max_br);
 
        } else if (mode == REGISTER_BASED) {
                u8 val = bl->props.brightness;
@@ -150,14 +162,7 @@ static int lp855x_bl_get_brightness(struct backlight_device *bl)
        struct lp855x *lp = bl_get_data(bl);
        enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
 
-       if (mode == PWM_BASED) {
-               struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
-               int max_br = bl->props.max_brightness;
-
-               if (pd->pwm_get_intensity)
-                       bl->props.brightness = pd->pwm_get_intensity(max_br);
-
-       } else if (mode == REGISTER_BASED) {
+       if (mode == REGISTER_BASED) {
                u8 val = 0;
 
                lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val);
@@ -266,8 +271,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        lp->chip_id = id->driver_data;
        i2c_set_clientdata(cl, lp);
 
-       mutex_init(&lp->xfer_lock);
-
        ret = lp855x_init_registers(lp);
        if (ret) {
                dev_err(lp->dev, "i2c communication err: %d", ret);
index c6bec7aab87b74c408f25adf5addbabea94c9a6a..2c9bce050aa954a03bd04ee09b5be4d45fe9a3a4 100644 (file)
@@ -120,15 +120,13 @@ static int max8925_backlight_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for mode control!\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_mode_cntl = res->start;
        res = platform_get_resource(pdev, IORESOURCE_REG, 1);
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for control!\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_cntl = res->start;
 
@@ -142,8 +140,7 @@ static int max8925_backlight_probe(struct platform_device *pdev)
                                        &max8925_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
-               ret = PTR_ERR(bl);
-               goto out;
+               return PTR_ERR(bl);
        }
        bl->props.brightness = MAX_BRIGHTNESS;
 
@@ -166,8 +163,6 @@ static int max8925_backlight_probe(struct platform_device *pdev)
        return 0;
 out_brt:
        backlight_device_unregister(bl);
-out:
-       devm_kfree(&pdev->dev, data);
        return ret;
 }
 
index 9a046a4c98f5db8865699f2304c2b50fa83e57e7..af31c269baa69802b6d9584a05ec576000011a09 100644 (file)
@@ -42,12 +42,12 @@ struct omap_backlight {
        struct omap_backlight_config *pdata;
 };
 
-static void inline omapbl_send_intensity(int intensity)
+static inline void omapbl_send_intensity(int intensity)
 {
        omap_writeb(intensity, OMAP_PWL_ENABLE);
 }
 
-static void inline omapbl_send_enable(int enable)
+static inline void omapbl_send_enable(int enable)
 {
        omap_writeb(enable, OMAP_PWL_CLK_ENABLE);
 }
index 4ec30748b4473486e1f4086ddee9753f0a698ed8..633b0a22fd64446db61d63755069963e75f1aff0 100644 (file)
@@ -71,8 +71,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
                 * set PWM duty cycle to max. TPS61161 seems to use this
                 * to calibrate it's PWM sensitivity when it starts.
                 */
-               twl_i2c_write_u8(TWL4030_MODULE_PWM0, MAX_VALUE,
-                                       TWL_PWM0_OFF);
+               twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF);
 
                /* first enable clock, then PWM0 out */
                twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1);
@@ -90,8 +89,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
                usleep_range(2000, 10000);
        }
 
-       twl_i2c_write_u8(TWL4030_MODULE_PWM0, MIN_VALUE + brightness,
-                               TWL_PWM0_OFF);
+       twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF);
 
 done:
        if (brightness != 0)
@@ -132,7 +130,7 @@ static int pandora_backlight_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, bl);
 
        /* 64 cycle period, ON position 0 */
-       twl_i2c_write_u8(TWL4030_MODULE_PWM0, 0x80, TWL_PWM0_ON);
+       twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON);
 
        bl->props.state |= PANDORABL_WAS_OFF;
        bl->props.brightness = MAX_USER_VALUE;
index 0087396007e464ca8ba8b04c2080d58ca78e6939..e87c7a3394f3adc2cf1782b11366e5539c3f1580 100644 (file)
@@ -52,7 +52,7 @@ int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
        pcf_bl->brightness_limit = limit & 0x3f;
        backlight_update_status(pcf_bl->bl);
 
-    return 0;
+       return 0;
 }
 
 static int pcf50633_bl_update_status(struct backlight_device *bl)
@@ -136,8 +136,10 @@ static int pcf50633_bl_probe(struct platform_device *pdev)
 
        pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
 
-       /* Should be different from bl_props.brightness, so we do not exit
-        * update_status early the first time it's called */
+       /*
+        * Should be different from bl_props.brightness, so we do not exit
+        * update_status early the first time it's called
+        */
        pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
 
        backlight_update_status(pcf_bl->bl);
index 894bfc5ce4221224b32c21b27fe8159680a9a8a5..17a6b83f97afdab22abeb065a9c5876d92d3f5b9 100644 (file)
@@ -27,7 +27,7 @@ struct platform_lcd {
        struct plat_lcd_data    *pdata;
 
        unsigned int             power;
-       unsigned int             suspended : 1;
+       unsigned int             suspended:1;
 };
 
 static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
index 484e10dd1a8e71a6a2a8a75b812b27649c5f3436..3e1c1135f6dfd5ceff1e4df6aac7ad2d8a6a235f 100644 (file)
@@ -757,7 +757,7 @@ static int s6e63m0_probe(struct spi_device *spi)
        lcd->spi = spi;
        lcd->dev = &spi->dev;
 
-       lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
+       lcd->lcd_pd = spi->dev.platform_data;
        if (!lcd->lcd_pd) {
                dev_err(&spi->dev, "platform data is NULL.\n");
                return -EFAULT;
index 146ffb9404d1611bf1e534cdc3370e17c75659c1..ad2325f3d652d39f1b636918bd1b77dabd99a05e 100644 (file)
@@ -2,7 +2,7 @@
  * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
  *
  * Copyright (C) 2008 Marvell International Ltd.
- *     Eric Miao <eric.miao@marvell.com>
+ *     Eric Miao <eric.miao@marvell.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -47,7 +47,7 @@ struct tdo24m {
                        ((x1) << 9) | 0x100 | (x2))
 #define CMD_NULL       (-1)
 
-static uint32_t lcd_panel_reset[] = {
+static const uint32_t lcd_panel_reset[] = {
        CMD0(0x1), /* reset */
        CMD0(0x0), /* nop */
        CMD0(0x0), /* nop */
@@ -55,7 +55,7 @@ static uint32_t lcd_panel_reset[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_panel_on[] = {
+static const uint32_t lcd_panel_on[] = {
        CMD0(0x29),             /* Display ON */
        CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
        CMD0(0x11),             /* Sleep out */
@@ -63,7 +63,7 @@ static uint32_t lcd_panel_on[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_panel_off[] = {
+static const uint32_t lcd_panel_off[] = {
        CMD0(0x28),             /* Display OFF */
        CMD2(0xB8, 0x80, 0x02), /* Output Control */
        CMD0(0x10),             /* Sleep in */
@@ -71,7 +71,7 @@ static uint32_t lcd_panel_off[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_vga_pass_through_tdo24m[] = {
+static const uint32_t lcd_vga_pass_through_tdo24m[] = {
        CMD1(0xB0, 0x16),
        CMD1(0xBC, 0x80),
        CMD1(0xE1, 0x00),
@@ -80,7 +80,7 @@ static uint32_t lcd_vga_pass_through_tdo24m[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_qvga_pass_through_tdo24m[] = {
+static const uint32_t lcd_qvga_pass_through_tdo24m[] = {
        CMD1(0xB0, 0x16),
        CMD1(0xBC, 0x81),
        CMD1(0xE1, 0x00),
@@ -89,8 +89,8 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_vga_transfer_tdo24m[] = {
-       CMD1(0xcf, 0x02),       /* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo24m[] = {
+       CMD1(0xcf, 0x02),       /* Blanking period control (1) */
        CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
        CMD1(0xd1, 0x01),       /* CKV timing control on/off */
        CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
@@ -102,7 +102,7 @@ static uint32_t lcd_vga_transfer_tdo24m[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_qvga_transfer[] = {
+static const uint32_t lcd_qvga_transfer[] = {
        CMD1(0xd6, 0x02),       /* Blanking period control (1) */
        CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
        CMD1(0xd8, 0x01),       /* CKV timing control on/off */
@@ -115,7 +115,7 @@ static uint32_t lcd_qvga_transfer[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_vga_pass_through_tdo35s[] = {
+static const uint32_t lcd_vga_pass_through_tdo35s[] = {
        CMD1(0xB0, 0x16),
        CMD1(0xBC, 0x80),
        CMD1(0xE1, 0x00),
@@ -123,7 +123,7 @@ static uint32_t lcd_vga_pass_through_tdo35s[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_qvga_pass_through_tdo35s[] = {
+static const uint32_t lcd_qvga_pass_through_tdo35s[] = {
        CMD1(0xB0, 0x16),
        CMD1(0xBC, 0x81),
        CMD1(0xE1, 0x00),
@@ -131,8 +131,8 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_vga_transfer_tdo35s[] = {
-       CMD1(0xcf, 0x02),       /* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo35s[] = {
+       CMD1(0xcf, 0x02),       /* Blanking period control (1) */
        CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
        CMD1(0xd1, 0x01),       /* CKV timing control on/off */
        CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */
@@ -144,7 +144,7 @@ static uint32_t lcd_vga_transfer_tdo35s[] = {
        CMD_NULL,
 };
 
-static uint32_t lcd_panel_config[] = {
+static const uint32_t lcd_panel_config[] = {
        CMD2(0xb8, 0xff, 0xf9), /* Output control */
        CMD0(0x11),             /* sleep out */
        CMD1(0xba, 0x01),       /* Display mode (1) */
@@ -175,10 +175,11 @@ static uint32_t lcd_panel_config[] = {
        CMD_NULL,
 };
 
-static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
+static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array)
 {
        struct spi_transfer *x = &lcd->xfer;
-       uint32_t data, *p = array;
+       const uint32_t *p = array;
+       uint32_t data;
        int nparams, err = 0;
 
        for (; *p != CMD_NULL; p++) {
index a0521abdcd8aa4b736abd0941cf74f8e9c02e38b..588682cc1614569c3283ee1c164e8f3f9ebd8795 100644 (file)
@@ -92,14 +92,12 @@ static int tosa_bl_probe(struct i2c_client *client,
 
        data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
 
-       ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight");
+       ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA,
+                               GPIOF_OUT_INIT_LOW, "backlight");
        if (ret) {
                dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
                return ret;
        }
-       ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
-       if (ret)
-               return ret;
 
        i2c_set_clientdata(client, data);
        data->i2c = client;
@@ -163,7 +161,6 @@ static const struct i2c_device_id tosa_bl_id[] = {
        { },
 };
 
-
 static struct i2c_driver tosa_bl_driver = {
        .driver = {
                .name           = "tosa-bl",
index 86fff88c2e4ad7a0ef27af52c38ae96c69db48de..96bae941585a4952585b6e8b80b62402453649d4 100644 (file)
@@ -63,7 +63,7 @@ static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
 int tosa_bl_enable(struct spi_device *spi, int enable)
 {
        /* bl_enable GP04=1 otherwise GP04=0*/
-       return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
+       return tosa_tg_send(spi, TG_GPODR2, enable ? 0x01 : 0x00);
 }
 EXPORT_SYMBOL(tosa_bl_enable);
 
@@ -91,15 +91,17 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
        tosa_tg_send(spi, TG_PNLCTL, value);
 
        /* TG LCD pannel power up */
-       tosa_tg_send(spi, TG_PINICTL,0x4);
+       tosa_tg_send(spi, TG_PINICTL, 0x4);
        mdelay(50);
 
        /* TG LCD GVSS */
-       tosa_tg_send(spi, TG_PINICTL,0x0);
+       tosa_tg_send(spi, TG_PINICTL, 0x0);
 
        if (!data->i2c) {
-               /* after the pannel is powered up the first time, we can access the i2c bus */
-               /* so probe for the DAC */
+               /*
+                * after the pannel is powered up the first time,
+                * we can access the i2c bus so probe for the DAC
+                */
                struct i2c_adapter *adap = i2c_get_adapter(0);
                struct i2c_board_info info = {
                        .type   = "tosa-bl",
@@ -115,11 +117,11 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
        struct spi_device *spi = data->spi;
 
        /* TG LCD VHSA off */
-       tosa_tg_send(spi, TG_PINICTL,0x4);
+       tosa_tg_send(spi, TG_PINICTL, 0x4);
        mdelay(50);
 
        /* TG LCD signal off */
-       tosa_tg_send(spi, TG_PINICTL,0x6);
+       tosa_tg_send(spi, TG_PINICTL, 0x6);
        mdelay(50);
 
        /* TG Off */
@@ -193,17 +195,13 @@ static int tosa_lcd_probe(struct spi_device *spi)
        data->spi = spi;
        dev_set_drvdata(&spi->dev, data);
 
-       ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr");
+       ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON,
+                               GPIOF_OUT_INIT_LOW, "tg #pwr");
        if (ret < 0)
                goto err_gpio_tg;
 
        mdelay(60);
 
-       ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
-       if (ret < 0)
-               goto err_gpio_tg;
-
-       mdelay(60);
        tosa_lcd_tg_init(data);
 
        tosa_lcd_tg_on(data);
index 712b0acfd339373ce69eadd1036335ad043aae9b..45e81b4cf8b402e565b0ca54660b4c3f03755368 100644 (file)
@@ -26,7 +26,7 @@
 
 /* Device initialisation sequences */
 
-static struct ili9320_reg vgg_init1[] = {
+static const struct ili9320_reg vgg_init1[] = {
        {
                .address = ILI9320_POWER1,
                .value   = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
@@ -43,7 +43,7 @@ static struct ili9320_reg vgg_init1[] = {
        },
 };
 
-static struct ili9320_reg vgg_init2[] = {
+static const struct ili9320_reg vgg_init2[] = {
        {
                .address = ILI9320_POWER1,
                .value   = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
@@ -54,7 +54,7 @@ static struct ili9320_reg vgg_init2[] = {
        }
 };
 
-static struct ili9320_reg vgg_gamma[] = {
+static const struct ili9320_reg vgg_gamma[] = {
        {
                .address = ILI9320_GAMMA1,
                .value   = 0x0000,
@@ -89,7 +89,7 @@ static struct ili9320_reg vgg_gamma[] = {
 
 };
 
-static struct ili9320_reg vgg_init0[] = {
+static const struct ili9320_reg vgg_init0[] = {
        [0]     = {
                /* set direction and scan mode gate */
                .address = ILI9320_DRIVER,
@@ -217,7 +217,7 @@ static int vgg2432a4_resume(struct spi_device *spi)
 }
 #else
 #define vgg2432a4_suspend      NULL
-#define vgg2432a4_resume       NULL
+#define vgg2432a4_resume       NULL
 #endif
 
 static struct ili9320_client vgg2432a4_client = {
index b1342ffb3cf6e595125252ac82d5bd54ebbe9544..922ad460bff9857e39b6719001508e02e9b2b434 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/poll.h>
 
 
-static loff_t bad_file_llseek(struct file *file, loff_t offset, int origin)
+static loff_t bad_file_llseek(struct file *file, loff_t offset, int whence)
 {
        return -EIO;
 }
index 6d7d1647a68c8cf3f8b2c906eb77e23040a49bf5..0c42cdbabecff0c4c8d9d0e597273ff4fce79507 100644 (file)
@@ -1601,8 +1601,10 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        info->thread = NULL;
 
        psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
-       if (psinfo == NULL)
+       if (psinfo == NULL) {
+               info->psinfo.data = NULL; /* So we don't free this wrongly */
                return 0;
+       }
 
        fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 
index 4e6cce57d113539f482b17db2931204f679d451b..037a3e2b045b07b27fc1f1fde0a0b3f2e1a541df 100644 (file)
@@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm)
                        return -ENOEXEC;
        }
 
-       bprm->recursion_depth++; /* Well, the bang-shell is implicit... */
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index b0b70fbea06cb03e1adfe854a987f01bbf9956a9..9be335fb8a7cd3f9f480d0c5a46de7cfbcdd1c1f 100644 (file)
@@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm)
        if (!enabled)
                goto _ret;
 
-       retval = -ENOEXEC;
-       if (bprm->recursion_depth > BINPRM_MAX_RECURSION)
-               goto _ret;
-
        /* to keep locking time low, we copy the interpreter string */
        read_lock(&entries_lock);
        fmt = check_file(bprm);
@@ -197,8 +193,6 @@ static int load_misc_binary(struct linux_binprm *bprm)
        if (retval < 0)
                goto _error;
 
-       bprm->recursion_depth++;
-
        retval = search_binary_handler(bprm);
        if (retval < 0)
                goto _error;
index 8c954997e7f73a22b39718a9564c0c9ed3465a58..1610a91637e57d88c54b1a88d6a3ba1e4a230ac4 100644 (file)
@@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm)
        char interp[BINPRM_BUF_SIZE];
        int retval;
 
-       if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
-           (bprm->recursion_depth > BINPRM_MAX_RECURSION))
+       if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
                return -ENOEXEC;
        /*
         * This section does the #! interpretation.
         * Sorta complicated, but hopefully it will work.  -TYT
         */
 
-       bprm->recursion_depth++;
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index ab3a456f66506a5a134f5280739e82c572b15f55..172f8491a2bd6905fda9d21afb8957c16a97c5f6 100644 (file)
@@ -321,7 +321,7 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping,
  * for a block special file file->f_path.dentry->d_inode->i_size is zero
  * so we compute the size by hand (just as in block_read/write above)
  */
-static loff_t block_llseek(struct file *file, loff_t offset, int origin)
+static loff_t block_llseek(struct file *file, loff_t offset, int whence)
 {
        struct inode *bd_inode = file->f_mapping->host;
        loff_t size;
@@ -331,7 +331,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
        size = i_size_read(bd_inode);
 
        retval = -EINVAL;
-       switch (origin) {
+       switch (whence) {
                case SEEK_END:
                        offset += size;
                        break;
index a8ee75cb96eeab848677daeea7130297bbd22e43..9c6673a9231fad34c6387f08822aaada78fe5665 100644 (file)
@@ -2120,7 +2120,7 @@ out:
        return ret;
 }
 
-static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
+static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_map *em;
@@ -2154,7 +2154,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
         * before the position we want in case there is outstanding delalloc
         * going on here.
         */
-       if (origin == SEEK_HOLE && start != 0) {
+       if (whence == SEEK_HOLE && start != 0) {
                if (start <= root->sectorsize)
                        em = btrfs_get_extent_fiemap(inode, NULL, 0, 0,
                                                     root->sectorsize, 0);
@@ -2188,13 +2188,13 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
                                }
                        }
 
-                       if (origin == SEEK_HOLE) {
+                       if (whence == SEEK_HOLE) {
                                *offset = start;
                                free_extent_map(em);
                                break;
                        }
                } else {
-                       if (origin == SEEK_DATA) {
+                       if (whence == SEEK_DATA) {
                                if (em->block_start == EXTENT_MAP_DELALLOC) {
                                        if (start >= inode->i_size) {
                                                free_extent_map(em);
@@ -2231,16 +2231,16 @@ out:
        return ret;
 }
 
-static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
+static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)
 {
        struct inode *inode = file->f_mapping->host;
        int ret;
 
        mutex_lock(&inode->i_mutex);
-       switch (origin) {
+       switch (whence) {
        case SEEK_END:
        case SEEK_CUR:
-               offset = generic_file_llseek(file, offset, origin);
+               offset = generic_file_llseek(file, offset, whence);
                goto out;
        case SEEK_DATA:
        case SEEK_HOLE:
@@ -2249,7 +2249,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
                        return -ENXIO;
                }
 
-               ret = find_desired_extent(inode, &offset, origin);
+               ret = find_desired_extent(inode, &offset, whence);
                if (ret) {
                        mutex_unlock(&inode->i_mutex);
                        return ret;
index e5b77319c97b7fe1a537bfd292e859467389167a..8c1aabe93b6779e2c2a39333c73f26222c7f4c28 100644 (file)
@@ -454,7 +454,7 @@ static void reset_readdir(struct ceph_file_info *fi)
        fi->flags &= ~CEPH_F_ATEND;
 }
 
-static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
+static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
 {
        struct ceph_file_info *fi = file->private_data;
        struct inode *inode = file->f_mapping->host;
@@ -463,7 +463,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
 
        mutex_lock(&inode->i_mutex);
        retval = -EINVAL;
-       switch (origin) {
+       switch (whence) {
        case SEEK_END:
                offset += inode->i_size + 2;   /* FIXME */
                break;
index 5840d2aaed15f76788e41fcee9d71bf81e2c0322..d4dfdcf76d7fdfbff4c318e1e4f5d9a2487d0088 100644 (file)
@@ -797,7 +797,7 @@ out:
 /*
  * llseek.  be sure to verify file size on SEEK_END.
  */
-static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
+static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
 {
        struct inode *inode = file->f_mapping->host;
        int ret;
@@ -805,7 +805,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
        mutex_lock(&inode->i_mutex);
        __ceph_do_pending_vmtruncate(inode);
 
-       if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) {
+       if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) {
                ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
                if (ret < 0) {
                        offset = ret;
@@ -813,7 +813,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
                }
        }
 
-       switch (origin) {
+       switch (whence) {
        case SEEK_END:
                offset += inode->i_size;
                break;
index 210f0af83fc449f8667f6482558dda9d5a060654..ce9f3c5421bf61d3d3bf828cc40820047c9b010c 100644 (file)
@@ -695,13 +695,13 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        return written;
 }
 
-static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
+static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
 {
        /*
-        * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
+        * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
         * the cached file length
         */
-       if (origin != SEEK_SET && origin != SEEK_CUR) {
+       if (whence != SEEK_SET && whence != SEEK_CUR) {
                int rc;
                struct inode *inode = file->f_path.dentry->d_inode;
 
@@ -728,7 +728,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
                if (rc < 0)
                        return (loff_t)rc;
        }
-       return generic_file_llseek(file, offset, origin);
+       return generic_file_llseek(file, offset, whence);
 }
 
 static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
index 7414ae24a79b4690ed5fb7ed72245d941791a82f..712b10f64c709ff8a27d423aa7a5186f80aec04f 100644 (file)
@@ -1613,12 +1613,12 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
        return 0;
 }
 
-static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
+static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
 {
        struct dentry * dentry = file->f_path.dentry;
 
        mutex_lock(&dentry->d_inode->i_mutex);
-       switch (origin) {
+       switch (whence) {
                case 1:
                        offset += file->f_pos;
                case 0:
index d81b9f654086d1cdb3899767cf6e1e5bf05e9f6e..35470d9b96e68951de6f1a63fe3657f09a8296c4 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/export.h>
 #include <linux/kref.h>
 #include <linux/eventfd.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 struct eventfd_ctx {
        struct kref kref;
@@ -284,7 +286,25 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
        return res;
 }
 
+#ifdef CONFIG_PROC_FS
+static int eventfd_show_fdinfo(struct seq_file *m, struct file *f)
+{
+       struct eventfd_ctx *ctx = f->private_data;
+       int ret;
+
+       spin_lock_irq(&ctx->wqh.lock);
+       ret = seq_printf(m, "eventfd-count: %16llx\n",
+                        (unsigned long long)ctx->count);
+       spin_unlock_irq(&ctx->wqh.lock);
+
+       return ret;
+}
+#endif
+
 static const struct file_operations eventfd_fops = {
+#ifdef CONFIG_PROC_FS
+       .show_fdinfo    = eventfd_show_fdinfo,
+#endif
        .release        = eventfd_release,
        .poll           = eventfd_poll,
        .read           = eventfd_read,
index cd96649bfe62da9e408dbd629f56f6452c139bc9..be56b21435f8c4e5170fdb2c0963abdd24dc9291 100644 (file)
@@ -38,6 +38,8 @@
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <linux/atomic.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 /*
  * LOCKING:
@@ -783,8 +785,34 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
        return pollflags != -1 ? pollflags : 0;
 }
 
+#ifdef CONFIG_PROC_FS
+static int ep_show_fdinfo(struct seq_file *m, struct file *f)
+{
+       struct eventpoll *ep = f->private_data;
+       struct rb_node *rbp;
+       int ret = 0;
+
+       mutex_lock(&ep->mtx);
+       for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
+               struct epitem *epi = rb_entry(rbp, struct epitem, rbn);
+
+               ret = seq_printf(m, "tfd: %8d events: %8x data: %16llx\n",
+                                epi->ffd.fd, epi->event.events,
+                                (long long)epi->event.data);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&ep->mtx);
+
+       return ret;
+}
+#endif
+
 /* File callbacks that implement the eventpoll file behaviour */
 static const struct file_operations eventpoll_fops = {
+#ifdef CONFIG_PROC_FS
+       .show_fdinfo    = ep_show_fdinfo,
+#endif
        .release        = ep_eventpoll_release,
        .poll           = ep_eventpoll_poll,
        .llseek         = noop_llseek,
index b71b08ce71204824c7c66c8d101a7ebecdbb4db0..d8e1191cb112eb2d77154908a32699a06c4bda78 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1353,6 +1353,10 @@ int search_binary_handler(struct linux_binprm *bprm)
        struct linux_binfmt *fmt;
        pid_t old_pid, old_vpid;
 
+       /* This allows 4 levels of binfmt rewrites before failing hard. */
+       if (depth > 5)
+               return -ELOOP;
+
        retval = security_bprm_check(bprm);
        if (retval)
                return retval;
@@ -1377,12 +1381,8 @@ int search_binary_handler(struct linux_binprm *bprm)
                        if (!try_module_get(fmt->module))
                                continue;
                        read_unlock(&binfmt_lock);
+                       bprm->recursion_depth = depth + 1;
                        retval = fn(bprm);
-                       /*
-                        * Restore the depth counter to its starting value
-                        * in this call, so we don't have to rely on every
-                        * load_binary function to restore it on return.
-                        */
                        bprm->recursion_depth = depth;
                        if (retval >= 0) {
                              &n