mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
Merge branch 'akpm' (patches from Andrew Morton)
Merge second patch-bomb from Andrew Morton: - a few hotfixes - drivers/dma updates - MAINTAINERS updates - Quite a lot of lib/ updates - checkpatch updates - binfmt updates - autofs4 - drivers/rtc/ - various small tweaks to less used filesystems - ipc/ updates - kernel/watchdog.c changes * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits) mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared kernel/param: consolidate __{start,stop}___param[] in <linux/moduleparam.h> ia64: remove duplicate declarations of __per_cpu_start[] and __per_cpu_end[] frv: remove unused declarations of __start___ex_table and __stop___ex_table kvm: ensure hard lockup detection is disabled by default kernel/watchdog.c: control hard lockup detection default staging: rtl8192u: use %*pEn to escape buffer staging: rtl8192e: use %*pEn to escape buffer staging: wlan-ng: use %*pEhp to print SN lib80211: remove unused print_ssid() wireless: hostap: proc: print properly escaped SSID wireless: ipw2x00: print SSID via %*pE wireless: libertas: print esaped string via %*pE lib/vsprintf: add %*pE[achnops] format specifier lib / string_helpers: introduce string_escape_mem() lib / string_helpers: refactoring the test suite lib / string_helpers: move documentation to c-file include/linux: remove strict_strto* definitions arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable fs: check bh blocknr earlier when searching lru ...
This commit is contained in:
commit
dfe2c6dcc8
@ -15,39 +15,50 @@ First you must mount binfmt_misc:
|
||||
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
||||
|
||||
To actually register a new binary type, you have to set up a string looking like
|
||||
:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon
|
||||
your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
|
||||
:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
|
||||
upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
|
||||
|
||||
Here is what the fields mean:
|
||||
- 'name' is an identifier string. A new /proc file will be created with this
|
||||
name below /proc/sys/fs/binfmt_misc
|
||||
name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
|
||||
reasons.
|
||||
- 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
|
||||
- 'offset' is the offset of the magic/mask in the file, counted in bytes. This
|
||||
defaults to 0 if you omit it (i.e. you write ':name:type::magic...')
|
||||
defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
|
||||
when using filename extension matching.
|
||||
- 'magic' is the byte sequence binfmt_misc is matching for. The magic string
|
||||
may contain hex-encoded characters like \x0a or \xA4. In a shell environment
|
||||
you will have to write \\x0a to prevent the shell from eating your \.
|
||||
may contain hex-encoded characters like \x0a or \xA4. Note that you must
|
||||
escape any NUL bytes; parsing halts at the first one. In a shell environment
|
||||
you might have to write \\x0a to prevent the shell from eating your \.
|
||||
If you chose filename extension matching, this is the extension to be
|
||||
recognised (without the '.', the \x0a specials are not allowed). Extension
|
||||
matching is case sensitive!
|
||||
matching is case sensitive, and slashes '/' are not allowed!
|
||||
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
|
||||
bits from matching by supplying a string like magic and as long as magic.
|
||||
The mask is anded with the byte sequence of the file.
|
||||
The mask is anded with the byte sequence of the file. Note that you must
|
||||
escape any NUL bytes; parsing halts at the first one. Ignored when using
|
||||
filename extension matching.
|
||||
- 'interpreter' is the program that should be invoked with the binary as first
|
||||
argument (specify the full path)
|
||||
- 'flags' is an optional field that controls several aspects of the invocation
|
||||
of the interpreter. It is a string of capital letters, each controls a certain
|
||||
aspect. The following flags are supported -
|
||||
'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the
|
||||
original argv[0] with the full path to the binary. When this flag is
|
||||
included, binfmt_misc will add an argument to the argument vector for
|
||||
this purpose, thus preserving the original argv[0].
|
||||
of the interpreter. It is a string of capital letters, each controls a
|
||||
certain aspect. The following flags are supported -
|
||||
'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
|
||||
the original argv[0] with the full path to the binary. When this
|
||||
flag is included, binfmt_misc will add an argument to the argument
|
||||
vector for this purpose, thus preserving the original argv[0].
|
||||
e.g. If your interp is set to /bin/foo and you run `blah` (which is
|
||||
in /usr/local/bin), then the kernel will execute /bin/foo with
|
||||
argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"]. The
|
||||
interp has to be aware of this so it can execute /usr/local/bin/blah
|
||||
with argv[] set to ["blah"].
|
||||
'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
|
||||
of the binary to the interpreter as an argument. When this flag is
|
||||
included, binfmt_misc will open the file for reading and pass its
|
||||
descriptor as an argument, instead of the full path, thus allowing
|
||||
the interpreter to execute non-readable binaries. This feature should
|
||||
be used with care - the interpreter has to be trusted not to emit
|
||||
the contents of the non-readable binary.
|
||||
the interpreter to execute non-readable binaries. This feature
|
||||
should be used with care - the interpreter has to be trusted not to
|
||||
emit the contents of the non-readable binary.
|
||||
'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
|
||||
the credentials and security token of the new process according to
|
||||
the interpreter. When this flag is included, these attributes are
|
||||
@ -58,7 +69,7 @@ Here is what the fields mean:
|
||||
|
||||
|
||||
There are some restrictions:
|
||||
- the whole register string may not exceed 255 characters
|
||||
- the whole register string may not exceed 1920 characters
|
||||
- the magic must reside in the first 128 bytes of the file, i.e.
|
||||
offset+size(magic) has to be less than 128
|
||||
- the interpreter string may not exceed 127 characters
|
||||
@ -110,7 +121,4 @@ passes it the full filename (or the file descriptor) to use. Using $PATH can
|
||||
cause unexpected behaviour and can be a security hazard.
|
||||
|
||||
|
||||
There is a web page about binfmt_misc at
|
||||
http://www.tat.physik.uni-tuebingen.de
|
||||
|
||||
Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
|
||||
|
18
Documentation/devicetree/bindings/i2c/ti,bq32k.txt
Normal file
18
Documentation/devicetree/bindings/i2c/ti,bq32k.txt
Normal file
@ -0,0 +1,18 @@
|
||||
* TI BQ32000 I2C Serial Real-Time Clock
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "ti,bq32000".
|
||||
- reg: I2C address for chip
|
||||
|
||||
Optional properties:
|
||||
- trickle-resistor-ohms : Selected resistor for trickle charger
|
||||
Values usable are 1120 and 20180
|
||||
Should be given if trickle charger should be enabled
|
||||
- trickle-diode-disable : Do not use internal trickle charger diode
|
||||
Should be given if internal trickle charger diode should be disabled
|
||||
Example:
|
||||
bq32000: rtc@68 {
|
||||
compatible = "ti,bq32000";
|
||||
trickle-resistor-ohms = <1120>;
|
||||
reg = <0x68>;
|
||||
};
|
@ -35,7 +35,6 @@ catalyst,24c32 i2c serial eeprom
|
||||
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
|
||||
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
|
||||
dallas,ds1338 I2C RTC with 56-Byte NV RAM
|
||||
dallas,ds1339 I2C Serial Real-Time Clock
|
||||
dallas,ds1340 I2C RTC with Trickle Charger
|
||||
dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
|
||||
dallas,ds1631 High-Precision Digital Thermometer
|
||||
|
18
Documentation/devicetree/bindings/rtc/dallas,ds1339.txt
Normal file
18
Documentation/devicetree/bindings/rtc/dallas,ds1339.txt
Normal file
@ -0,0 +1,18 @@
|
||||
* Dallas DS1339 I2C Serial Real-Time Clock
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "dallas,ds1339".
|
||||
- reg: I2C address for chip
|
||||
|
||||
Optional properties:
|
||||
- trickle-resistor-ohms : Selected resistor for trickle charger
|
||||
Values usable for ds1339 are 250, 2000, 4000
|
||||
Should be given if trickle charger should be enabled
|
||||
- trickle-diode-disable : Do not use internal trickle charger diode
|
||||
Should be given if internal trickle charger diode should be disabled
|
||||
Example:
|
||||
ds1339: rtc@68 {
|
||||
compatible = "dallas,ds1339";
|
||||
trickle-resistor-ohms = <250>;
|
||||
reg = <0x68>;
|
||||
};
|
@ -3,7 +3,10 @@
|
||||
Required properties:
|
||||
- compatible: should be one of the following.
|
||||
* "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc.
|
||||
* "samsung,s3c2416-rtc" - for controllers compatible with s3c2416 rtc.
|
||||
* "samsung,s3c2443-rtc" - for controllers compatible with s3c2443 rtc.
|
||||
* "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
|
||||
* "samsung,exynos3250-rtc" - for controllers compatible with exynos3250 rtc.
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: Two interrupt numbers to the cpu should be specified. First
|
||||
|
520
Documentation/filesystems/autofs4.txt
Normal file
520
Documentation/filesystems/autofs4.txt
Normal file
@ -0,0 +1,520 @@
|
||||
<head>
|
||||
<style> p { max-width:50em} ol, ul {max-width: 40em}</style>
|
||||
</head>
|
||||
|
||||
autofs - how it works
|
||||
=====================
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
The goal of autofs is to provide on-demand mounting and race free
|
||||
automatic unmounting of various other filesystems. This provides two
|
||||
key advantages:
|
||||
|
||||
1. There is no need to delay boot until all filesystems that
|
||||
might be needed are mounted. Processes that try to access those
|
||||
slow filesystems might be delayed but other processes can
|
||||
continue freely. This is particularly important for
|
||||
network filesystems (e.g. NFS) or filesystems stored on
|
||||
media with a media-changing robot.
|
||||
|
||||
2. The names and locations of filesystems can be stored in
|
||||
a remote database and can change at any time. The content
|
||||
in that data base at the time of access will be used to provide
|
||||
a target for the access. The interpretation of names in the
|
||||
filesystem can even be programmatic rather than database-backed,
|
||||
allowing wildcards for example, and can vary based on the user who
|
||||
first accessed a name.
|
||||
|
||||
Context
|
||||
-------
|
||||
|
||||
The "autofs4" filesystem module is only one part of an autofs system.
|
||||
There also needs to be a user-space program which looks up names
|
||||
and mounts filesystems. This will often be the "automount" program,
|
||||
though other tools including "systemd" can make use of "autofs4".
|
||||
This document describes only the kernel module and the interactions
|
||||
required with any user-space program. Subsequent text refers to this
|
||||
as the "automount daemon" or simply "the daemon".
|
||||
|
||||
"autofs4" is a Linux kernel module with provides the "autofs"
|
||||
filesystem type. Several "autofs" filesystems can be mounted and they
|
||||
can each be managed separately, or all managed by the same daemon.
|
||||
|
||||
Content
|
||||
-------
|
||||
|
||||
An autofs filesystem can contain 3 sorts of objects: directories,
|
||||
symbolic links and mount traps. Mount traps are directories with
|
||||
extra properties as described in the next section.
|
||||
|
||||
Objects can only be created by the automount daemon: symlinks are
|
||||
created with a regular `symlink` system call, while directories and
|
||||
mount traps are created with `mkdir`. The determination of whether a
|
||||
directory should be a mount trap or not is quite _ad hoc_, largely for
|
||||
historical reasons, and is determined in part by the
|
||||
*direct*/*indirect*/*offset* mount options, and the *maxproto* mount option.
|
||||
|
||||
If neither the *direct* or *offset* mount options are given (so the
|
||||
mount is considered to be *indirect*), then the root directory is
|
||||
always a regular directory, otherwise it is a mount trap when it is
|
||||
empty and a regular directory when not empty. Note that *direct* and
|
||||
*offset* are treated identically so a concise summary is that the root
|
||||
directory is a mount trap only if the filesystem is mounted *direct*
|
||||
and the root is empty.
|
||||
|
||||
Directories created in the root directory are mount traps only if the
|
||||
filesystem is mounted *indirect* and they are empty.
|
||||
|
||||
Directories further down the tree depend on the *maxproto* mount
|
||||
option and particularly whether it is less than five or not.
|
||||
When *maxproto* is five, no directories further down the
|
||||
tree are ever mount traps, they are always regular directories. When
|
||||
the *maxproto* is four (or three), these directories are mount traps
|
||||
precisely when they are empty.
|
||||
|
||||
So: non-empty (i.e. non-leaf) directories are never mount traps. Empty
|
||||
directories are sometimes mount traps, and sometimes not depending on
|
||||
where in the tree they are (root, top level, or lower), the *maxproto*,
|
||||
and whether the mount was *indirect* or not.
|
||||
|
||||
Mount Traps
|
||||
---------------
|
||||
|
||||
A core element of the implementation of autofs is the Mount Traps
|
||||
which are provided by the Linux VFS. Any directory provided by a
|
||||
filesystem can be designated as a trap. This involves two separate
|
||||
features that work together to allow autofs to do its job.
|
||||
|
||||
**DCACHE_NEED_AUTOMOUNT**
|
||||
|
||||
If a dentry has the DCACHE_NEED_AUTOMOUNT flag set (which gets set if
|
||||
the inode has S_AUTOMOUNT set, or can be set directly) then it is
|
||||
(potentially) a mount trap. Any access to this directory beyond a
|
||||
"`stat`" will (normally) cause the `d_op->d_automount()` dentry operation
|
||||
to be called. The task of this method is to find the filesystem that
|
||||
should be mounted on the directory and to return it. The VFS is
|
||||
responsible for actually mounting the root of this filesystem on the
|
||||
directory.
|
||||
|
||||
autofs doesn't find the filesystem itself but sends a message to the
|
||||
automount daemon asking it to find and mount the filesystem. The
|
||||
autofs `d_automount` method then waits for the daemon to report that
|
||||
everything is ready. It will then return "`NULL`" indicating that the
|
||||
mount has already happened. The VFS doesn't try to mount anything but
|
||||
follows down the mount that is already there.
|
||||
|
||||
This functionality is sufficient for some users of mount traps such
|
||||
as NFS which creates traps so that mountpoints on the server can be
|
||||
reflected on the client. However it is not sufficient for autofs. As
|
||||
mounting onto a directory is considered to be "beyond a `stat`", the
|
||||
automount daemon would not be able to mount a filesystem on the 'trap'
|
||||
directory without some way to avoid getting caught in the trap. For
|
||||
that purpose there is another flag.
|
||||
|
||||
**DCACHE_MANAGE_TRANSIT**
|
||||
|
||||
If a dentry has DCACHE_MANAGE_TRANSIT set then two very different but
|
||||
related behaviors are invoked, both using the `d_op->d_manage()`
|
||||
dentry operation.
|
||||
|
||||
Firstly, before checking to see if any filesystem is mounted on the
|
||||
directory, d_manage() will be called with the `rcu_walk` parameter set
|
||||
to `false`. It may return one of three things:
|
||||
|
||||
- A return value of zero indicates that there is nothing special
|
||||
about this dentry and normal checks for mounts and automounts
|
||||
should proceed.
|
||||
|
||||
autofs normally returns zero, but first waits for any
|
||||
expiry (automatic unmounting of the mounted filesystem) to
|
||||
complete. This avoids races.
|
||||
|
||||
- A return value of `-EISDIR` tells the VFS to ignore any mounts
|
||||
on the directory and to not consider calling `->d_automount()`.
|
||||
This effectively disables the **DCACHE_NEED_AUTOMOUNT** flag
|
||||
causing the directory not be a mount trap after all.
|
||||
|
||||
autofs returns this if it detects that the process performing the
|
||||
lookup is the automount daemon and that the mount has been
|
||||
requested but has not yet completed. How it determines this is
|
||||
discussed later. This allows the automount daemon not to get
|
||||
caught in the mount trap.
|
||||
|
||||
There is a subtlety here. It is possible that a second autofs
|
||||
filesystem can be mounted below the first and for both of them to
|
||||
be managed by the same daemon. For the daemon to be able to mount
|
||||
something on the second it must be able to "walk" down past the
|
||||
first. This means that d_manage cannot *always* return -EISDIR for
|
||||
the automount daemon. It must only return it when a mount has
|
||||
been requested, but has not yet completed.
|
||||
|
||||
`d_manage` also returns `-EISDIR` if the dentry shouldn't be a
|
||||
mount trap, either because it is a symbolic link or because it is
|
||||
not empty.
|
||||
|
||||
- Any other negative value is treated as an error and returned
|
||||
to the caller.
|
||||
|
||||
autofs can return
|
||||
|
||||
- -ENOENT if the automount daemon failed to mount anything,
|
||||
- -ENOMEM if it ran out of memory,
|
||||
- -EINTR if a signal arrived while waiting for expiry to
|
||||
complete
|
||||
- or any other error sent down by the automount daemon.
|
||||
|
||||
|
||||
The second use case only occurs during an "RCU-walk" and so `rcu_walk`
|
||||
will be set.
|
||||
|
||||
An RCU-walk is a fast and lightweight process for walking down a
|
||||
filename path (i.e. it is like running on tip-toes). RCU-walk cannot
|
||||
cope with all situations so when it finds a difficulty it falls back
|
||||
to "REF-walk", which is slower but more robust.
|
||||
|
||||
RCU-walk will never call `->d_automount`; the filesystems must already
|
||||
be mounted or RCU-walk cannot handle the path.
|
||||
To determine if a mount-trap is safe for RCU-walk mode it calls
|
||||
`->d_manage()` with `rcu_walk` set to `true`.
|
||||
|
||||
In this case `d_manage()` must avoid blocking and should avoid taking
|
||||
spinlocks if at all possible. Its sole purpose is to determine if it
|
||||
would be safe to follow down into any mounted directory and the only
|
||||
reason that it might not be is if an expiry of the mount is
|
||||
underway.
|
||||
|
||||
In the `rcu_walk` case, `d_manage()` cannot return -EISDIR to tell the
|
||||
VFS that this is a directory that doesn't require d_automount. If
|
||||
`rcu_walk` sees a dentry with DCACHE_NEED_AUTOMOUNT set but nothing
|
||||
mounted, it *will* fall back to REF-walk. `d_manage()` cannot make the
|
||||
VFS remain in RCU-walk mode, but can only tell it to get out of
|
||||
RCU-walk mode by returning `-ECHILD`.
|
||||
|
||||
So `d_manage()`, when called with `rcu_walk` set, should either return
|
||||
-ECHILD if there is any reason to believe it is unsafe to end the
|
||||
mounted filesystem, and otherwise should return 0.
|
||||
|
||||
autofs will return `-ECHILD` if an expiry of the filesystem has been
|
||||
initiated or is being considered, otherwise it returns 0.
|
||||
|
||||
|
||||
Mountpoint expiry
|
||||
-----------------
|
||||
|
||||
The VFS has a mechansim for automatically expiring unused mounts,
|
||||
much as it can expire any unused dentry information from the dcache.
|
||||
This is guided by the MNT_SHRINKABLE flag. This only applies to
|
||||
mounts that were created by `d_automount()` returning a filesystem to be
|
||||
mounted. As autofs doesn't return such a filesystem but leaves the
|
||||
mounting to the automount daemon, it must involve the automount daemon
|
||||
in unmounting as well. This also means that autofs has more control
|
||||
of expiry.
|
||||
|
||||
The VFS also supports "expiry" of mounts using the MNT_EXPIRE flag to
|
||||
the `umount` system call. Unmounting with MNT_EXPIRE will fail unless
|
||||
a previous attempt had been made, and the filesystem has been inactive
|
||||
and untouched since that previous attempt. autofs4 does not depend on
|
||||
this but has its own internal tracking of whether filesystems were
|
||||
recently used. This allows individual names in the autofs directory
|
||||
to expire separately.
|
||||
|
||||
With version 4 of the protocol, the automount daemon can try to
|
||||
unmount any filesystems mounted on the autofs filesystem or remove any
|
||||
symbolic links or empty directories any time it likes. If the unmount
|
||||
or removal is successful the filesystem will be returned to the state
|
||||
it was before the mount or creation, so that any access of the name
|
||||
will trigger normal auto-mount processing. In particlar, `rmdir` and
|
||||
`unlink` do not leave negative entries in the dcache as a normal
|
||||
filesystem would, so an attempt to access a recently-removed object is
|
||||
passed to autofs for handling.
|
||||
|
||||
With version 5, this is not safe except for unmounting from top-level
|
||||
directories. As lower-level directories are never mount traps, other
|
||||
processes will see an empty directory as soon as the filesystem is
|
||||
unmounted. So it is generally safest to use the autofs expiry
|
||||
protocol described below.
|
||||
|
||||
Normally the daemon only wants to remove entries which haven't been
|
||||
used for a while. For this purpose autofs maintains a "`last_used`"
|
||||
time stamp on each directory or symlink. For symlinks it genuinely
|
||||
does record the last time the symlink was "used" or followed to find
|
||||
out where it points to. For directories the field is a slight
|
||||
misnomer. It actually records the last time that autofs checked if
|
||||
the directory or one of its descendents was busy and found that it
|
||||
was. This is just as useful and doesn't require updating the field so
|
||||
often.
|
||||
|
||||
The daemon is able to ask autofs if anything is due to be expired,
|
||||
using an `ioctl` as discussed later. For a *direct* mount, autofs
|
||||
considers if the entire mount-tree can be unmounted or not. For an
|
||||
*indirect* mount, autofs considers each of the names in the top level
|
||||
directory to determine if any of those can be unmounted and cleaned
|
||||
up.
|
||||
|
||||
There is an option with indirect mounts to consider each of the leaves
|
||||
that has been mounted on instead of considering the top-level names.
|
||||
This is intended for compatability with version 4 of autofs and should
|
||||
be considered as deprecated.
|
||||
|
||||
When autofs considers a directory it checks the `last_used` time and
|
||||
compares it with the "timeout" value set when the filesystem was
|
||||
mounted, though this check is ignored in some cases. It also checks if
|
||||
the directory or anything below it is in use. For symbolic links,
|
||||
only the `last_used` time is ever considered.
|
||||
|
||||
If both appear to support expiring the directory or symlink, an action
|
||||
is taken.
|
||||
|
||||
There are two ways to ask autofs to consider expiry. The first is to
|
||||
use the **AUTOFS_IOC_EXPIRE** ioctl. This only works for indirect
|
||||
mounts. If it finds something in the root directory to expire it will
|
||||
return the name of that thing. Once a name has been returned the
|
||||
automount daemon needs to unmount any filesystems mounted below the
|
||||
name normally. As described above, this is unsafe for non-toplevel
|
||||
mounts in a version-5 autofs. For this reason the current `automountd`
|
||||
does not use this ioctl.
|
||||
|
||||
The second mechanism uses either the **AUTOFS_DEV_IOCTL_EXPIRE_CMD** or
|
||||
the **AUTOFS_IOC_EXPIRE_MULTI** ioctl. This will work for both direct and
|
||||
indirect mounts. If it selects an object to expire, it will notify
|
||||
the daemon using the notification mechanism described below. This
|
||||
will block until the daemon acknowledges the expiry notification.
|
||||
This implies that the "`EXPIRE`" ioctl must be sent from a different
|
||||
thread than the one which handles notification.
|
||||
|
||||
While the ioctl is blocking, the entry is marked as "expiring" and
|
||||
`d_manage` will block until the daemon affirms that the unmount has
|
||||
completed (together with removing any directories that might have been
|
||||
necessary), or has been aborted.
|
||||
|
||||
Communicating with autofs: detecting the daemon
|
||||
-----------------------------------------------
|
||||
|
||||
There are several forms of communication between the automount daemon
|
||||
and the filesystem. As we have already seen, the daemon can create and
|
||||
remove directories and symlinks using normal filesystem operations.
|
||||
autofs knows whether a process requesting some operation is the daemon
|
||||
or not based on its process-group id number (see getpgid(1)).
|
||||
|
||||
When an autofs filesystem it mounted the pgid of the mounting
|
||||
processes is recorded unless the "pgrp=" option is given, in which
|
||||
case that number is recorded instead. Any request arriving from a
|
||||
process in that process group is considered to come from the daemon.
|
||||
If the daemon ever has to be stopped and restarted a new pgid can be
|
||||
provided through an ioctl as will be described below.
|
||||
|
||||
Communicating with autofs: the event pipe
|
||||
-----------------------------------------
|
||||
|
||||
When an autofs filesystem is mounted, the 'write' end of a pipe must
|
||||
be passed using the 'fd=' mount option. autofs will write
|
||||
notification messages to this pipe for the daemon to respond to.
|
||||
For version 5, the format of the message is:
|
||||
|
||||
struct autofs_v5_packet {
|
||||
int proto_version; /* Protocol version */
|
||||
int type; /* Type of packet */
|
||||
autofs_wqt_t wait_queue_token;
|
||||
__u32 dev;
|
||||
__u64 ino;
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 pid;
|
||||
__u32 tgid;
|
||||
__u32 len;
|
||||
char name[NAME_MAX+1];
|
||||
};
|
||||
|
||||
where the type is one of
|
||||
|
||||
autofs_ptype_missing_indirect
|
||||
autofs_ptype_expire_indirect
|
||||
autofs_ptype_missing_direct
|
||||
autofs_ptype_expire_direct
|
||||
|
||||
so messages can indicate that a name is missing (something tried to
|
||||
access it but it isn't there) or that it has been selected for expiry.
|
||||
|
||||
The pipe will be set to "packet mode" (equivalent to passing
|
||||
`O_DIRECT`) to _pipe2(2)_ so that a read from the pipe will return at
|
||||
most one packet, and any unread portion of a packet will be discarded.
|
||||
|
||||
The `wait_queue_token` is a unique number which can identify a
|
||||
particular request to be acknowledged. When a message is sent over
|
||||
the pipe the affected dentry is marked as either "active" or
|
||||
"expiring" and other accesses to it block until the message is
|
||||
acknowledged using one of the ioctls below and the relevant
|
||||
`wait_queue_token`.
|
||||
|
||||
Communicating with autofs: root directory ioctls
|
||||
------------------------------------------------
|
||||
|
||||
The root directory of an autofs filesystem will respond to a number of
|
||||
ioctls. The process issuing the ioctl must have the CAP_SYS_ADMIN
|
||||
capability, or must be the automount daemon.
|
||||
|
||||
The available ioctl commands are:
|
||||
|
||||
- **AUTOFS_IOC_READY**: a notification has been handled. The argument
|
||||
to the ioctl command is the "wait_queue_token" number
|
||||
corresponding to the notification being acknowledged.
|
||||
- **AUTOFS_IOC_FAIL**: similar to above, but indicates failure with
|
||||
the error code `ENOENT`.
|
||||
- **AUTOFS_IOC_CATATONIC**: Causes the autofs to enter "catatonic"
|
||||
mode meaning that it stops sending notifications to the daemon.
|
||||
This mode is also entered if a write to the pipe fails.
|
||||
- **AUTOFS_IOC_PROTOVER**: This returns the protocol version in use.
|
||||
- **AUTOFS_IOC_PROTOSUBVER**: Returns the protocol sub-version which
|
||||
is really a version number for the implementation. It is
|
||||
currently 2.
|
||||
- **AUTOFS_IOC_SETTIMEOUT**: This passes a pointer to an unsigned
|
||||
long. The value is used to set the timeout for expiry, and
|
||||
the current timeout value is stored back through the pointer.
|
||||
- **AUTOFS_IOC_ASKUMOUNT**: Returns, in the pointed-to `int`, 1 if
|
||||
the filesystem could be unmounted. This is only a hint as
|
||||
the situation could change at any instant. This call can be
|
||||
use to avoid a more expensive full unmount attempt.
|
||||
- **AUTOFS_IOC_EXPIRE**: as described above, this asks if there is
|
||||
anything suitable to expire. A pointer to a packet:
|
||||
|
||||
struct autofs_packet_expire_multi {
|
||||
int proto_version; /* Protocol version */
|
||||
int type; /* Type of packet */
|
||||
autofs_wqt_t wait_queue_token;
|
||||
int len;
|
||||
char name[NAME_MAX+1];
|
||||
};
|
||||
|
||||
is required. This is filled in with the name of something
|
||||
that can be unmounted or removed. If nothing can be expired,
|
||||
`errno` is set to `EAGAIN`. Even though a `wait_queue_token`
|
||||
is present in the structure, no "wait queue" is established
|
||||
and no acknowledgment is needed.
|
||||
- **AUTOFS_IOC_EXPIRE_MULTI**: This is similar to
|
||||
**AUTOFS_IOC_EXPIRE** except that it causes notification to be
|
||||
sent to the daemon, and it blocks until the daemon acknowledges.
|
||||
The argument is an integer which can contain two different flags.
|
||||
|
||||
**AUTOFS_EXP_IMMEDIATE** causes `last_used` time to be ignored
|
||||
and objects are expired if the are not in use.
|
||||
|
||||
**AUTOFS_EXP_LEAVES** will select a leaf rather than a top-level
|
||||
name to expire. This is only safe when *maxproto* is 4.
|
||||
|
||||
Communicating with autofs: char-device ioctls
|
||||
---------------------------------------------
|
||||
|
||||
It is not always possible to open the root of an autofs filesystem,
|
||||
particularly a *direct* mounted filesystem. If the automount daemon
|
||||
is restarted there is no way for it to regain control of existing
|
||||
mounts using any of the above communication channels. To address this
|
||||
need there is a "miscellaneous" character device (major 10, minor 235)
|
||||
which can be used to communicate directly with the autofs filesystem.
|
||||
It requires CAP_SYS_ADMIN for access.
|
||||
|
||||
The `ioctl`s that can be used on this device are described in a separate
|
||||
document `autofs4-mount-control.txt`, and are summarized briefly here.
|
||||
Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:
|
||||
|
||||
struct autofs_dev_ioctl {
|
||||
__u32 ver_major;
|
||||
__u32 ver_minor;
|
||||
__u32 size; /* total size of data passed in
|
||||
* including this struct */
|
||||
__s32 ioctlfd; /* automount command fd */
|
||||
|
||||
__u32 arg1; /* Command parameters */
|
||||
__u32 arg2;
|
||||
|
||||
char path[0];
|
||||
};
|
||||
|
||||
For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target
|
||||
filesystem is identified by the `path`. All other commands identify
|
||||
the filesystem by the `ioctlfd` which is a file descriptor open on the
|
||||
root, and which can be returned by **OPEN_MOUNT**.
|
||||
|
||||
The `ver_major` and `ver_minor` are in/out parameters which check that
|
||||
the requested version is supported, and report the maximum version
|
||||
that the kernel module can support.
|
||||
|
||||
Commands are:
|
||||
|
||||
- **AUTOFS_DEV_IOCTL_VERSION_CMD**: does nothing, except validate and
|
||||
set version numbers.
|
||||
- **AUTOFS_DEV_IOCTL_OPENMOUNT_CMD**: return an open file descriptor
|
||||
on the root of an autofs filesystem. The filesystem is identified
|
||||
by name and device number, which is stored in `arg1`. Device
|
||||
numbers for existing filesystems can be found in
|
||||
`/proc/self/mountinfo`.
|
||||
- **AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD**: same as `close(ioctlfd)`.
|
||||
- **AUTOFS_DEV_IOCTL_SETPIPEFD_CMD**: if the filesystem is in
|
||||
catatonic mode, this can provide the write end of a new pipe
|
||||
in `arg1` to re-establish communication with a daemon. The
|
||||
process group of the calling process is used to identify the
|
||||
daemon.
|
||||
- **AUTOFS_DEV_IOCTL_REQUESTER_CMD**: `path` should be a
|
||||
name within the filesystem that has been auto-mounted on.
|
||||
arg1 is the dev number of the underlying autofs. On successful
|
||||
return, `arg1` and `arg2` will be the UID and GID of the process
|
||||
which triggered that mount.
|
||||
|
||||
- **AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD**: Check if path is a
|
||||
mountpoint of a particular type - see separate documentation for
|
||||
details.
|
||||
|
||||
- **AUTOFS_DEV_IOCTL_PROTOVER_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_READY_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_FAIL_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_CATATONIC_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_TIMEOUT_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_EXPIRE_CMD**:
|
||||
- **AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD**: These all have the same
|
||||
function as the similarly named **AUTOFS_IOC** ioctls, except
|
||||
that **FAIL** can be given an explicit error number in `arg1`
|
||||
instead of assuming `ENOENT`, and this **EXPIRE** command
|
||||
corresponds to **AUTOFS_IOC_EXPIRE_MULTI**.
|
||||
|
||||
Catatonic mode
|
||||
--------------
|
||||
|
||||
As mentioned, an autofs mount can enter "catatonic" mode. This
|
||||
happens if a write to the notification pipe fails, or if it is
|
||||
explicitly requested by an `ioctl`.
|
||||
|
||||
When entering catatonic mode, the pipe is closed and any pending
|
||||
notifications are acknowledged with the error `ENOENT`.
|
||||
|
||||
Once in catatonic mode attempts to access non-existing names will
|
||||
result in `ENOENT` while attempts to access existing directories will
|
||||
be treated in the same way as if they came from the daemon, so mount
|
||||
traps will not fire.
|
||||
|
||||
When the filesystem is mounted a _uid_ and _gid_ can be given which
|
||||
set the ownership of directories and symbolic links. When the
|
||||
filesystem is in catatonic mode, any process with a matching UID can
|
||||
create directories or symlinks in the root directory, but not in other
|
||||
directories.
|
||||
|
||||
Catatonic mode can only be left via the
|
||||
**AUTOFS_DEV_IOCTL_OPENMOUNT_CMD** ioctl on the `/dev/autofs`.
|
||||
|
||||
autofs, name spaces, and shared mounts
|
||||
--------------------------------------
|
||||
|
||||
With bind mounts and name spaces it is possible for an autofs
|
||||
filesystem to appear at multiple places in one or more filesystem
|
||||
name spaces. For this to work sensibly, the autofs filesystem should
|
||||
always be mounted "shared". e.g.
|
||||
|
||||
> `mount --make-shared /autofs/mount/point`
|
||||
|
||||
The automount daemon is only able to mange a single mount location for
|
||||
an autofs filesystem and if mounts on that are not 'shared', other
|
||||
locations will not behave as expected. In particular access to those
|
||||
other locations will likely result in the `ELOOP` error
|
||||
|
||||
> Too many levels of symbolic links
|
@ -70,6 +70,38 @@ DMA addresses types dma_addr_t:
|
||||
For printing a dma_addr_t type which can vary based on build options,
|
||||
regardless of the width of the CPU data path. Passed by reference.
|
||||
|
||||
Raw buffer as an escaped string:
|
||||
|
||||
%*pE[achnops]
|
||||
|
||||
For printing raw buffer as an escaped string. For the following buffer
|
||||
|
||||
1b 62 20 5c 43 07 22 90 0d 5d
|
||||
|
||||
few examples show how the conversion would be done (the result string
|
||||
without surrounding quotes):
|
||||
|
||||
%*pE "\eb \C\a"\220\r]"
|
||||
%*pEhp "\x1bb \C\x07"\x90\x0d]"
|
||||
%*pEa "\e\142\040\\\103\a\042\220\r\135"
|
||||
|
||||
The conversion rules are applied according to an optional combination
|
||||
of flags (see string_escape_mem() kernel documentation for the
|
||||
details):
|
||||
a - ESCAPE_ANY
|
||||
c - ESCAPE_SPECIAL
|
||||
h - ESCAPE_HEX
|
||||
n - ESCAPE_NULL
|
||||
o - ESCAPE_OCTAL
|
||||
p - ESCAPE_NP
|
||||
s - ESCAPE_SPACE
|
||||
By default ESCAPE_ANY_NP is used.
|
||||
|
||||
ESCAPE_ANY_NP is the sane choice for many cases, in particularly for
|
||||
printing SSIDs.
|
||||
|
||||
If field width is omitted the 1 byte only will be escaped.
|
||||
|
||||
Raw buffer as a hex string:
|
||||
%*ph 00 01 02 ... 3f
|
||||
%*phC 00:01:02: ... :3f
|
||||
|
@ -190,6 +190,8 @@ core_pattern is used to specify a core dumpfile pattern name.
|
||||
%% output one '%'
|
||||
%p pid
|
||||
%P global pid (init PID namespace)
|
||||
%i tid
|
||||
%I global tid (init PID namespace)
|
||||
%u uid
|
||||
%g gid
|
||||
%d dump mode, matches PR_SET_DUMPABLE and
|
||||
|
32
MAINTAINERS
32
MAINTAINERS
@ -1338,8 +1338,7 @@ ARM/SAMSUNG MOBILE MACHINE SUPPORT
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-s5pv210/mach-aquila.c
|
||||
F: arch/arm/mach-s5pv210/mach-goni.c
|
||||
F: arch/arm/mach-s5pv210/
|
||||
|
||||
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
@ -1550,6 +1549,7 @@ T: git git://git.xilinx.com/linux-xlnx.git
|
||||
S: Supported
|
||||
F: arch/arm/mach-zynq/
|
||||
F: drivers/cpuidle/cpuidle-zynq.c
|
||||
F: drivers/block/xsysace.c
|
||||
N: zynq
|
||||
N: xilinx
|
||||
F: drivers/clocksource/cadence_ttc_timer.c
|
||||
@ -1738,6 +1738,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/cadence/
|
||||
|
||||
ATMEL NAND DRIVER
|
||||
M: Josh Wu <josh.wu@atmel.com>
|
||||
L: linux-mtd@lists.infradead.org
|
||||
S: Supported
|
||||
F: drivers/mtd/nand/atmel_nand*
|
||||
|
||||
ATMEL SPI DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
S: Supported
|
||||
@ -3048,7 +3054,7 @@ M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
S: Maintained
|
||||
L: linux-media@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: linaro-mm-sig@lists.linaro.org
|
||||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
F: drivers/dma-buf/
|
||||
F: include/linux/dma-buf*
|
||||
F: include/linux/reservation.h
|
||||
@ -4297,9 +4303,8 @@ S: Maintained
|
||||
F: drivers/media/dvb-frontends/hd29l2*
|
||||
|
||||
HEWLETT-PACKARD SMART2 RAID DRIVER
|
||||
M: Chirag Kantharia <chirag.kantharia@hp.com>
|
||||
L: iss_storagedev@hp.com
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: Documentation/blockdev/cpqarray.txt
|
||||
F: drivers/block/cpqarray.*
|
||||
|
||||
@ -5300,6 +5305,13 @@ F: include/linux/lockd/
|
||||
F: include/linux/sunrpc/
|
||||
F: include/uapi/linux/sunrpc/
|
||||
|
||||
KERNEL SELFTEST FRAMEWORK
|
||||
M: Shuah Khan <shuahkh@osg.samsung.com>
|
||||
L: linux-api@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/shuah/linux-kselftest
|
||||
S: Maintained
|
||||
F: tools/testing/selftests
|
||||
|
||||
KERNEL VIRTUAL MACHINE (KVM)
|
||||
M: Gleb Natapov <gleb@kernel.org>
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
@ -5746,11 +5758,8 @@ T: git git://github.com/linux-test-project/ltp.git
|
||||
S: Maintained
|
||||
|
||||
M32R ARCHITECTURE
|
||||
M: Hirokazu Takata <takata@linux-m32r.org>
|
||||
L: linux-m32r@ml.linux-m32r.org (moderated for non-subscribers)
|
||||
L: linux-m32r-ja@ml.linux-m32r.org (in Japanese)
|
||||
W: http://www.linux-m32r.org/
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: arch/m32r/
|
||||
|
||||
M68K ARCHITECTURE
|
||||
@ -7974,7 +7983,6 @@ S: Supported
|
||||
F: drivers/mfd/sec*.c
|
||||
F: drivers/regulator/s2m*.c
|
||||
F: drivers/regulator/s5m*.c
|
||||
F: drivers/rtc/rtc-sec.c
|
||||
F: include/linux/mfd/samsung/
|
||||
|
||||
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
|
||||
@ -10315,10 +10323,6 @@ M: John Linn <John.Linn@xilinx.com>
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/xilinx/xilinx_axienet*
|
||||
|
||||
XILINX SYSTEMACE DRIVER
|
||||
S: Orphan
|
||||
F: drivers/block/xsysace.c
|
||||
|
||||
XILINX UARTLITE SERIAL DRIVER
|
||||
M: Peter Korsgaard <jacmet@sunsite.dk>
|
||||
L: linux-serial@vger.kernel.org
|
||||
|
@ -164,7 +164,7 @@
|
||||
};
|
||||
|
||||
rtc: rtc@10070000 {
|
||||
compatible = "samsung,s3c6410-rtc";
|
||||
compatible = "samsung,exynos3250-rtc";
|
||||
reg = <0x10070000 0x100>;
|
||||
interrupts = <0 73 0>, <0 74 0>;
|
||||
status = "disabled";
|
||||
|
@ -416,17 +416,17 @@ static struct pxafb_mach_info *lpd270_lcd_to_use;
|
||||
|
||||
static int __init lpd270_set_lcd(char *str)
|
||||
{
|
||||
if (!strnicmp(str, "lq057q3dc02", 11)) {
|
||||
if (!strncasecmp(str, "lq057q3dc02", 11)) {
|
||||
lpd270_lcd_to_use = &sharp_lq057q3dc02;
|
||||
} else if (!strnicmp(str, "lq121s1dg31", 11)) {
|
||||
} else if (!strncasecmp(str, "lq121s1dg31", 11)) {
|
||||
lpd270_lcd_to_use = &sharp_lq121s1dg31;
|
||||
} else if (!strnicmp(str, "lq036q1da01", 11)) {
|
||||
} else if (!strncasecmp(str, "lq036q1da01", 11)) {
|
||||
lpd270_lcd_to_use = &sharp_lq036q1da01;
|
||||
} else if (!strnicmp(str, "lq64d343", 8)) {
|
||||
} else if (!strncasecmp(str, "lq64d343", 8)) {
|
||||
lpd270_lcd_to_use = &sharp_lq64d343;
|
||||
} else if (!strnicmp(str, "lq10d368", 8)) {
|
||||
} else if (!strncasecmp(str, "lq10d368", 8)) {
|
||||
lpd270_lcd_to_use = &sharp_lq10d368;
|
||||
} else if (!strnicmp(str, "lq035q7db02-20", 14)) {
|
||||
} else if (!strncasecmp(str, "lq035q7db02-20", 14)) {
|
||||
lpd270_lcd_to_use = &sharp_lq035q7db02_20;
|
||||
} else {
|
||||
printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str);
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
|
||||
extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
|
||||
extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
|
||||
extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
|
||||
extern spinlock_t modlist_lock;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
|
||||
extern char __phys_per_cpu_start[];
|
||||
#ifdef CONFIG_SMP
|
||||
extern char __cpu0_per_cpu[];
|
||||
#endif
|
||||
|
@ -964,6 +964,7 @@ static void vgetcpu_set_mode(void)
|
||||
vgetcpu_mode = VGETCPU_LSL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
/* May not be __init: called during resume */
|
||||
static void syscall32_cpu_init(void)
|
||||
{
|
||||
@ -975,7 +976,8 @@ static void syscall32_cpu_init(void)
|
||||
|
||||
wrmsrl(MSR_CSTAR, ia32_cstar_target);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_IA32_EMULATION */
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
void enable_sep_cpu(void)
|
||||
|
@ -237,7 +237,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
|
||||
ced->max_nr_ranges++;
|
||||
|
||||
/* If crashk_low_res is not 0, another range split possible */
|
||||
if (crashk_low_res.end != 0)
|
||||
if (crashk_low_res.end)
|
||||
ced->max_nr_ranges++;
|
||||
}
|
||||
|
||||
@ -335,9 +335,11 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (crashk_low_res.end) {
|
||||
ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Exclude GART region */
|
||||
if (ced->gart_end) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/crash.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/kexec-bzimage64.h>
|
||||
|
||||
#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
|
||||
|
||||
@ -267,7 +268,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bzImage64_probe(const char *buf, unsigned long len)
|
||||
static int bzImage64_probe(const char *buf, unsigned long len)
|
||||
{
|
||||
int ret = -ENOEXEC;
|
||||
struct setup_header *header;
|
||||
@ -325,10 +326,10 @@ int bzImage64_probe(const char *buf, unsigned long len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *bzImage64_load(struct kimage *image, char *kernel,
|
||||
unsigned long kernel_len, char *initrd,
|
||||
unsigned long initrd_len, char *cmdline,
|
||||
unsigned long cmdline_len)
|
||||
static void *bzImage64_load(struct kimage *image, char *kernel,
|
||||
unsigned long kernel_len, char *initrd,
|
||||
unsigned long initrd_len, char *cmdline,
|
||||
unsigned long cmdline_len)
|
||||
{
|
||||
|
||||
struct setup_header *header;
|
||||
@ -514,7 +515,7 @@ out_free_params:
|
||||
}
|
||||
|
||||
/* This cleanup function is called after various segments have been loaded */
|
||||
int bzImage64_cleanup(void *loader_data)
|
||||
static int bzImage64_cleanup(void *loader_data)
|
||||
{
|
||||
struct bzimage64_data *ldata = loader_data;
|
||||
|
||||
@ -528,7 +529,7 @@ int bzImage64_cleanup(void *loader_data)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
|
||||
int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
|
||||
static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
|
||||
{
|
||||
bool trusted;
|
||||
int ret;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/traps.h>
|
||||
@ -499,6 +500,13 @@ void __init kvm_guest_init(void)
|
||||
#else
|
||||
kvm_guest_cpu_init();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hard lockup detection is enabled by default. Disable it, as guests
|
||||
* can get false positives too easily, for example if the host is
|
||||
* overcommitted.
|
||||
*/
|
||||
watchdog_enable_hardlockup_detector(false);
|
||||
}
|
||||
|
||||
static noinline uint32_t __kvm_cpuid_base(void)
|
||||
|
@ -86,6 +86,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
|
||||
pgprot_t prot;
|
||||
int retval;
|
||||
void __iomem *ret_addr;
|
||||
int ram_region;
|
||||
|
||||
/* Don't allow wraparound or zero size */
|
||||
last_addr = phys_addr + size - 1;
|
||||
@ -108,12 +109,23 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
|
||||
/*
|
||||
* Don't allow anybody to remap normal RAM that we're using..
|
||||
*/
|
||||
pfn = phys_addr >> PAGE_SHIFT;
|
||||
last_pfn = last_addr >> PAGE_SHIFT;
|
||||
if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
|
||||
__ioremap_check_ram) == 1)
|
||||
/* First check if whole region can be identified as RAM or not */
|
||||
ram_region = region_is_ram(phys_addr, size);
|
||||
if (ram_region > 0) {
|
||||
WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n",
|
||||
(unsigned long int)phys_addr,
|
||||
(unsigned long int)last_addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If could not be identified(-1), check page by page */
|
||||
if (ram_region < 0) {
|
||||
pfn = phys_addr >> PAGE_SHIFT;
|
||||
last_pfn = last_addr >> PAGE_SHIFT;
|
||||
if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
|
||||
__ioremap_check_ram) == 1)
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Mappings have to be page-aligned
|
||||
*/
|
||||
|
@ -463,6 +463,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __init numa_clear_kernel_node_hotplug(void)
|
||||
{
|
||||
int i, nid;
|
||||
nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
|
||||
unsigned long start, end;
|
||||
struct memblock_region *r;
|
||||
|
||||
/*
|
||||
* At this time, all memory regions reserved by memblock are
|
||||
* used by the kernel. Set the nid in memblock.reserved will
|
||||
* mark out all the nodes the kernel resides in.
|
||||
*/
|
||||
for (i = 0; i < numa_meminfo.nr_blks; i++) {
|
||||
struct numa_memblk *mb = &numa_meminfo.blk[i];
|
||||
|
||||
memblock_set_node(mb->start, mb->end - mb->start,
|
||||
&memblock.reserved, mb->nid);
|
||||
}
|
||||
|
||||
/* Mark all kernel nodes. */
|
||||
for_each_memblock(reserved, r)
|
||||
node_set(r->nid, numa_kernel_nodes);
|
||||
|
||||
/* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
|
||||
for (i = 0; i < numa_meminfo.nr_blks; i++) {
|
||||
nid = numa_meminfo.blk[i].nid;
|
||||
if (!node_isset(nid, numa_kernel_nodes))
|
||||
continue;
|
||||
|
||||
start = numa_meminfo.blk[i].start;
|
||||
end = numa_meminfo.blk[i].end;
|
||||
|
||||
memblock_clear_hotplug(start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init numa_register_memblks(struct numa_meminfo *mi)
|
||||
{
|
||||
unsigned long uninitialized_var(pfn_align);
|
||||
@ -480,6 +516,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
|
||||
&memblock.memory, mb->nid);
|
||||
}
|
||||
|
||||
/*
|
||||
* At very early time, the kernel have to use some memory such as
|
||||
* loading the kernel image. We cannot prevent this anyway. So any
|
||||
* node the kernel resides in should be un-hotpluggable.
|
||||
*
|
||||
* And when we come here, alloc node data won't fail.
|
||||
*/
|
||||
numa_clear_kernel_node_hotplug();
|
||||
|
||||
/*
|
||||
* If sections array is gonna be used for pfn -> nid mapping, check
|
||||
* whether its granularity is fine enough.
|
||||
@ -548,41 +593,6 @@ static void __init numa_init_array(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init numa_clear_kernel_node_hotplug(void)
|
||||
{
|
||||
int i, nid;
|
||||
nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
|
||||
unsigned long start, end;
|
||||
struct memblock_region *r;
|
||||
|
||||
/*
|
||||
* At this time, all memory regions reserved by memblock are
|
||||
* used by the kernel. Set the nid in memblock.reserved will
|
||||
* mark out all the nodes the kernel resides in.
|
||||
*/
|
||||
for (i = 0; i < numa_meminfo.nr_blks; i++) {
|
||||
struct numa_memblk *mb = &numa_meminfo.blk[i];
|
||||
memblock_set_node(mb->start, mb->end - mb->start,
|
||||
&memblock.reserved, mb->nid);
|
||||
}
|
||||
|
||||
/* Mark all kernel nodes. */
|
||||
for_each_memblock(reserved, r)
|
||||
node_set(r->nid, numa_kernel_nodes);
|
||||
|
||||
/* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
|
||||
for (i = 0; i < numa_meminfo.nr_blks; i++) {
|
||||
nid = numa_meminfo.blk[i].nid;
|
||||
if (!node_isset(nid, numa_kernel_nodes))
|
||||
continue;
|
||||
|
||||
start = numa_meminfo.blk[i].start;
|
||||
end = numa_meminfo.blk[i].end;
|
||||
|
||||
memblock_clear_hotplug(start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init numa_init(int (*init_func)(void))
|
||||
{
|
||||
int i;
|
||||
@ -637,15 +647,6 @@ static int __init numa_init(int (*init_func)(void))
|
||||
}
|
||||
numa_init_array();
|
||||
|
||||
/*
|
||||
* At very early time, the kernel have to use some memory such as
|
||||
* loading the kernel image. We cannot prevent this anyway. So any
|
||||
* node the kernel resides in should be un-hotpluggable.
|
||||
*
|
||||
* And when we come here, numa_init() won't fail.
|
||||
*/
|
||||
numa_clear_kernel_node_hotplug();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,9 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
|
||||
|
||||
targets += kexec-purgatory.c
|
||||
|
||||
CMD_BIN2C = $(objtree)/scripts/basic/bin2c
|
||||
quiet_cmd_bin2c = BIN2C $@
|
||||
cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c
|
||||
cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
|
||||
|
||||
$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
|
||||
$(call if_changed,bin2c)
|
||||
|
@ -14,11 +14,14 @@ struct dma_coherent_mem {
|
||||
int size;
|
||||
int flags;
|
||||
unsigned long *bitmap;
|
||||
spinlock_t spinlock;
|
||||
};
|
||||
|
||||
int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
|
||||
dma_addr_t device_addr, size_t size, int flags)
|
||||
static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr,
|
||||
size_t size, int flags,
|
||||
struct dma_coherent_mem **mem)
|
||||
{
|
||||
struct dma_coherent_mem *dma_mem = NULL;
|
||||
void __iomem *mem_base = NULL;
|
||||
int pages = size >> PAGE_SHIFT;
|
||||
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
|
||||
@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
|
||||
goto out;
|
||||
if (!size)
|
||||
goto out;
|
||||
if (dev->dma_mem)
|
||||
goto out;
|
||||
|
||||
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
|
||||
|
||||
mem_base = ioremap(phys_addr, size);
|
||||
if (!mem_base)
|
||||
goto out;
|
||||
|
||||
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
|
||||
if (!dev->dma_mem)
|
||||
dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
|
||||
if (!dma_mem)
|
||||
goto out;
|
||||
dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
||||
if (!dma_mem->bitmap)
|
||||
goto out;
|
||||
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
||||
if (!dev->dma_mem->bitmap)
|
||||
goto free1_out;
|
||||
|
||||
dev->dma_mem->virt_base = mem_base;
|
||||
dev->dma_mem->device_base = device_addr;
|
||||
dev->dma_mem->pfn_base = PFN_DOWN(phys_addr);
|
||||
dev->dma_mem->size = pages;
|
||||
dev->dma_mem->flags = flags;
|
||||
dma_mem->virt_base = mem_base;
|
||||
dma_mem->device_base = device_addr;
|
||||
dma_mem->pfn_base = PFN_DOWN(phys_addr);
|
||||
dma_mem->size = pages;
|
||||
dma_mem->flags = flags;
|
||||
spin_lock_init(&dma_mem->spinlock);
|
||||
|
||||
*mem = dma_mem;
|
||||
|
||||
if (flags & DMA_MEMORY_MAP)
|
||||
return DMA_MEMORY_MAP;
|
||||
|
||||
return DMA_MEMORY_IO;
|
||||
|
||||
free1_out:
|
||||
kfree(dev->dma_mem);
|
||||
out:
|
||||
out:
|
||||
kfree(dma_mem);
|
||||
if (mem_base)
|
||||
iounmap(mem_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
|
||||
{
|
||||
if (!mem)
|
||||
return;
|
||||
iounmap(mem->virt_base);
|
||||
kfree(mem->bitmap);
|
||||
kfree(mem);
|
||||
}
|
||||
|
||||
static int dma_assign_coherent_memory(struct device *dev,
|
||||
struct dma_coherent_mem *mem)
|
||||
{
|
||||
if (dev->dma_mem)
|
||||
return -EBUSY;
|
||||
|
||||
dev->dma_mem = mem;
|
||||
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
|
||||
dma_addr_t device_addr, size_t size, int flags)
|
||||
{
|
||||
struct dma_coherent_mem *mem;
|
||||
int ret;
|
||||
|
||||
ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags,
|
||||
&mem);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
if (dma_assign_coherent_memory(dev, mem) == 0)
|
||||
return ret;
|
||||
|
||||
dma_release_coherent_memory(mem);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_declare_coherent_memory);
|
||||
|
||||
void dma_release_declared_memory(struct device *dev)
|
||||
@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev)
|
||||
|
||||
if (!mem)
|
||||
return;
|
||||
dma_release_coherent_memory(mem);
|
||||
dev->dma_mem = NULL;
|
||||
iounmap(mem->virt_base);
|
||||
kfree(mem->bitmap);
|
||||
kfree(mem);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_release_declared_memory);
|
||||
|
||||
@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
|
||||
dma_addr_t device_addr, size_t size)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev->dma_mem;
|
||||
unsigned long flags;
|
||||
int pos, err;
|
||||
|
||||
size += device_addr & ~PAGE_MASK;
|
||||
@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
|
||||
if (!mem)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
spin_lock_irqsave(&mem->spinlock, flags);
|
||||
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
|
||||
err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
|
||||
if (err != 0)
|
||||
return ERR_PTR(err);
|
||||
return mem->virt_base + (pos << PAGE_SHIFT);
|
||||
@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
||||
{
|
||||
struct dma_coherent_mem *mem;
|
||||
int order = get_order(size);
|
||||
unsigned long flags;
|
||||
int pageno;
|
||||
|
||||
if (!dev)
|
||||
@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
||||
return 0;
|
||||
|
||||
*ret = NULL;
|
||||
spin_lock_irqsave(&mem->spinlock, flags);
|
||||
|
||||
if (unlikely(size > (mem->size << PAGE_SHIFT)))
|
||||
goto err;
|
||||
@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
||||
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
|
||||
*ret = mem->virt_base + (pageno << PAGE_SHIFT);
|
||||
memset(*ret, 0, size);
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
/*
|
||||
* In the case where the allocation can not be satisfied from the
|
||||
* per-device area, try to fall back to generic memory if the
|
||||
@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
|
||||
if (mem && vaddr >= mem->virt_base && vaddr <
|
||||
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
||||
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mem->spinlock, flags);
|
||||
bitmap_release_region(mem->bitmap, page, order);
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_mmap_from_coherent);
|
||||
|
||||
/*
|
||||
* Support for reserved memory regions defined in device tree
|
||||
*/
|
||||
#ifdef CONFIG_OF_RESERVED_MEM
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
||||
static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
|
||||
{
|
||||
struct dma_coherent_mem *mem = rmem->priv;
|
||||
|
||||
if (!mem &&
|
||||
dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
|
||||
DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE,
|
||||
&mem) != DMA_MEMORY_MAP) {
|
||||
pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
|
||||
&rmem->base, (unsigned long)rmem->size / SZ_1M);
|
||||
return -ENODEV;
|
||||
}
|
||||
rmem->priv = mem;
|
||||
dma_assign_coherent_memory(dev, mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rmem_dma_device_release(struct reserved_mem *rmem,
|
||||
struct device *dev)
|
||||
{
|
||||
dev->dma_mem = NULL;
|
||||
}
|
||||
|
||||
static const struct reserved_mem_ops rmem_dma_ops = {
|
||||
.device_init = rmem_dma_device_init,
|
||||
.device_release = rmem_dma_device_release,
|
||||
};
|
||||
|
||||
static int __init rmem_dma_setup(struct reserved_mem *rmem)
|
||||
{
|
||||
unsigned long node = rmem->fdt_node;
|
||||
|
||||
if (of_get_flat_dt_prop(node, "reusable", NULL))
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
if (!of_get_flat_dt_prop(node, "no-map", NULL)) {
|
||||
pr_err("Reserved memory: regions without no-map are not yet supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
rmem->ops = &rmem_dma_ops;
|
||||
pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n",
|
||||
&rmem->base, (unsigned long)rmem->size / SZ_1M);
|
||||
return 0;
|
||||
}
|
||||
RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
|
||||
#endif
|
||||
|
@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
|
||||
{
|
||||
return cma_release(dev_get_cma_area(dev), pages, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for reserved memory regions defined in device tree
|
||||
*/
|
||||
#ifdef CONFIG_OF_RESERVED_MEM
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) fmt
|
||||
|
||||
static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
|
||||
{
|
||||
dev_set_cma_area(dev, rmem->priv);
|
||||
}
|
||||
|
||||
static void rmem_cma_device_release(struct reserved_mem *rmem,
|
||||
struct device *dev)
|
||||
{
|
||||
dev_set_cma_area(dev, NULL);
|
||||
}
|
||||
|
||||
static const struct reserved_mem_ops rmem_cma_ops = {
|
||||
.device_init = rmem_cma_device_init,
|
||||
.device_release = rmem_cma_device_release,
|
||||
};
|
||||
|
||||
static int __init rmem_cma_setup(struct reserved_mem *rmem)
|
||||
{
|
||||
phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
|
||||
phys_addr_t mask = align - 1;
|
||||
unsigned long node = rmem->fdt_node;
|
||||
struct cma *cma;
|
||||
int err;
|
||||
|
||||
if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
|
||||
of_get_flat_dt_prop(node, "no-map", NULL))
|
||||
return -EINVAL;
|
||||
|
||||
if ((rmem->base & mask) || (rmem->size & mask)) {
|
||||
pr_err("Reserved memory: incorrect alignment of CMA region\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
|
||||
if (err) {
|
||||
pr_err("Reserved memory: unable to setup CMA region\n");
|
||||
return err;
|
||||
}
|
||||
/* Architecture specific contiguous memory fixup. */
|
||||
dma_contiguous_early_fixup(rmem->base, rmem->size);
|
||||
|
||||
if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
|
||||
dma_contiguous_set_default(cma);
|
||||
|
||||
rmem->ops = &rmem_cma_ops;
|
||||
rmem->priv = cma;
|
||||
|
||||
pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",
|
||||
&rmem->base, (unsigned long)rmem->size / SZ_1M);
|
||||
|
||||
return 0;
|
||||
}
|
||||
RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);
|
||||
#endif
|
||||
|
@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686
|
||||
---help---
|
||||
This driver supports Maxim 77686 crystal oscillator clock.
|
||||
|
||||
config COMMON_CLK_RK808
|
||||
tristate "Clock driver for RK808"
|
||||
depends on MFD_RK808
|
||||
---help---
|
||||
This driver supports RK808 crystal oscillator clock. These
|
||||
multi-function devices have two fixed-rate oscillators,
|
||||
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
|
||||
by control register.
|
||||
|
||||
config COMMON_CLK_SI5351
|
||||
tristate "Clock driver for SiLabs 5351A/B/C"
|
||||
depends on I2C
|
||||
|
@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
|
||||
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
|
||||
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
|
||||
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
|
||||
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
|
||||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
||||
|
170
drivers/clk/clk-rk808.c
Normal file
170
drivers/clk/clk-rk808.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Clkout driver for Rockchip RK808
|
||||
*
|
||||
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* Author:Chris Zhong <zyw@rock-chips.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/rk808.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#define RK808_NR_OUTPUT 2
|
||||
|
||||
struct rk808_clkout {
|
||||
struct rk808 *rk808;
|
||||
struct clk_onecell_data clk_data;
|
||||
struct clk_hw clkout1_hw;
|
||||
struct clk_hw clkout2_hw;
|
||||
};
|
||||
|
||||
static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return 32768;
|
||||
}
|
||||
|
||||
static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct rk808_clkout *rk808_clkout = container_of(hw,
|
||||
struct rk808_clkout,
|
||||
clkout2_hw);
|
||||
struct rk808 *rk808 = rk808_clkout->rk808;
|
||||
|
||||
return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
|
||||
CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
|
||||
}
|
||||
|
||||
static int rk808_clkout2_prepare(struct clk_hw *hw)
|
||||
{
|
||||
return rk808_clkout2_enable(hw, true);
|
||||
}
|
||||
|
||||
static void rk808_clkout2_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
rk808_clkout2_enable(hw, false);
|
||||
}
|
||||
|
||||
static int rk808_clkout2_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct rk808_clkout *rk808_clkout = container_of(hw,
|
||||
struct rk808_clkout,
|
||||
clkout2_hw);
|
||||
struct rk808 *rk808 = rk808_clkout->rk808;
|
||||
uint32_t val;
|
||||
|
||||
int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (val & CLK32KOUT2_EN) ? 1 : 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops rk808_clkout1_ops = {
|
||||
.recalc_rate = rk808_clkout_recalc_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops rk808_clkout2_ops = {
|
||||
.prepare = rk808_clkout2_prepare,
|
||||
.unprepare = rk808_clkout2_unprepare,
|
||||
.is_prepared = rk808_clkout2_is_prepared,
|
||||
.recalc_rate = rk808_clkout_recalc_rate,
|
||||
};
|
||||
|
||||
static int rk808_clkout_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct i2c_client *client = rk808->i2c;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
struct clk_init_data init = {};
|
||||
struct clk **clk_table;
|
||||
struct rk808_clkout *rk808_clkout;
|
||||
|
||||
rk808_clkout = devm_kzalloc(&client->dev,
|
||||
sizeof(*rk808_clkout), GFP_KERNEL);
|
||||
if (!rk808_clkout)
|
||||
return -ENOMEM;
|
||||
|
||||
rk808_clkout->rk808 = rk808;
|
||||
|
||||
clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT,
|
||||
sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return -ENOMEM;
|
||||
|
||||
init.flags = CLK_IS_ROOT;
|
||||
init.parent_names = NULL;
|
||||
init.num_parents = 0;
|
||||
init.name = "rk808-clkout1";
|
||||
init.ops = &rk808_clkout1_ops;
|
||||
rk808_clkout->clkout1_hw.init = &init;
|
||||
|
||||
/* optional override of the clockname */
|
||||
of_property_read_string_index(node, "clock-output-names",
|
||||
0, &init.name);
|
||||
|
||||
clk_table[0] = devm_clk_register(&client->dev,
|
||||
&rk808_clkout->clkout1_hw);
|
||||
if (IS_ERR(clk_table[0]))
|
||||
return PTR_ERR(clk_table[0]);
|
||||
|
||||
init.name = "rk808-clkout2";
|
||||
init.ops = &rk808_clkout2_ops;
|
||||
rk808_clkout->clkout2_hw.init = &init;
|
||||
|
||||
/* optional override of the clockname */
|
||||
of_property_read_string_index(node, "clock-output-names",
|
||||
1, &init.name);
|
||||
|
||||
clk_table[1] = devm_clk_register(&client->dev,
|
||||
&rk808_clkout->clkout2_hw);
|
||||
if (IS_ERR(clk_table[1]))
|
||||
return PTR_ERR(clk_table[1]);
|
||||
|
||||
rk808_clkout->clk_data.clks = clk_table;
|
||||
rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT;
|
||||
|
||||
return of_clk_add_provider(node, of_clk_src_onecell_get,
|
||||
&rk808_clkout->clk_data);
|
||||
}
|
||||
|
||||
static int rk808_clkout_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct i2c_client *client = rk808->i2c;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
|
||||
of_clk_del_provider(node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk808_clkout_driver = {
|
||||
.probe = rk808_clkout_probe,
|
||||
.remove = rk808_clkout_remove,
|
||||
.driver = {
|
||||
.name = "rk808-clkout",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rk808_clkout_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
|
||||
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:rk808-clkout");
|
@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
|
||||
int ret, rc;
|
||||
|
||||
p = name;
|
||||
if (strnicmp(p, "0x", 2) == 0)
|
||||
if (strncasecmp(p, "0x", 2) == 0)
|
||||
p += 2;
|
||||
ret = -EINVAL;
|
||||
len = strlen(p);
|
||||
|
@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
|
||||
/* if we find something consistent, stay with that assumption
|
||||
* at least M09 won't send 3 bytes here
|
||||
*/
|
||||
if (!(strnicmp(rdbuf + 1, "EP0", 3))) {
|
||||
if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
|
||||
tsdata->version = M06;
|
||||
|
||||
/* remove last '$' end marker */
|
||||
|
@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev)
|
||||
r592_set_mode(dev, dev->parallel_mode);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Disable all hardware interrupts */
|
||||
static void r592_clear_interrupts(struct r592_device *dev)
|
||||
{
|
||||
@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev)
|
||||
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK);
|
||||
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tests if there is an CRC error */
|
||||
static int r592_test_io_error(struct r592_device *dev)
|
||||
|
@ -454,7 +454,7 @@ exit_done:
|
||||
|
||||
name = &p[str_table + name_id];
|
||||
|
||||
if (strnicmp(aconf->action, name, strlen(name)) == 0) {
|
||||
if (strncasecmp(aconf->action, name, strlen(name)) == 0) {
|
||||
action_found = 1;
|
||||
current_proc =
|
||||
get_unaligned_be32(&p[action_table +
|
||||
@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size,
|
||||
key_ptr = &p[note_strings +
|
||||
get_unaligned_be32(
|
||||
&p[note_table + (8 * i)])];
|
||||
if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) &&
|
||||
if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) &&
|
||||
(key != NULL)) {
|
||||
status = 0;
|
||||
|
||||
|
@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
|
||||
local_info_t *local = m->private;
|
||||
struct list_head *ptr = v;
|
||||
struct hostap_bss_info *bss;
|
||||
int i;
|
||||
|
||||
if (ptr == &local->bss_list) {
|
||||
seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
|
||||
@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
|
||||
bss->bssid, bss->last_update,
|
||||
bss->count, bss->capab_info);
|
||||
|
||||
for (i = 0; i < bss->ssid_len; i++)
|
||||
seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
|
||||
bss->ssid[i] : '_');
|
||||
seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid);
|
||||
|
||||
seq_putc(m, '\t');
|
||||
seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid);
|
||||
|
@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
|
||||
u32 chan;
|
||||
char *txratename;
|
||||
u8 bssid[ETH_ALEN];
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/*
|
||||
* TBD: BSSID is usually 00:00:00:00:00:00 here and not
|
||||
@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
|
||||
break;
|
||||
}
|
||||
|
||||
IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
|
||||
priv->net_dev->name, print_ssid(ssid, essid, essid_len),
|
||||
IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n",
|
||||
priv->net_dev->name, essid_len, essid,
|
||||
txratename, chan, bssid);
|
||||
|
||||
/* now we copy read ssid into dev */
|
||||
@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
|
||||
.host_command_length = ssid_len
|
||||
};
|
||||
int err;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
|
||||
IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid);
|
||||
|
||||
if (ssid_len)
|
||||
memcpy(cmd.host_command_parameters, essid, ssid_len);
|
||||
@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
|
||||
|
||||
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
|
||||
"disassociated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len),
|
||||
"disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
|
||||
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
|
||||
@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
|
||||
char *essid = ""; /* ANY */
|
||||
int length = 0;
|
||||
int err = 0;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
if (!(priv->status & STATUS_INITIALIZED)) {
|
||||
@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
|
||||
goto done;
|
||||
}
|
||||
|
||||
IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
|
||||
print_ssid(ssid, essid, length), length);
|
||||
IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length);
|
||||
|
||||
priv->essid_len = length;
|
||||
memcpy(priv->essid, essid, priv->essid_len);
|
||||
@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/* If we are associated, trying to associate, or have a statically
|
||||
* configured ESSID then return that; otherwise return ANY */
|
||||
if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
|
||||
IPW_DEBUG_WX("Getting essid: '%s'\n",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len));
|
||||
IPW_DEBUG_WX("Getting essid: '%*pE'\n",
|
||||
priv->essid_len, priv->essid);
|
||||
memcpy(extra, priv->essid, priv->essid_len);
|
||||
wrqu->essid.length = priv->essid_len;
|
||||
wrqu->essid.flags = 1; /* active */
|
||||
|
@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv)
|
||||
static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
struct ipw_rx_notification *notif)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
u16 size = le16_to_cpu(notif->size);
|
||||
|
||||
IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
|
||||
@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
case CMAS_ASSOCIATED:{
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
|
||||
IPW_DL_ASSOC,
|
||||
"associated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len),
|
||||
"associated: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
|
||||
switch (priv->ieee->iw_mode) {
|
||||
@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
IPW_DEBUG(IPW_DL_NOTIF |
|
||||
IPW_DL_STATE |
|
||||
IPW_DL_ASSOC,
|
||||
"deauthenticated: '%s' "
|
||||
"%pM"
|
||||
": (0x%04X) - %s\n",
|
||||
print_ssid(ssid,
|
||||
priv->
|
||||
essid,
|
||||
priv->
|
||||
essid_len),
|
||||
"deauthenticated: '%*pE' %pM: (0x%04X) - %s\n",
|
||||
priv->essid_len,
|
||||
priv->essid,
|
||||
priv->bssid,
|
||||
le16_to_cpu(auth->status),
|
||||
ipw_get_status_code
|
||||
@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
|
||||
IPW_DL_ASSOC,
|
||||
"authenticated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len),
|
||||
"authenticated: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
break;
|
||||
}
|
||||
@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
|
||||
IPW_DL_ASSOC,
|
||||
"disassociated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len),
|
||||
"disassociated: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
|
||||
priv->status &=
|
||||
@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
switch (auth->state) {
|
||||
case CMAS_AUTHENTICATED:
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
|
||||
"authenticated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len),
|
||||
"authenticated: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
priv->status |= STATUS_AUTH;
|
||||
break;
|
||||
@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
}
|
||||
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
|
||||
IPW_DL_ASSOC,
|
||||
"deauthenticated: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len),
|
||||
"deauthenticated: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid,
|
||||
priv->bssid);
|
||||
|
||||
priv->status &= ~(STATUS_ASSOCIATING |
|
||||
@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
int roaming)
|
||||
{
|
||||
struct ipw_supported_rates rates;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/* Verify that this network's capability is compatible with the
|
||||
* current mode (AdHoc or Infrastructure) */
|
||||
if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
|
||||
!(network->capability & WLAN_CAPABILITY_IBSS))) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
|
||||
"capability mismatch.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
if ((network->ssid_len != match->network->ssid_len) ||
|
||||
memcmp(network->ssid, match->network->ssid,
|
||||
network->ssid_len)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of non-network ESSID.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
((network->ssid_len != priv->essid_len) ||
|
||||
memcmp(network->ssid, priv->essid,
|
||||
min(network->ssid_len, priv->essid_len)))) {
|
||||
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
|
||||
strlcpy(escaped,
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
sizeof(escaped));
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of ESSID mismatch: '%s'.\n",
|
||||
escaped, network->bssid,
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len));
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid, priv->essid_len,
|
||||
priv->essid);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
* testing everything else. */
|
||||
|
||||
if (network->time_stamp[0] < match->network->time_stamp[0]) {
|
||||
IPW_DEBUG_MERGE("Network '%s excluded because newer than "
|
||||
"current network.\n",
|
||||
print_ssid(ssid, match->network->ssid,
|
||||
match->network->ssid_len));
|
||||
IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
|
||||
match->network->ssid_len, match->network->ssid);
|
||||
return 0;
|
||||
} else if (network->time_stamp[1] < match->network->time_stamp[1]) {
|
||||
IPW_DEBUG_MERGE("Network '%s excluded because newer than "
|
||||
"current network.\n",
|
||||
print_ssid(ssid, match->network->ssid,
|
||||
match->network->ssid_len));
|
||||
IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
|
||||
match->network->ssid_len, match->network->ssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now go through and see if the requested network is valid... */
|
||||
if (priv->ieee->scan_age != 0 &&
|
||||
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of age: %ums.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
jiffies_to_msecs(jiffies -
|
||||
network->last_scanned));
|
||||
@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
|
||||
if ((priv->config & CFG_STATIC_CHANNEL) &&
|
||||
(network->channel != priv->channel)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of channel mismatch: %d != %d.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
network->channel, priv->channel);
|
||||
return 0;
|
||||
@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
/* Verify privacy compatibility */
|
||||
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
|
||||
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of privacy mismatch: %s != %s.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
priv->
|
||||
capability & CAP_PRIVACY_ON ? "on" : "off",
|
||||
@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
}
|
||||
|
||||
if (ether_addr_equal(network->bssid, priv->bssid)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of the same BSSID match: %pM"
|
||||
".\n", print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
network->bssid,
|
||||
priv->bssid);
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid, priv->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Filter out any incompatible freq / mode combinations */
|
||||
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of invalid frequency/mode "
|
||||
"combination.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
/* Ensure that the rates supported by the driver are compatible with
|
||||
* this AP, including verification of basic rates (mandatory) */
|
||||
if (!ipw_compatible_rates(priv, network, &rates)) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because configured rate mask excludes "
|
||||
"AP mandatory rate.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rates.num_rates == 0) {
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
|
||||
"because of no compatible rates.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
|
||||
/* Set up 'new' AP to this network */
|
||||
ipw_copy_rates(&match->rates, &rates);
|
||||
match->network = network;
|
||||
IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
|
||||
print_ssid(ssid, network->ssid, network->ssid_len),
|
||||
network->bssid);
|
||||
IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n",
|
||||
network->ssid_len, network->ssid, network->bssid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ipw_merge_adhoc_network(struct work_struct *work)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
struct ipw_priv *priv =
|
||||
container_of(work, struct ipw_priv, merge_networks);
|
||||
struct libipw_network *network = NULL;
|
||||
@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work)
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
|
||||
IPW_DEBUG_MERGE("remove network %s\n",
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len));
|
||||
IPW_DEBUG_MERGE("remove network %*pE\n",
|
||||
priv->essid_len, priv->essid);
|
||||
ipw_remove_current_network(priv);
|
||||
}
|
||||
|
||||
@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
struct libipw_network *network, int roaming)
|
||||
{
|
||||
struct ipw_supported_rates rates;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/* Verify that this network's capability is compatible with the
|
||||
* current mode (AdHoc or Infrastructure) */
|
||||
@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
!(network->capability & WLAN_CAPABILITY_ESS)) ||
|
||||
(priv->ieee->iw_mode == IW_MODE_ADHOC &&
|
||||
!(network->capability & WLAN_CAPABILITY_IBSS))) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
|
||||
"capability mismatch.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
if ((network->ssid_len != match->network->ssid_len) ||
|
||||
memcmp(network->ssid, match->network->ssid,
|
||||
network->ssid_len)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of non-network ESSID.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
((network->ssid_len != priv->essid_len) ||
|
||||
memcmp(network->ssid, priv->essid,
|
||||
min(network->ssid_len, priv->essid_len)))) {
|
||||
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
strlcpy(escaped,
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
sizeof(escaped));
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of ESSID mismatch: '%s'.\n",
|
||||
escaped, network->bssid,
|
||||
print_ssid(ssid, priv->essid,
|
||||
priv->essid_len));
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid, priv->essid_len,
|
||||
priv->essid);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
/* If the old network rate is better than this one, don't bother
|
||||
* testing everything else. */
|
||||
if (match->network && match->network->stats.rssi > network->stats.rssi) {
|
||||
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
strlcpy(escaped,
|
||||
print_ssid(ssid, network->ssid, network->ssid_len),
|
||||
sizeof(escaped));
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
|
||||
"'%s (%pM)' has a stronger signal.\n",
|
||||
escaped, network->bssid,
|
||||
print_ssid(ssid, match->network->ssid,
|
||||
match->network->ssid_len),
|
||||
match->network->bssid);
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid, match->network->ssid_len,
|
||||
match->network->ssid, match->network->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
* last 3 seconds, do not try and associate again... */
|
||||
if (network->last_associate &&
|
||||
time_after(network->last_associate + (HZ * 3UL), jiffies)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of storming (%ums since last "
|
||||
"assoc attempt).\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
jiffies_to_msecs(jiffies -
|
||||
network->last_associate));
|
||||
@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
/* Now go through and see if the requested network is valid... */
|
||||
if (priv->ieee->scan_age != 0 &&
|
||||
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of age: %ums.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
jiffies_to_msecs(jiffies -
|
||||
network->last_scanned));
|
||||
@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
|
||||
if ((priv->config & CFG_STATIC_CHANNEL) &&
|
||||
(network->channel != priv->channel)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of channel mismatch: %d != %d.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
network->channel, priv->channel);
|
||||
return 0;
|
||||
@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
/* Verify privacy compatibility */
|
||||
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
|
||||
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of privacy mismatch: %s != %s.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
priv->capability & CAP_PRIVACY_ON ? "on" :
|
||||
"off",
|
||||
@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
|
||||
if ((priv->config & CFG_STATIC_BSSID) &&
|
||||
!ether_addr_equal(network->bssid, priv->bssid)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of BSSID mismatch: %pM.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid, priv->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Filter out any incompatible freq / mode combinations */
|
||||
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of invalid frequency/mode "
|
||||
"combination.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Filter out invalid channel in current GEO */
|
||||
if (!libipw_is_valid_channel(priv->ieee, network->channel)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of invalid channel in current GEO\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
/* Ensure that the rates supported by the driver are compatible with
|
||||
* this AP, including verification of basic rates (mandatory) */
|
||||
if (!ipw_compatible_rates(priv, network, &rates)) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because configured rate mask excludes "
|
||||
"AP mandatory rate.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rates.num_rates == 0) {
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
|
||||
"because of no compatible rates.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 0;
|
||||
}
|
||||
@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv,
|
||||
ipw_copy_rates(&match->rates, &rates);
|
||||
match->network = network;
|
||||
|
||||
IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
|
||||
print_ssid(ssid, network->ssid, network->ssid_len),
|
||||
network->bssid);
|
||||
IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n",
|
||||
network->ssid_len, network->ssid, network->bssid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work)
|
||||
|
||||
static void ipw_debug_config(struct ipw_priv *priv)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
IPW_DEBUG_INFO("Scan completed, no valid APs matched "
|
||||
"[CFG 0x%08X]\n", priv->config);
|
||||
if (priv->config & CFG_STATIC_CHANNEL)
|
||||
@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv)
|
||||
else
|
||||
IPW_DEBUG_INFO("Channel unlocked.\n");
|
||||
if (priv->config & CFG_STATIC_ESSID)
|
||||
IPW_DEBUG_INFO("ESSID locked to '%s'\n",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len));
|
||||
IPW_DEBUG_INFO("ESSID locked to '%*pE'\n",
|
||||
priv->essid_len, priv->essid);
|
||||
else
|
||||
IPW_DEBUG_INFO("ESSID unlocked.\n");
|
||||
if (priv->config & CFG_STATIC_BSSID)
|
||||
@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
|
||||
struct ipw_supported_rates *rates, int roaming)
|
||||
{
|
||||
int err;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
if (priv->config & CFG_FIXED_RATE)
|
||||
ipw_set_fixed_rate(priv, network->mode);
|
||||
@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
|
||||
priv->assoc_request.capability &=
|
||||
~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
||||
|
||||
IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, "
|
||||
"802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
|
||||
IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
|
||||
roaming ? "Rea" : "A",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len),
|
||||
priv->essid_len, priv->essid,
|
||||
network->channel,
|
||||
ipw_modes[priv->assoc_request.ieee_mode],
|
||||
rates->num_rates,
|
||||
@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv,
|
||||
return err;
|
||||
}
|
||||
|
||||
IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len),
|
||||
priv->bssid);
|
||||
IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n",
|
||||
priv->essid_len, priv->essid, priv->bssid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -7645,7 +7555,6 @@ static int ipw_associate(void *data)
|
||||
struct ipw_supported_rates *rates;
|
||||
struct list_head *element;
|
||||
unsigned long flags;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
|
||||
IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
|
||||
@ -7704,10 +7613,8 @@ static int ipw_associate(void *data)
|
||||
/* If there are no more slots, expire the oldest */
|
||||
list_del(&oldest->list);
|
||||
target = oldest;
|
||||
IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
|
||||
"network list.\n",
|
||||
print_ssid(ssid, target->ssid,
|
||||
target->ssid_len),
|
||||
IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n",
|
||||
target->ssid_len, target->ssid,
|
||||
target->bssid);
|
||||
list_add_tail(&target->list,
|
||||
&priv->ieee->network_free_list);
|
||||
@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
|
||||
{
|
||||
struct ipw_priv *priv = libipw_priv(dev);
|
||||
int length;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
|
||||
print_ssid(ssid, extra, length), length);
|
||||
IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length);
|
||||
|
||||
priv->essid_len = length;
|
||||
memcpy(priv->essid, extra, priv->essid_len);
|
||||
@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw_priv *priv = libipw_priv(dev);
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/* If we are associated, trying to associate, or have a statically
|
||||
* configured ESSID then return that; otherwise return ANY */
|
||||
mutex_lock(&priv->mutex);
|
||||
if (priv->config & CFG_STATIC_ESSID ||
|
||||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
|
||||
IPW_DEBUG_WX("Getting essid: '%s'\n",
|
||||
print_ssid(ssid, priv->essid, priv->essid_len));
|
||||
IPW_DEBUG_WX("Getting essid: '%*pE'\n",
|
||||
priv->essid_len, priv->essid);
|
||||
memcpy(extra, priv->essid, priv->essid_len);
|
||||
wrqu->essid.length = priv->essid_len;
|
||||
wrqu->essid.flags = 1; /* active */
|
||||
|
@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element
|
||||
*info_element, u16 length,
|
||||
struct libipw_network *network)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
u8 i;
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
char rates_str[64];
|
||||
@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element
|
||||
memset(network->ssid + network->ssid_len, 0,
|
||||
IW_ESSID_MAX_SIZE - network->ssid_len);
|
||||
|
||||
LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
network->ssid_len);
|
||||
LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->ssid_len);
|
||||
break;
|
||||
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
|
||||
struct libipw_network *network,
|
||||
struct libipw_rx_stats *stats)
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
network->qos_data.active = 0;
|
||||
network->qos_data.supported = 0;
|
||||
network->qos_data.param_count = 0;
|
||||
@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
|
||||
}
|
||||
|
||||
if (network->mode == 0) {
|
||||
LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' "
|
||||
"network.\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
network->bssid);
|
||||
LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device
|
||||
struct libipw_info_element *info_element = beacon->info_element;
|
||||
#endif
|
||||
unsigned long flags;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
LIBIPW_DEBUG_SCAN("'%s' (%pM"
|
||||
"): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
|
||||
print_ssid(ssid, info_element->data, info_element->len),
|
||||
LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
|
||||
info_element->len, info_element->data,
|
||||
beacon->header.addr3,
|
||||
(beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
|
||||
(beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
|
||||
@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device
|
||||
(beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
|
||||
|
||||
if (libipw_network_init(ieee, beacon, &network, stats)) {
|
||||
LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
|
||||
print_ssid(ssid, info_element->data,
|
||||
info_element->len),
|
||||
beacon->header.addr3,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n",
|
||||
info_element->len, info_element->data,
|
||||
beacon->header.addr3,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device
|
||||
/* If there are no more slots, expire the oldest */
|
||||
list_del(&oldest->list);
|
||||
target = oldest;
|
||||
LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from "
|
||||
"network list.\n",
|
||||
print_ssid(ssid, target->ssid,
|
||||
target->ssid_len),
|
||||
target->bssid);
|
||||
LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
|
||||
target->ssid_len, target->ssid,
|
||||
target->bssid);
|
||||
libipw_network_reset(target);
|
||||
} else {
|
||||
/* Otherwise just pull from the free list */
|
||||
@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
|
||||
print_ssid(ssid, network.ssid,
|
||||
network.ssid_len),
|
||||
network.bssid,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n",
|
||||
network.ssid_len, network.ssid,
|
||||
network.bssid,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
#endif
|
||||
memcpy(target, &network, sizeof(*target));
|
||||
network.ibss_dfs = NULL;
|
||||
list_add_tail(&target->list, &ieee->network_list);
|
||||
} else {
|
||||
LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
|
||||
print_ssid(ssid, target->ssid,
|
||||
target->ssid_len),
|
||||
target->bssid,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
|
||||
target->ssid_len, target->ssid,
|
||||
target->bssid,
|
||||
is_beacon(beacon->header.frame_ctl) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
update_network(target, &network);
|
||||
network.ibss_dfs = NULL;
|
||||
}
|
||||
|
@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
|
||||
char *ev = extra;
|
||||
char *stop = ev + wrqu->data.length;
|
||||
int i = 0;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
LIBIPW_DEBUG_WX("Getting scan\n");
|
||||
|
||||
@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
|
||||
ev = libipw_translate_scan(ieee, ev, stop, network,
|
||||
info);
|
||||
else {
|
||||
LIBIPW_DEBUG_SCAN("Not showing network '%s ("
|
||||
"%pM)' due to age (%ums).\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
network->bssid,
|
||||
elapsed_jiffies_msecs(
|
||||
LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
|
||||
network->ssid_len, network->ssid,
|
||||
network->bssid,
|
||||
elapsed_jiffies_msecs(
|
||||
network->last_scanned));
|
||||
}
|
||||
}
|
||||
@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
|
||||
int i, key, key_provided, len;
|
||||
struct lib80211_crypt_data **crypt;
|
||||
int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
LIBIPW_DEBUG_WX("SET_ENCODE\n");
|
||||
|
||||
@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
|
||||
if (len > erq->length)
|
||||
memset(sec.keys[key] + erq->length, 0,
|
||||
len - erq->length);
|
||||
LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
|
||||
key, print_ssid(ssid, sec.keys[key], len),
|
||||
LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
|
||||
key, len, sec.keys[key],
|
||||
erq->length, len);
|
||||
sec.key_sizes[key] = len;
|
||||
if (*crypt)
|
||||
|
@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
|
||||
int chan_no = -1;
|
||||
const u8 *ssid = NULL;
|
||||
u8 ssid_len = 0;
|
||||
DECLARE_SSID_BUF(ssid_buf);
|
||||
|
||||
int len = get_unaligned_le16(pos);
|
||||
pos += 2;
|
||||
@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
|
||||
struct ieee80211_channel *channel =
|
||||
ieee80211_get_channel(wiphy, freq);
|
||||
|
||||
lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
|
||||
"%d dBm\n",
|
||||
bssid, capa, chan_no,
|
||||
print_ssid(ssid_buf, ssid, ssid_len),
|
||||
lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n",
|
||||
bssid, capa, chan_no, ssid_len, ssid,
|
||||
LBS_SCAN_RSSI_TO_MBM(rssi)/100);
|
||||
|
||||
if (channel &&
|
||||
@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
int ret = 0;
|
||||
struct cfg80211_bss *bss;
|
||||
DECLARE_SSID_BUF(ssid_buf);
|
||||
|
||||
if (dev == priv->mesh_dev)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
|
||||
{
|
||||
struct cmd_ds_mesh_config cmd;
|
||||
struct mrvl_meshie *ie;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.channel = cpu_to_le16(chan);
|
||||
@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
|
||||
action, priv->mesh_tlv, chan,
|
||||
print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
|
||||
lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
|
||||
action, priv->mesh_tlv, chan, priv->mesh_ssid_len,
|
||||
priv->mesh_ssid);
|
||||
|
||||
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
|
||||
}
|
||||
|
@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data(
|
||||
}
|
||||
|
||||
s = dmi_get_system_info(DMI_PRODUCT_VERSION);
|
||||
if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) {
|
||||
if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
|
||||
tp->model_str = kstrdup(s, GFP_KERNEL);
|
||||
if (!tp->model_str)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
s = dmi_get_system_info(DMI_BIOS_VENDOR);
|
||||
if (s && !(strnicmp(s, "Lenovo", 6))) {
|
||||
if (s && !(strncasecmp(s, "Lenovo", 6))) {
|
||||
tp->model_str = kstrdup(s, GFP_KERNEL);
|
||||
if (!tp->model_str)
|
||||
return -ENOMEM;
|
||||
|
@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev,
|
||||
}
|
||||
|
||||
buf = skip_spaces(buf);
|
||||
if (!strnicmp(buf, "disable", 7)) {
|
||||
if (!strncasecmp(buf, "disable", 7)) {
|
||||
retval = pnp_disable_dev(dev);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "activate", 8)) {
|
||||
if (!strncasecmp(buf, "activate", 8)) {
|
||||
retval = pnp_activate_dev(dev);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "fill", 4)) {
|
||||
if (!strncasecmp(buf, "fill", 4)) {
|
||||
if (dev->active)
|
||||
goto done;
|
||||
retval = pnp_auto_config_dev(dev);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "auto", 4)) {
|
||||
if (!strncasecmp(buf, "auto", 4)) {
|
||||
if (dev->active)
|
||||
goto done;
|
||||
pnp_init_resources(dev);
|
||||
retval = pnp_auto_config_dev(dev);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "clear", 5)) {
|
||||
if (!strncasecmp(buf, "clear", 5)) {
|
||||
if (dev->active)
|
||||
goto done;
|
||||
pnp_init_resources(dev);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "get", 3)) {
|
||||
if (!strncasecmp(buf, "get", 3)) {
|
||||
mutex_lock(&pnp_res_mutex);
|
||||
if (pnp_can_read(dev))
|
||||
dev->protocol->get(dev);
|
||||
mutex_unlock(&pnp_res_mutex);
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "set", 3)) {
|
||||
if (!strncasecmp(buf, "set", 3)) {
|
||||
resource_size_t start;
|
||||
resource_size_t end;
|
||||
unsigned long flags;
|
||||
@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev,
|
||||
mutex_lock(&pnp_res_mutex);
|
||||
while (1) {
|
||||
buf = skip_spaces(buf);
|
||||
if (!strnicmp(buf, "io", 2)) {
|
||||
if (!strncasecmp(buf, "io", 2)) {
|
||||
buf = pnp_get_resource_value(buf + 2,
|
||||
IORESOURCE_IO,
|
||||
&start, &end,
|
||||
&flags);
|
||||
pnp_add_io_resource(dev, start, end, flags);
|
||||
} else if (!strnicmp(buf, "mem", 3)) {
|
||||
} else if (!strncasecmp(buf, "mem", 3)) {
|
||||
buf = pnp_get_resource_value(buf + 3,
|
||||
IORESOURCE_MEM,
|
||||
&start, &end,
|
||||
&flags);
|
||||
pnp_add_mem_resource(dev, start, end, flags);
|
||||
} else if (!strnicmp(buf, "irq", 3)) {
|
||||
} else if (!strncasecmp(buf, "irq", 3)) {
|
||||
buf = pnp_get_resource_value(buf + 3,
|
||||
IORESOURCE_IRQ,
|
||||
&start, NULL,
|
||||
&flags);
|
||||
pnp_add_irq_resource(dev, start, flags);
|
||||
} else if (!strnicmp(buf, "dma", 3)) {
|
||||
} else if (!strncasecmp(buf, "dma", 3)) {
|
||||
buf = pnp_get_resource_value(buf + 3,
|
||||
IORESOURCE_DMA,
|
||||
&start, NULL,
|
||||
&flags);
|
||||
pnp_add_dma_resource(dev, start, flags);
|
||||
} else if (!strnicmp(buf, "bus", 3)) {
|
||||
} else if (!strncasecmp(buf, "bus", 3)) {
|
||||
buf = pnp_get_resource_value(buf + 3,
|
||||
IORESOURCE_BUS,
|
||||
&start, &end,
|
||||
|
@ -288,6 +288,26 @@ config RTC_DRV_MAX77686
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-max77686.
|
||||
|
||||
config RTC_DRV_RK808
|
||||
tristate "Rockchip RK808 RTC"
|
||||
depends on MFD_RK808
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
RTC of RK808 PMIC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rk808-rtc.
|
||||
|
||||
config RTC_DRV_MAX77802
|
||||
tristate "Maxim 77802 RTC"
|
||||
depends on MFD_MAX77686
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
RTC of Maxim MAX77802 PMIC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-max77802.
|
||||
|
||||
config RTC_DRV_RS5C372
|
||||
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
|
||||
help
|
||||
@ -732,6 +752,7 @@ config RTC_DRV_DS1216
|
||||
|
||||
config RTC_DRV_DS1286
|
||||
tristate "Dallas DS1286"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the Dallas DS1286 RTC chips.
|
||||
|
||||
@ -743,6 +764,7 @@ config RTC_DRV_DS1302
|
||||
|
||||
config RTC_DRV_DS1511
|
||||
tristate "Dallas DS1511"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
Dallas DS1511 timekeeping/watchdog chip.
|
||||
@ -752,6 +774,7 @@ config RTC_DRV_DS1511
|
||||
|
||||
config RTC_DRV_DS1553
|
||||
tristate "Maxim/Dallas DS1553"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
Maxim/Dallas DS1553 timekeeping chip.
|
||||
@ -761,6 +784,7 @@ config RTC_DRV_DS1553
|
||||
|
||||
config RTC_DRV_DS1742
|
||||
tristate "Maxim/Dallas DS1742/1743"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
Maxim/Dallas DS1742/1743 timekeeping chip.
|
||||
@ -816,6 +840,7 @@ config RTC_DRV_EFI
|
||||
|
||||
config RTC_DRV_STK17TA8
|
||||
tristate "Simtek STK17TA8"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
Simtek STK17TA8 timekeeping chip.
|
||||
@ -834,6 +859,7 @@ config RTC_DRV_M48T86
|
||||
|
||||
config RTC_DRV_M48T35
|
||||
tristate "ST M48T35"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say Y here you will get support for the
|
||||
ST M48T35 RTC chip.
|
||||
@ -843,6 +869,7 @@ config RTC_DRV_M48T35
|
||||
|
||||
config RTC_DRV_M48T59
|
||||
tristate "ST M48T59/M48T08/M48T02"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say Y here you will get support for the
|
||||
ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
|
||||
@ -855,6 +882,7 @@ config RTC_DRV_M48T59
|
||||
|
||||
config RTC_DRV_MSM6242
|
||||
tristate "Oki MSM6242"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the Oki MSM6242
|
||||
timekeeping chip. It is used in some Amiga models (e.g. A2000).
|
||||
@ -864,6 +892,7 @@ config RTC_DRV_MSM6242
|
||||
|
||||
config RTC_DRV_BQ4802
|
||||
tristate "TI BQ4802"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say Y here you will get support for the TI
|
||||
BQ4802 RTC chip.
|
||||
@ -873,6 +902,7 @@ config RTC_DRV_BQ4802
|
||||
|
||||
config RTC_DRV_RP5C01
|
||||
tristate "Ricoh RP5C01"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the Ricoh RP5C01
|
||||
timekeeping chip. It is used in some Amiga models (e.g. A3000
|
||||
@ -1374,6 +1404,7 @@ config RTC_DRV_MOXART
|
||||
|
||||
config RTC_DRV_XGENE
|
||||
tristate "APM X-Gene RTC"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the APM X-Gene SoC real time
|
||||
clock.
|
||||
|
@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
|
||||
obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o
|
||||
obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o
|
||||
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
|
||||
@ -109,6 +110,7 @@ obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
|
||||
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
|
||||
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
|
||||
obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o
|
||||
obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o
|
||||
obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
|
||||
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
|
||||
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
|
||||
|
@ -2,10 +2,14 @@
|
||||
* Driver for TI BQ32000 RTC.
|
||||
*
|
||||
* Copyright (C) 2009 Semihalf.
|
||||
* Copyright (C) 2014 Pavel Machek <pavel@denx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* You can get hardware description at
|
||||
* http://www.ti.com/lit/ds/symlink/bq32000.pdf
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -27,6 +31,10 @@
|
||||
#define BQ32K_CENT 0x40 /* Century flag */
|
||||
#define BQ32K_CENT_EN 0x80 /* Century flag enable bit */
|
||||
|
||||
#define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */
|
||||
#define BQ32K_TCH2 0x08 /* Trickle charge enable */
|
||||
#define BQ32K_CFG2 0x09 /* Trickle charger control */
|
||||
|
||||
struct bq32k_regs {
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = {
|
||||
.set_time = bq32k_rtc_set_time,
|
||||
};
|
||||
|
||||
static int trickle_charger_of_init(struct device *dev, struct device_node *node)
|
||||
{
|
||||
unsigned char reg;
|
||||
int error;
|
||||
u32 ohms = 0;
|
||||
|
||||
if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
|
||||
return 0;
|
||||
|
||||
switch (ohms) {
|
||||
case 180+940:
|
||||
/*
|
||||
* TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
|
||||
* over diode and 940ohm resistor)
|
||||
*/
|
||||
|
||||
if (of_property_read_bool(node, "trickle-diode-disable")) {
|
||||
dev_err(dev, "diode and resistor mismatch\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
reg = 0x05;
|
||||
break;
|
||||
|
||||
case 180+20000:
|
||||
/* diode disabled */
|
||||
|
||||
if (!of_property_read_bool(node, "trickle-diode-disable")) {
|
||||
dev_err(dev, "bq32k: diode and resistor mismatch\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
reg = 0x25;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dev, "invalid resistor value (%d)\n", ohms);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = bq32k_write(dev, ®, BQ32K_CFG2, 1);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
reg = 0x20;
|
||||
error = bq32k_write(dev, ®, BQ32K_TCH2, 1);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev_info(dev, "Enabled trickle RTC battery charge.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bq32k_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (client && client->dev.of_node)
|
||||
trickle_charger_of_init(dev, client->dev.of_node);
|
||||
|
||||
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
|
||||
&bq32k_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc))
|
||||
|
@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev)
|
||||
cmos->dev = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int cmos_suspend(struct device *dev)
|
||||
{
|
||||
@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev)
|
||||
return cmos_suspend(dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int cmos_resume(struct device *dev)
|
||||
{
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
static inline int cmos_poweroff(struct device *dev)
|
||||
|
@ -126,9 +126,14 @@ struct chip_desc {
|
||||
u16 nvram_offset;
|
||||
u16 nvram_size;
|
||||
u16 trickle_charger_reg;
|
||||
u8 trickle_charger_setup;
|
||||
u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
|
||||
};
|
||||
|
||||
static const struct chip_desc chips[last_ds_type] = {
|
||||
static u8 do_trickle_setup_ds1339(struct i2c_client *,
|
||||
uint32_t ohms, bool diode);
|
||||
|
||||
static struct chip_desc chips[last_ds_type] = {
|
||||
[ds_1307] = {
|
||||
.nvram_offset = 8,
|
||||
.nvram_size = 56,
|
||||
@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = {
|
||||
[ds_1339] = {
|
||||
.alarm = 1,
|
||||
.trickle_charger_reg = 0x10,
|
||||
.do_trickle_setup = &do_trickle_setup_ds1339,
|
||||
},
|
||||
[ds_1340] = {
|
||||
.trickle_charger_reg = 0x08,
|
||||
@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static u8 do_trickle_setup_ds1339(struct i2c_client *client,
|
||||
uint32_t ohms, bool diode)
|
||||
{
|
||||
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
|
||||
DS1307_TRICKLE_CHARGER_NO_DIODE;
|
||||
|
||||
switch (ohms) {
|
||||
case 250:
|
||||
setup |= DS1307_TRICKLE_CHARGER_250_OHM;
|
||||
break;
|
||||
case 2000:
|
||||
setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
|
||||
break;
|
||||
case 4000:
|
||||
setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&client->dev,
|
||||
"Unsupported ohm value %u in dt\n", ohms);
|
||||
return 0;
|
||||
}
|
||||
return setup;
|
||||
}
|
||||
|
||||
static void ds1307_trickle_of_init(struct i2c_client *client,
|
||||
struct chip_desc *chip)
|
||||
{
|
||||
uint32_t ohms = 0;
|
||||
bool diode = true;
|
||||
|
||||
if (!chip->do_trickle_setup)
|
||||
goto out;
|
||||
if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms))
|
||||
goto out;
|
||||
if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
|
||||
diode = false;
|
||||
chip->trickle_charger_setup = chip->do_trickle_setup(client,
|
||||
ohms, diode);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int ds1307_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ds1307 *ds1307;
|
||||
int err = -ENODEV;
|
||||
int tmp;
|
||||
const struct chip_desc *chip = &chips[id->driver_data];
|
||||
struct chip_desc *chip = &chips[id->driver_data];
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
bool want_irq = false;
|
||||
unsigned char *buf;
|
||||
@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client,
|
||||
ds1307->client = client;
|
||||
ds1307->type = id->driver_data;
|
||||
|
||||
if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
|
||||
if (!pdata && client->dev.of_node)
|
||||
ds1307_trickle_of_init(client, chip);
|
||||
else if (pdata && pdata->trickle_charger_setup)
|
||||
chip->trickle_charger_setup = pdata->trickle_charger_setup;
|
||||
|
||||
if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
|
||||
dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
|
||||
DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
|
||||
chip->trickle_charger_reg);
|
||||
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
|
||||
DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
|
||||
DS13XX_TRICKLE_CHARGER_MAGIC |
|
||||
chip->trickle_charger_setup);
|
||||
}
|
||||
|
||||
buf = ds1307->regs;
|
||||
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||
|
@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id isl12022_dt_match[] = {
|
||||
static const struct of_device_id isl12022_dt_match[] = {
|
||||
{ .compatible = "isl,isl12022" },
|
||||
{ },
|
||||
};
|
||||
|
@ -32,15 +32,6 @@
|
||||
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
|
||||
#define RTC_RBUDR_SHIFT 4
|
||||
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
|
||||
/* WTSR and SMPL Register */
|
||||
#define WTSRT_SHIFT 0
|
||||
#define SMPLT_SHIFT 2
|
||||
#define WTSR_EN_SHIFT 6
|
||||
#define SMPL_EN_SHIFT 7
|
||||
#define WTSRT_MASK (3 << WTSRT_SHIFT)
|
||||
#define SMPLT_MASK (3 << SMPLT_SHIFT)
|
||||
#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT)
|
||||
#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT)
|
||||
/* RTC Hour register */
|
||||
#define HOUR_PM_SHIFT 6
|
||||
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
|
||||
@ -49,7 +40,6 @@
|
||||
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
|
||||
|
||||
#define MAX77686_RTC_UPDATE_DELAY 16
|
||||
#undef MAX77686_RTC_WTSR_SMPL
|
||||
|
||||
enum {
|
||||
RTC_SEC = 0,
|
||||
@ -80,16 +70,6 @@ enum MAX77686_RTC_OP {
|
||||
MAX77686_RTC_READ,
|
||||
};
|
||||
|
||||
static inline int max77686_rtc_calculate_wday(u8 shifted)
|
||||
{
|
||||
int counter = -1;
|
||||
while (shifted) {
|
||||
shifted >>= 1;
|
||||
counter++;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
|
||||
int rtc_24hr_mode)
|
||||
{
|
||||
@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
|
||||
tm->tm_hour += 12;
|
||||
}
|
||||
|
||||
tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f);
|
||||
/* Only a single bit is set in data[], so fls() would be equivalent */
|
||||
tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
|
||||
tm->tm_mday = data[RTC_DATE] & 0x1f;
|
||||
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
|
||||
tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
|
||||
@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = {
|
||||
.alarm_irq_enable = max77686_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
#ifdef MAX77686_RTC_WTSR_SMPL
|
||||
static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val, mask;
|
||||
|
||||
if (enable)
|
||||
val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT);
|
||||
else
|
||||
val = 0;
|
||||
|
||||
mask = WTSR_EN_MASK | WTSRT_MASK;
|
||||
|
||||
dev_info(info->dev, "%s: %s WTSR\n", __func__,
|
||||
enable ? "enable" : "disable");
|
||||
|
||||
ret = regmap_update_bits(info->max77686->rtc_regmap,
|
||||
MAX77686_WTSR_SMPL_CNTL, mask, val);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
|
||||
__func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
max77686_rtc_update(info, MAX77686_RTC_WRITE);
|
||||
}
|
||||
|
||||
static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val, mask;
|
||||
|
||||
if (enable)
|
||||
val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT);
|
||||
else
|
||||
val = 0;
|
||||
|
||||
mask = SMPL_EN_MASK | SMPLT_MASK;
|
||||
|
||||
dev_info(info->dev, "%s: %s SMPL\n", __func__,
|
||||
enable ? "enable" : "disable");
|
||||
|
||||
ret = regmap_update_bits(info->max77686->rtc_regmap,
|
||||
MAX77686_WTSR_SMPL_CNTL, mask, val);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
|
||||
__func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
max77686_rtc_update(info, MAX77686_RTC_WRITE);
|
||||
|
||||
val = 0;
|
||||
regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
|
||||
dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val);
|
||||
}
|
||||
#endif /* MAX77686_RTC_WTSR_SMPL */
|
||||
|
||||
static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
|
||||
{
|
||||
u8 data[2];
|
||||
@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
|
||||
goto err_rtc;
|
||||
}
|
||||
|
||||
#ifdef MAX77686_RTC_WTSR_SMPL
|
||||
max77686_rtc_enable_wtsr(info, true);
|
||||
max77686_rtc_enable_smpl(info, true);
|
||||
#endif
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
|
||||
&max77686_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(info->rtc_dev)) {
|
||||
dev_info(&pdev->dev, "%s: fail\n", __func__);
|
||||
|
||||
ret = PTR_ERR(info->rtc_dev);
|
||||
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
||||
if (ret == 0)
|
||||
@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
|
||||
goto err_rtc;
|
||||
}
|
||||
|
||||
if (!max77686->rtc_irq_data) {
|
||||
ret = -EINVAL;
|
||||
dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
|
||||
goto err_rtc;
|
||||
}
|
||||
|
||||
info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
|
||||
MAX77686_RTCIRQ_RTCA1);
|
||||
if (!info->virq) {
|
||||
@ -556,33 +478,33 @@ err_rtc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void max77686_rtc_shutdown(struct platform_device *pdev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int max77686_rtc_suspend(struct device *dev)
|
||||
{
|
||||
#ifdef MAX77686_RTC_WTSR_SMPL
|
||||
struct max77686_rtc_info *info = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
u8 val = 0;
|
||||
if (device_may_wakeup(dev)) {
|
||||
struct max77686_rtc_info *info = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
max77686_rtc_enable_wtsr(info, false);
|
||||
regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
|
||||
dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__,
|
||||
val);
|
||||
if (val & WTSR_EN_MASK) {
|
||||
dev_emerg(info->dev, "%s: fail to disable WTSR\n",
|
||||
__func__);
|
||||
} else {
|
||||
dev_info(info->dev, "%s: success to disable WTSR\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
return enable_irq_wake(info->virq);
|
||||
}
|
||||
|
||||
/* Disable SMPL when power off */
|
||||
max77686_rtc_enable_smpl(info, false);
|
||||
#endif /* MAX77686_RTC_WTSR_SMPL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77686_rtc_resume(struct device *dev)
|
||||
{
|
||||
if (device_may_wakeup(dev)) {
|
||||
struct max77686_rtc_info *info = dev_get_drvdata(dev);
|
||||
|
||||
return disable_irq_wake(info->virq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
|
||||
max77686_rtc_suspend, max77686_rtc_resume);
|
||||
|
||||
static const struct platform_device_id rtc_id[] = {
|
||||
{ "max77686-rtc", 0 },
|
||||
{},
|
||||
@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "max77686-rtc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &max77686_rtc_pm_ops,
|
||||
},
|
||||
.probe = max77686_rtc_probe,
|
||||
.shutdown = max77686_rtc_shutdown,
|
||||
.id_table = rtc_id,
|
||||
};
|
||||
|
||||
|
502
drivers/rtc/rtc-max77802.c
Normal file
502
drivers/rtc/rtc-max77802.c
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* RTC driver for Maxim MAX77802
|
||||
*
|
||||
* Copyright (C) 2013 Google, Inc
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co.Ltd
|
||||
*
|
||||
* based on rtc-max8997.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/max77686-private.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* RTC Control Register */
|
||||
#define BCD_EN_SHIFT 0
|
||||
#define BCD_EN_MASK (1 << BCD_EN_SHIFT)
|
||||
#define MODEL24_SHIFT 1
|
||||
#define MODEL24_MASK (1 << MODEL24_SHIFT)
|
||||
/* RTC Update Register1 */
|
||||
#define RTC_UDR_SHIFT 0
|
||||
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
|
||||
#define RTC_RBUDR_SHIFT 4
|
||||
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
|
||||
/* RTC Hour register */
|
||||
#define HOUR_PM_SHIFT 6
|
||||
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
|
||||
/* RTC Alarm Enable */
|
||||
#define ALARM_ENABLE_SHIFT 7
|
||||
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
|
||||
|
||||
/* For the RTCAE1 register, we write this value to enable the alarm */
|
||||
#define ALARM_ENABLE_VALUE 0x77
|
||||
|
||||
#define MAX77802_RTC_UPDATE_DELAY_US 200
|
||||
|
||||
enum {
|
||||
RTC_SEC = 0,
|
||||
RTC_MIN,
|
||||
RTC_HOUR,
|
||||
RTC_WEEKDAY,
|
||||
RTC_MONTH,
|
||||
RTC_YEAR,
|
||||
RTC_DATE,
|
||||
RTC_NR_TIME
|
||||
};
|
||||
|
||||
struct max77802_rtc_info {
|
||||
struct device *dev;
|
||||
struct max77686_dev *max77802;
|
||||
struct i2c_client *rtc;
|
||||
struct rtc_device *rtc_dev;
|
||||
struct mutex lock;
|
||||
|
||||
struct regmap *regmap;
|
||||
|
||||
int virq;
|
||||
int rtc_24hr_mode;
|
||||
};
|
||||
|
||||
enum MAX77802_RTC_OP {
|
||||
MAX77802_RTC_WRITE,
|
||||
MAX77802_RTC_READ,
|
||||
};
|
||||
|
||||
static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
|
||||
int rtc_24hr_mode)
|
||||
{
|
||||
tm->tm_sec = data[RTC_SEC] & 0xff;
|
||||
tm->tm_min = data[RTC_MIN] & 0xff;
|
||||
if (rtc_24hr_mode)
|
||||
tm->tm_hour = data[RTC_HOUR] & 0x1f;
|
||||
else {
|
||||
tm->tm_hour = data[RTC_HOUR] & 0x0f;
|
||||
if (data[RTC_HOUR] & HOUR_PM_MASK)
|
||||
tm->tm_hour += 12;
|
||||
}
|
||||
|
||||
/* Only a single bit is set in data[], so fls() would be equivalent */
|
||||
tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
|
||||
tm->tm_mday = data[RTC_DATE] & 0x1f;
|
||||
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
|
||||
|
||||
tm->tm_year = data[RTC_YEAR] & 0xff;
|
||||
tm->tm_yday = 0;
|
||||
tm->tm_isdst = 0;
|
||||
}
|
||||
|
||||
static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
|
||||
{
|
||||
data[RTC_SEC] = tm->tm_sec;
|
||||
data[RTC_MIN] = tm->tm_min;
|
||||
data[RTC_HOUR] = tm->tm_hour;
|
||||
data[RTC_WEEKDAY] = 1 << tm->tm_wday;
|
||||
data[RTC_DATE] = tm->tm_mday;
|
||||
data[RTC_MONTH] = tm->tm_mon + 1;
|
||||
data[RTC_YEAR] = tm->tm_year;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77802_rtc_update(struct max77802_rtc_info *info,
|
||||
enum MAX77802_RTC_OP op)
|
||||
{
|
||||
int ret;
|
||||
unsigned int data;
|
||||
|
||||
if (op == MAX77802_RTC_WRITE)
|
||||
data = 1 << RTC_UDR_SHIFT;
|
||||
else
|
||||
data = 1 << RTC_RBUDR_SHIFT;
|
||||
|
||||
ret = regmap_update_bits(info->max77802->regmap,
|
||||
MAX77802_RTC_UPDATE0, data, data);
|
||||
if (ret < 0)
|
||||
dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
|
||||
__func__, ret, data);
|
||||
else {
|
||||
/* Minimum delay required before RTC update. */
|
||||
usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
|
||||
MAX77802_RTC_UPDATE_DELAY_US * 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
u8 data[RTC_NR_TIME];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_bulk_read(info->max77802->regmap,
|
||||
MAX77802_RTC_SEC, data, RTC_NR_TIME);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
|
||||
|
||||
ret = rtc_valid_tm(tm);
|
||||
|
||||
out:
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
u8 data[RTC_NR_TIME];
|
||||
int ret;
|
||||
|
||||
ret = max77802_rtc_tm_to_data(tm, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
ret = regmap_bulk_write(info->max77802->regmap,
|
||||
MAX77802_RTC_SEC, data, RTC_NR_TIME);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
|
||||
|
||||
out:
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
u8 data[RTC_NR_TIME];
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_bulk_read(info->max77802->regmap,
|
||||
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
|
||||
|
||||
alrm->enabled = 0;
|
||||
ret = regmap_read(info->max77802->regmap,
|
||||
MAX77802_RTC_AE1, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (val)
|
||||
alrm->enabled = 1;
|
||||
|
||||
alrm->pending = 0;
|
||||
ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (val & (1 << 2)) /* RTCA1 */
|
||||
alrm->pending = 1;
|
||||
|
||||
out:
|
||||
mutex_unlock(&info->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!mutex_is_locked(&info->lock))
|
||||
dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_write(info->max77802->regmap,
|
||||
MAX77802_RTC_AE1, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!mutex_is_locked(&info->lock))
|
||||
dev_warn(info->dev, "%s: should have mutex locked\n",
|
||||
__func__);
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_write(info->max77802->regmap,
|
||||
MAX77802_RTC_AE1,
|
||||
ALARM_ENABLE_VALUE);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
u8 data[RTC_NR_TIME];
|
||||
int ret;
|
||||
|
||||
ret = max77802_rtc_tm_to_data(&alrm->time, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
ret = max77802_rtc_stop_alarm(info);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_bulk_write(info->max77802->regmap,
|
||||
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (alrm->enabled)
|
||||
ret = max77802_rtc_start_alarm(info);
|
||||
out:
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_alarm_irq_enable(struct device *dev,
|
||||
unsigned int enabled)
|
||||
{
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
if (enabled)
|
||||
ret = max77802_rtc_start_alarm(info);
|
||||
else
|
||||
ret = max77802_rtc_stop_alarm(info);
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
|
||||
{
|
||||
struct max77802_rtc_info *info = data;
|
||||
|
||||
dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
|
||||
|
||||
rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops max77802_rtc_ops = {
|
||||
.read_time = max77802_rtc_read_time,
|
||||
.set_time = max77802_rtc_set_time,
|
||||
.read_alarm = max77802_rtc_read_alarm,
|
||||
.set_alarm = max77802_rtc_set_alarm,
|
||||
.alarm_irq_enable = max77802_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
|
||||
{
|
||||
u8 data[2];
|
||||
int ret;
|
||||
|
||||
max77802_rtc_update(info, MAX77802_RTC_READ);
|
||||
|
||||
/* Set RTC control register : Binary mode, 24hour mdoe */
|
||||
data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
|
||||
data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
|
||||
|
||||
info->rtc_24hr_mode = 1;
|
||||
|
||||
ret = regmap_bulk_write(info->max77802->regmap,
|
||||
MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77802_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max77802_rtc_info *info;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
|
||||
GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&info->lock);
|
||||
info->dev = &pdev->dev;
|
||||
info->max77802 = max77802;
|
||||
info->rtc = max77802->i2c;
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
ret = max77802_rtc_init_reg(info);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
|
||||
&max77802_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(info->rtc_dev)) {
|
||||
ret = PTR_ERR(info->rtc_dev);
|
||||
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!max77802->rtc_irq_data) {
|
||||
dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
|
||||
MAX77686_RTCIRQ_RTCA1);
|
||||
|
||||
if (info->virq <= 0) {
|
||||
dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
|
||||
MAX77686_RTCIRQ_RTCA1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
|
||||
max77802_rtc_alarm_irq, 0, "rtc-alarm1",
|
||||
info);
|
||||
if (ret < 0)
|
||||
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
|
||||
info->virq, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int max77802_rtc_suspend(struct device *dev)
|
||||
{
|
||||
if (device_may_wakeup(dev)) {
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
|
||||
return enable_irq_wake(info->virq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77802_rtc_resume(struct device *dev)
|
||||
{
|
||||
if (device_may_wakeup(dev)) {
|
||||
struct max77802_rtc_info *info = dev_get_drvdata(dev);
|
||||
|
||||
return disable_irq_wake(info->virq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
|
||||
max77802_rtc_suspend, max77802_rtc_resume);
|
||||
|
||||
static const struct platform_device_id rtc_id[] = {
|
||||
{ "max77802-rtc", 0 },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver max77802_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "max77802-rtc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &max77802_rtc_pm_ops,
|
||||
},
|
||||
.probe = max77802_rtc_probe,
|
||||
.id_table = rtc_id,
|
||||
};
|
||||
|
||||
module_platform_driver(max77802_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
|
||||
MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
|
||||
MODULE_LICENSE("GPL");
|
@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id mpc5121_rtc_match[] = {
|
||||
static const struct of_device_id mpc5121_rtc_match[] = {
|
||||
{ .compatible = "fsl,mpc5121-rtc", },
|
||||
{ .compatible = "fsl,mpc5200-rtc", },
|
||||
{},
|
||||
|
@ -167,8 +167,8 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
|
||||
char pending;
|
||||
|
||||
err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (pending) {
|
||||
rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
|
||||
|
@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned char ctrl, year[2];
|
||||
struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
|
||||
struct rtc_mem mem = {
|
||||
.loc = CMOS_YEAR,
|
||||
.nr = sizeof(year),
|
||||
.data = year
|
||||
};
|
||||
int real_year, year_offset, err;
|
||||
|
||||
/*
|
||||
@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned char year[2], chk;
|
||||
struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year };
|
||||
struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
|
||||
struct rtc_mem cmos_year = {
|
||||
.loc = CMOS_YEAR,
|
||||
.nr = sizeof(year),
|
||||
.data = year
|
||||
};
|
||||
struct rtc_mem cmos_check = {
|
||||
.loc = CMOS_CHECKSUM,
|
||||
.nr = 1,
|
||||
.data = &chk
|
||||
};
|
||||
unsigned int proper_year = tm->tm_year + 1900;
|
||||
int ret;
|
||||
|
||||
|
414
drivers/rtc/rtc-rk808.c
Normal file
414
drivers/rtc/rtc-rk808.c
Normal file
@ -0,0 +1,414 @@
|
||||
/*
|
||||
* RTC driver for Rockchip RK808
|
||||
*
|
||||
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* Author: Chris Zhong <zyw@rock-chips.com>
|
||||
* Author: Zhang Qing <zhangqing@rock-chips.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/mfd/rk808.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
/* RTC_CTRL_REG bitfields */
|
||||
#define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0)
|
||||
|
||||
/* RK808 has a shadowed register for saving a "frozen" RTC time.
|
||||
* When user setting "GET_TIME" to 1, the time will save in this shadowed
|
||||
* register. If set "READSEL" to 1, user read rtc time register, actually
|
||||
* get the time of that moment. If we need the real time, clr this bit.
|
||||
*/
|
||||
#define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6)
|
||||
#define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7)
|
||||
#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M BIT(3)
|
||||
#define RTC_STATUS_MASK 0xFE
|
||||
|
||||
#define SECONDS_REG_MSK 0x7F
|
||||
#define MINUTES_REG_MAK 0x7F
|
||||
#define HOURS_REG_MSK 0x3F
|
||||
#define DAYS_REG_MSK 0x3F
|
||||
#define MONTHS_REG_MSK 0x1F
|
||||
#define YEARS_REG_MSK 0xFF
|
||||
#define WEEKS_REG_MSK 0x7
|
||||
|
||||
/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
|
||||
|
||||
#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
|
||||
#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
|
||||
|
||||
struct rk808_rtc {
|
||||
struct rk808 *rk808;
|
||||
struct rtc_device *rtc;
|
||||
int irq;
|
||||
};
|
||||
|
||||
/* Read current time and date in RTC */
|
||||
static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
u8 rtc_data[NUM_TIME_REGS];
|
||||
int ret;
|
||||
|
||||
/* Force an update of the shadowed registers right now */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME,
|
||||
0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
|
||||
rtc_data, NUM_TIME_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK);
|
||||
tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK);
|
||||
tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK);
|
||||
tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK);
|
||||
tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
|
||||
tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
|
||||
tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
|
||||
dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
|
||||
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set current time and date in RTC */
|
||||
static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
u8 rtc_data[NUM_TIME_REGS];
|
||||
int ret;
|
||||
|
||||
rtc_data[0] = bin2bcd(tm->tm_sec);
|
||||
rtc_data[1] = bin2bcd(tm->tm_min);
|
||||
rtc_data[2] = bin2bcd(tm->tm_hour);
|
||||
rtc_data[3] = bin2bcd(tm->tm_mday);
|
||||
rtc_data[4] = bin2bcd(tm->tm_mon + 1);
|
||||
rtc_data[5] = bin2bcd(tm->tm_year - 100);
|
||||
rtc_data[6] = bin2bcd(tm->tm_wday);
|
||||
dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
|
||||
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
|
||||
|
||||
/* Stop RTC while updating the RTC registers */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to update RTC control: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
|
||||
rtc_data, NUM_TIME_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Start RTC again */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to update RTC control: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read alarm time and date in RTC */
|
||||
static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
u8 alrm_data[NUM_ALARM_REGS];
|
||||
uint32_t int_reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
|
||||
alrm_data, NUM_ALARM_REGS);
|
||||
|
||||
alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
|
||||
alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
|
||||
alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK);
|
||||
alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
|
||||
alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
|
||||
alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
|
||||
|
||||
ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
|
||||
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
|
||||
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
|
||||
alrm->time.tm_min, alrm->time.tm_sec);
|
||||
|
||||
alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
|
||||
{
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
|
||||
{
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
u8 alrm_data[NUM_ALARM_REGS];
|
||||
int ret;
|
||||
|
||||
ret = rk808_rtc_stop_alarm(rk808_rtc);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to stop alarm: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
|
||||
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
|
||||
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
|
||||
alrm->time.tm_min, alrm->time.tm_sec);
|
||||
|
||||
alrm_data[0] = bin2bcd(alrm->time.tm_sec);
|
||||
alrm_data[1] = bin2bcd(alrm->time.tm_min);
|
||||
alrm_data[2] = bin2bcd(alrm->time.tm_hour);
|
||||
alrm_data[3] = bin2bcd(alrm->time.tm_mday);
|
||||
alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
|
||||
alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
|
||||
|
||||
ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
|
||||
alrm_data, NUM_ALARM_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bulk write: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (alrm->enabled) {
|
||||
ret = rk808_rtc_start_alarm(rk808_rtc);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to start alarm: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk808_rtc_alarm_irq_enable(struct device *dev,
|
||||
unsigned int enabled)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
|
||||
|
||||
if (enabled)
|
||||
return rk808_rtc_start_alarm(rk808_rtc);
|
||||
|
||||
return rk808_rtc_stop_alarm(rk808_rtc);
|
||||
}
|
||||
|
||||
/*
|
||||
* We will just handle setting the frequency and make use the framework for
|
||||
* reading the periodic interupts.
|
||||
*
|
||||
* @freq: Current periodic IRQ freq:
|
||||
* bit 0: every second
|
||||
* bit 1: every minute
|
||||
* bit 2: every hour
|
||||
* bit 3: every day
|
||||
*/
|
||||
static irqreturn_t rk808_alarm_irq(int irq, void *data)
|
||||
{
|
||||
struct rk808_rtc *rk808_rtc = data;
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
struct i2c_client *client = rk808->i2c;
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
|
||||
RTC_STATUS_MASK);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"%s:Failed to update RTC status: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF);
|
||||
dev_dbg(&client->dev,
|
||||
"%s:irq=%d\n", __func__, irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops rk808_rtc_ops = {
|
||||
.read_time = rk808_rtc_readtime,
|
||||
.set_time = rk808_rtc_set_time,
|
||||
.read_alarm = rk808_rtc_readalarm,
|
||||
.set_alarm = rk808_rtc_setalarm,
|
||||
.alarm_irq_enable = rk808_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Turn off the alarm if it should not be a wake source. */
|
||||
static int rk808_rtc_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
enable_irq_wake(rk808_rtc->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable the alarm if it should be enabled (in case it was disabled to
|
||||
* prevent use as a wake source).
|
||||
*/
|
||||
static int rk808_rtc_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
disable_irq_wake(rk808_rtc->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
|
||||
rk808_rtc_suspend, rk808_rtc_resume);
|
||||
|
||||
static int rk808_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rk808_rtc *rk808_rtc;
|
||||
struct rtc_time tm;
|
||||
int ret;
|
||||
|
||||
rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
|
||||
if (rk808_rtc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, rk808_rtc);
|
||||
rk808_rtc->rk808 = rk808;
|
||||
|
||||
/* start rtc running by default, and use shadowed timer. */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M |
|
||||
BIT_RTC_CTRL_REG_RTC_READSEL_M,
|
||||
BIT_RTC_CTRL_REG_RTC_READSEL_M);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to update RTC control: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
|
||||
RTC_STATUS_MASK);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to write RTC status: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set init time */
|
||||
ret = rk808_rtc_readtime(&pdev->dev, &tm);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to read RTC time\n");
|
||||
return ret;
|
||||
}
|
||||
ret = rtc_valid_tm(&tm);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "invalid date/time\n");
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
|
||||
&rk808_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rk808_rtc->rtc)) {
|
||||
ret = PTR_ERR(rk808_rtc->rtc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rk808_rtc->irq = platform_get_irq(pdev, 0);
|
||||
if (rk808_rtc->irq < 0) {
|
||||
if (rk808_rtc->irq != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n",
|
||||
rk808_rtc->irq);
|
||||
return rk808_rtc->irq;
|
||||
}
|
||||
|
||||
/* request alarm irq of rk808 */
|
||||
ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL,
|
||||
rk808_alarm_irq, 0,
|
||||
"RTC alarm", rk808_rtc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
|
||||
rk808_rtc->irq, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver rk808_rtc_driver = {
|
||||
.probe = rk808_rtc_probe,
|
||||
.driver = {
|
||||
.name = "rk808-rtc",
|
||||
.pm = &rk808_rtc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rk808_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs");
|
||||
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
|
||||
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:rk808-rtc");
|
@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
|
||||
"%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
|
||||
rs5c->regs[0], rs5c->regs[1], rs5c->regs[2], rs5c->regs[3],
|
||||
rs5c->regs[4], rs5c->regs[5], rs5c->regs[6], rs5c->regs[7],
|
||||
rs5c->regs[8], rs5c->regs[9], rs5c->regs[10], rs5c->regs[11],
|
||||
rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);
|
||||
"%3ph (%02x) %3ph (%02x), %3ph, %3ph; %02x %02x\n",
|
||||
rs5c->regs + 0, rs5c->regs[3],
|
||||
rs5c->regs + 4, rs5c->regs[7],
|
||||
rs5c->regs + 8, rs5c->regs + 11,
|
||||
rs5c->regs[14], rs5c->regs[15]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev,
|
||||
if (!num_args)
|
||||
return count;
|
||||
|
||||
if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
|
||||
if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
|
||||
mutex_lock(&cp->lock);
|
||||
error = s390_vary_chpid(cp->chpid, 1);
|
||||
mutex_unlock(&cp->lock);
|
||||
} else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
|
||||
} else if (!strncasecmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
|
||||
mutex_lock(&cp->lock);
|
||||
error = s390_vary_chpid(cp->chpid, 0);
|
||||
mutex_unlock(&cp->lock);
|
||||
|
@ -528,7 +528,7 @@ ips_setup(char *ips_str)
|
||||
* Update the variables
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
||||
if (strnicmp
|
||||
if (strncasecmp
|
||||
(key, options[i].option_name,
|
||||
strlen(options[i].option_name)) == 0) {
|
||||
if (value)
|
||||
|
@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
|
||||
char work[20];
|
||||
|
||||
if (1 == sscanf(buf, "%10s", work)) {
|
||||
if (0 == strnicmp(work,"0x", 2)) {
|
||||
if (0 == strncasecmp(work,"0x", 2)) {
|
||||
if (1 == sscanf(&work[2], "%x", &opts))
|
||||
goto opts_done;
|
||||
} else {
|
||||
|
@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr)
|
||||
{
|
||||
int cmd_num;
|
||||
for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
|
||||
if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num],
|
||||
if (0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num],
|
||||
strlen(android_wifi_cmd_str[cmd_num])))
|
||||
break;
|
||||
return cmd_num;
|
||||
|
@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee)
|
||||
static inline const char *escape_essid(const char *essid, u8 essid_len)
|
||||
{
|
||||
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
const char *s = essid;
|
||||
char *d = escaped;
|
||||
|
||||
if (rtllib_is_empty_essid(essid, essid_len)) {
|
||||
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
|
||||
return escaped;
|
||||
}
|
||||
|
||||
essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
|
||||
while (essid_len--) {
|
||||
if (*s == '\0') {
|
||||
*d++ = '\\';
|
||||
*d++ = '0';
|
||||
s++;
|
||||
} else {
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
*d = '\0';
|
||||
snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
|
||||
return escaped;
|
||||
}
|
||||
|
||||
|
@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
|
||||
|
||||
static inline const char *escape_essid(const char *essid, u8 essid_len) {
|
||||
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
const char *s = essid;
|
||||
char *d = escaped;
|
||||
|
||||
if (ieee80211_is_empty_essid(essid, essid_len)) {
|
||||
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
|
||||
return escaped;
|
||||
}
|
||||
|
||||
essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
|
||||
while (essid_len--) {
|
||||
if (*s == '\0') {
|
||||
*d++ = '\\';
|
||||
*d++ = '0';
|
||||
s++;
|
||||
} else {
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
*d = '\0';
|
||||
snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
|
||||
return escaped;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,6 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/byteorder/generic.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
@ -81,27 +80,6 @@
|
||||
#include "hfa384x.h"
|
||||
#include "prism2mgmt.h"
|
||||
|
||||
/* Create a string of printable chars from something that might not be */
|
||||
/* It's recommended that the str be 4*len + 1 bytes long */
|
||||
#define wlan_mkprintstr(buf, buflen, str, strlen) \
|
||||
{ \
|
||||
int i = 0; \
|
||||
int j = 0; \
|
||||
memset(str, 0, (strlen)); \
|
||||
for (i = 0; i < (buflen); i++) { \
|
||||
if (isprint((buf)[i])) { \
|
||||
(str)[j] = (buf)[i]; \
|
||||
j++; \
|
||||
} else { \
|
||||
(str)[j] = '\\'; \
|
||||
(str)[j+1] = 'x'; \
|
||||
(str)[j+2] = hex_asc_hi((buf)[i]); \
|
||||
(str)[j+3] = hex_asc_lo((buf)[i]); \
|
||||
j += 4; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
static char *dev_info = "prism2_usb";
|
||||
static wlandevice_t *create_wlan(void);
|
||||
|
||||
@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
|
||||
hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
|
||||
u16 temp;
|
||||
u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
|
||||
char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
|
||||
|
||||
/* Collect version and compatibility info */
|
||||
/* Some are critical, some are not */
|
||||
@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
|
||||
result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
|
||||
snum, HFA384x_RID_NICSERIALNUMBER_LEN);
|
||||
if (!result) {
|
||||
wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
|
||||
pstr, sizeof(pstr));
|
||||
netdev_info(wlandev->netdev, "Prism2 card SN: %s\n", pstr);
|
||||
netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n",
|
||||
HFA384x_RID_NICSERIALNUMBER_LEN, snum);
|
||||
} else {
|
||||
netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
|
||||
goto failed;
|
||||
|
@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name)
|
||||
return def_governor;
|
||||
|
||||
list_for_each_entry(pos, &thermal_governor_list, governor_list)
|
||||
if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
|
||||
if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH))
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor)
|
||||
|
||||
name = pos->tzp->governor_name;
|
||||
|
||||
if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
|
||||
if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH))
|
||||
pos->governor = governor;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)
|
||||
mutex_lock(&thermal_list_lock);
|
||||
|
||||
list_for_each_entry(pos, &thermal_tz_list, node) {
|
||||
if (!strnicmp(pos->governor->name, governor->name,
|
||||
if (!strncasecmp(pos->governor->name, governor->name,
|
||||
THERMAL_NAME_LENGTH))
|
||||
pos->governor = NULL;
|
||||
}
|
||||
@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
|
||||
|
||||
mutex_lock(&thermal_list_lock);
|
||||
list_for_each_entry(pos, &thermal_tz_list, node)
|
||||
if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) {
|
||||
if (!strncasecmp(name, pos->type, THERMAL_NAME_LENGTH)) {
|
||||
found++;
|
||||
ref = pos;
|
||||
}
|
||||
|
@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
|
||||
|
||||
for (i = 0 ; i < size ; i++ ) {
|
||||
if (s != NULL) {
|
||||
if (!strnicmp(p[i].name, s, strlen(s)))
|
||||
if (!strncasecmp(p[i].name, s, strlen(s)))
|
||||
return p[i].val;
|
||||
} else {
|
||||
if (p[i].val == val)
|
||||
|
@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev,
|
||||
if (len < 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (strnicmp(buf, "on", 2) == 0 ||
|
||||
strnicmp(buf, "1", 1) == 0) {
|
||||
if (strncasecmp(buf, "on", 2) == 0 ||
|
||||
strncasecmp(buf, "1", 1) == 0) {
|
||||
debug = 1;
|
||||
dev_dbg(dev, "s3c2410fb: Debug On");
|
||||
} else if (strnicmp(buf, "off", 3) == 0 ||
|
||||
strnicmp(buf, "0", 1) == 0) {
|
||||
} else if (strncasecmp(buf, "off", 3) == 0 ||
|
||||
strncasecmp(buf, "0", 1) == 0) {
|
||||
debug = 0;
|
||||
dev_dbg(dev, "s3c2410fb: Debug Off");
|
||||
} else {
|
||||
|
@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
|
||||
if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
|
||||
if(!quiet)
|
||||
printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
|
||||
|
||||
@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet)
|
||||
|
||||
i = 0; j = 0;
|
||||
while(sisbios_mode[i].mode_no[0] != 0) {
|
||||
if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
|
||||
if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
|
||||
if(sisfb_fstn) {
|
||||
if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
|
||||
sisbios_mode[i-1].mode_no[1] == 0x56 ||
|
||||
@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name)
|
||||
if(name == NULL) return;
|
||||
|
||||
while(sis_crt2type[i].type_no != -1) {
|
||||
if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
|
||||
if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
|
||||
sisfb_crt2type = sis_crt2type[i].type_no;
|
||||
sisfb_tvplug = sis_crt2type[i].tvplug_no;
|
||||
sisfb_crt2flags = sis_crt2type[i].flags;
|
||||
@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name)
|
||||
return;
|
||||
|
||||
while(sis_tvtype[i].type_no != -1) {
|
||||
if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
|
||||
if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
|
||||
sisfb_tvstd = sis_tvtype[i].type_no;
|
||||
break;
|
||||
}
|
||||
@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name)
|
||||
if(name == NULL)
|
||||
return;
|
||||
|
||||
if(!strnicmp(name, "none", 4)) {
|
||||
if(!strncasecmp(name, "none", 4)) {
|
||||
sisfb_specialtiming = CUT_FORCENONE;
|
||||
printk(KERN_DEBUG "sisfb: Special timing disabled\n");
|
||||
} else {
|
||||
while(mycustomttable[i].chipID != 0) {
|
||||
if(!strnicmp(name,mycustomttable[i].optionName,
|
||||
if(!strncasecmp(name,mycustomttable[i].optionName,
|
||||
strlen(mycustomttable[i].optionName))) {
|
||||
sisfb_specialtiming = mycustomttable[i].SpecialID;
|
||||
found = true;
|
||||
@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options)
|
||||
|
||||
if(!(*this_opt)) continue;
|
||||
|
||||
if(!strnicmp(this_opt, "off", 3)) {
|
||||
if(!strncasecmp(this_opt, "off", 3)) {
|
||||
sisfb_off = 1;
|
||||
} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
|
||||
} else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
|
||||
/* Need to check crt2 type first for fstn/dstn */
|
||||
sisfb_search_crt2type(this_opt + 14);
|
||||
} else if(!strnicmp(this_opt, "tvmode:",7)) {
|
||||
} else if(!strncasecmp(this_opt, "tvmode:",7)) {
|
||||
sisfb_search_tvstd(this_opt + 7);
|
||||
} else if(!strnicmp(this_opt, "tvstandard:",11)) {
|
||||
} else if(!strncasecmp(this_opt, "tvstandard:",11)) {
|
||||
sisfb_search_tvstd(this_opt + 11);
|
||||
} else if(!strnicmp(this_opt, "mode:", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "mode:", 5)) {
|
||||
sisfb_search_mode(this_opt + 5, false);
|
||||
} else if(!strnicmp(this_opt, "vesa:", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "vesa:", 5)) {
|
||||
sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
|
||||
} else if(!strnicmp(this_opt, "rate:", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "rate:", 5)) {
|
||||
sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
|
||||
} else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
|
||||
sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "mem:",4)) {
|
||||
} else if(!strncasecmp(this_opt, "mem:",4)) {
|
||||
sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "pdc:", 4)) {
|
||||
} else if(!strncasecmp(this_opt, "pdc:", 4)) {
|
||||
sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "pdc1:", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "pdc1:", 5)) {
|
||||
sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "noaccel", 7)) {
|
||||
} else if(!strncasecmp(this_opt, "noaccel", 7)) {
|
||||
sisfb_accel = 0;
|
||||
} else if(!strnicmp(this_opt, "accel", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "accel", 5)) {
|
||||
sisfb_accel = -1;
|
||||
} else if(!strnicmp(this_opt, "noypan", 6)) {
|
||||
} else if(!strncasecmp(this_opt, "noypan", 6)) {
|
||||
sisfb_ypan = 0;
|
||||
} else if(!strnicmp(this_opt, "ypan", 4)) {
|
||||
} else if(!strncasecmp(this_opt, "ypan", 4)) {
|
||||
sisfb_ypan = -1;
|
||||
} else if(!strnicmp(this_opt, "nomax", 5)) {
|
||||
} else if(!strncasecmp(this_opt, "nomax", 5)) {
|
||||
sisfb_max = 0;
|
||||
} else if(!strnicmp(this_opt, "max", 3)) {
|
||||
} else if(!strncasecmp(this_opt, "max", 3)) {
|
||||
sisfb_max = -1;
|
||||
} else if(!strnicmp(this_opt, "userom:", 7)) {
|
||||
} else if(!strncasecmp(this_opt, "userom:", 7)) {
|
||||
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "useoem:", 7)) {
|
||||
} else if(!strncasecmp(this_opt, "useoem:", 7)) {
|
||||
sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
|
||||
} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
|
||||
} else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
|
||||
sisfb_nocrt2rate = 1;
|
||||
} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
|
||||
} else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
|
||||
unsigned long temp = 2;
|
||||
temp = simple_strtoul(this_opt + 9, NULL, 0);
|
||||
if((temp == 0) || (temp == 1)) {
|
||||
sisfb_scalelcd = temp ^ 1;
|
||||
}
|
||||
} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
|
||||
} else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
|
||||
int temp = 0;
|
||||
temp = (int)simple_strtol(this_opt + 13, NULL, 0);
|
||||
if((temp >= -32) && (temp <= 32)) {
|
||||
sisfb_tvxposoffset = temp;
|
||||
}
|
||||
} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
|
||||
} else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
|
||||
int temp = 0;
|
||||
temp = (int)simple_strtol(this_opt + 13, NULL, 0);
|
||||
if((temp >= -32) && (temp <= 32)) {
|
||||
sisfb_tvyposoffset = temp;
|
||||
}
|
||||
} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
|
||||
} else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
|
||||
sisfb_search_specialtiming(this_opt + 14);
|
||||
} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
|
||||
} else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
|
||||
int temp = 4;
|
||||
temp = simple_strtoul(this_opt + 7, NULL, 0);
|
||||
if((temp >= 0) && (temp <= 3)) {
|
||||
@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options)
|
||||
} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
|
||||
sisfb_search_mode(this_opt, true);
|
||||
#if !defined(__i386__) && !defined(__x86_64__)
|
||||
} else if(!strnicmp(this_opt, "resetcard", 9)) {
|
||||
} else if(!strncasecmp(this_opt, "resetcard", 9)) {
|
||||
sisfb_resetcard = 1;
|
||||
} else if(!strnicmp(this_opt, "videoram:", 9)) {
|
||||
} else if(!strncasecmp(this_opt, "videoram:", 9)) {
|
||||
sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
|
||||
#endif
|
||||
} else {
|
||||
|
@ -1187,9 +1187,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
|
||||
if (len < 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (strnicmp(buf, "crt", 3) == 0)
|
||||
if (strncasecmp(buf, "crt", 3) == 0)
|
||||
head = HEAD_CRT;
|
||||
else if (strnicmp(buf, "panel", 5) == 0)
|
||||
else if (strncasecmp(buf, "panel", 5) == 0)
|
||||
head = HEAD_PANEL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
#include "affs.h"
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
static char ErrorBuffer[256];
|
||||
|
||||
/*
|
||||
|
@ -584,11 +584,14 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
|
||||
bh->b_state &= ~(1UL << BH_New);
|
||||
mark_buffer_dirty_inode(bh, inode);
|
||||
if (prev_bh) {
|
||||
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
if (tmp)
|
||||
affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);
|
||||
u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
|
||||
if (tmp_next)
|
||||
affs_warning(sb, "extent_file_ofs",
|
||||
"next block already set for %d (%d)",
|
||||
bidx, tmp_next);
|
||||
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
|
||||
mark_buffer_dirty_inode(prev_bh, inode);
|
||||
affs_brelse(prev_bh);
|
||||
}
|
||||
@ -727,11 +730,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
|
||||
AFFS_DATA_HEAD(bh)->next = 0;
|
||||
bh->b_state &= ~(1UL << BH_New);
|
||||
if (prev_bh) {
|
||||
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
if (tmp)
|
||||
affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
|
||||
u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
|
||||
if (tmp_next)
|
||||
affs_warning(sb, "commit_write_ofs",
|
||||
"next block already set for %d (%d)",
|
||||
bidx, tmp_next);
|
||||
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
|
||||
mark_buffer_dirty_inode(prev_bh, inode);
|
||||
}
|
||||
}
|
||||
@ -758,11 +764,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
|
||||
AFFS_DATA_HEAD(bh)->next = 0;
|
||||
bh->b_state &= ~(1UL << BH_New);
|
||||
if (prev_bh) {
|
||||
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
if (tmp)
|
||||
affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
|
||||
u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
|
||||
|
||||
if (tmp_next)
|
||||
affs_warning(sb, "commit_write_ofs",
|
||||
"next block already set for %d (%d)",
|
||||
bidx, tmp_next);
|
||||
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
|
||||
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
|
||||
mark_buffer_dirty_inode(prev_bh, inode);
|
||||
}
|
||||
} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
|
||||
@ -842,12 +851,12 @@ affs_truncate(struct inode *inode)
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct page *page;
|
||||
void *fsdata;
|
||||
loff_t size = inode->i_size;
|
||||
loff_t isize = inode->i_size;
|
||||
int res;
|
||||
|
||||
res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
|
||||
res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, 0, &page, &fsdata);
|
||||
if (!res)
|
||||
res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
|
||||
res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
|
||||
else
|
||||
inode->i_size = AFFS_I(inode)->mmu_private;
|
||||
mark_inode_dirty(inode);
|
||||
|
@ -14,13 +14,11 @@
|
||||
#include "affs.h"
|
||||
|
||||
extern const struct inode_operations affs_symlink_inode_operations;
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
struct inode *affs_iget(struct super_block *sb, unsigned long ino)
|
||||
{
|
||||
struct affs_sb_info *sbi = AFFS_SB(sb);
|
||||
struct buffer_head *bh;
|
||||
struct affs_head *head;
|
||||
struct affs_tail *tail;
|
||||
struct inode *inode;
|
||||
u32 block;
|
||||
@ -49,7 +47,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
|
||||
goto bad_inode;
|
||||
}
|
||||
|
||||
head = AFFS_HEAD(bh);
|
||||
tail = AFFS_TAIL(sb, bh);
|
||||
prot = be32_to_cpu(tail->protect);
|
||||
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <linux/writeback.h>
|
||||
#include "affs.h"
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
|
||||
static int affs_remount (struct super_block *sb, int *flags, char *data);
|
||||
|
||||
@ -308,7 +306,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
u32 chksum;
|
||||
int num_bm;
|
||||
int i, j;
|
||||
s32 key;
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
int reserved;
|
||||
@ -367,7 +364,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
i = j = blocksize;
|
||||
size = size / (blocksize / 512);
|
||||
}
|
||||
for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
|
||||
for (blocksize = i; blocksize <= j; blocksize <<= 1, size >>= 1) {
|
||||
sbi->s_root_block = root_block;
|
||||
if (root_block < 0)
|
||||
sbi->s_root_block = (reserved + size - 1) / 2;
|
||||
@ -399,7 +396,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
|
||||
sbi->s_hashsize = blocksize / 4 - 56;
|
||||
sbi->s_root_block += num_bm;
|
||||
key = 1;
|
||||
goto got_root;
|
||||
}
|
||||
affs_brelse(root_bh);
|
||||
|
@ -79,6 +79,10 @@ struct autofs_info {
|
||||
};
|
||||
|
||||
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
|
||||
#define AUTOFS_INF_NO_RCU (1<<1) /* the dentry is being considered
|
||||
* for expiry, so RCU_walk is
|
||||
* not permitted
|
||||
*/
|
||||
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
|
||||
|
||||
struct autofs_wait_queue {
|
||||
@ -148,7 +152,7 @@ void autofs4_free_ino(struct autofs_info *);
|
||||
|
||||
/* Expiration */
|
||||
int is_autofs4_dentry(struct dentry *);
|
||||
int autofs4_expire_wait(struct dentry *dentry);
|
||||
int autofs4_expire_wait(struct dentry *dentry, int rcu_walk);
|
||||
int autofs4_expire_run(struct super_block *, struct vfsmount *,
|
||||
struct autofs_sb_info *,
|
||||
struct autofs_packet_expire __user *);
|
||||
|
@ -450,7 +450,7 @@ static int autofs_dev_ioctl_requester(struct file *fp,
|
||||
ino = autofs4_dentry_ino(path.dentry);
|
||||
if (ino) {
|
||||
err = 0;
|
||||
autofs4_expire_wait(path.dentry);
|
||||
autofs4_expire_wait(path.dentry, 0);
|
||||
spin_lock(&sbi->fs_lock);
|
||||
param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid);
|
||||
param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid);
|
||||
|
@ -30,12 +30,6 @@ static inline int autofs4_can_expire(struct dentry *dentry,
|
||||
/* Too young to die */
|
||||
if (!timeout || time_after(ino->last_used + timeout, now))
|
||||
return 0;
|
||||
|
||||
/* update last_used here :-
|
||||
- obviously makes sense if it is in use now
|
||||
- less obviously, prevents rapid-fire expire
|
||||
attempts if expire fails the first time */
|
||||
ino->last_used = now;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -327,10 +321,19 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
|
||||
if (ino->flags & AUTOFS_INF_PENDING)
|
||||
goto out;
|
||||
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
|
||||
ino->flags |= AUTOFS_INF_EXPIRING;
|
||||
init_completion(&ino->expire_complete);
|
||||
ino->flags |= AUTOFS_INF_NO_RCU;
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
return root;
|
||||
synchronize_rcu();
|
||||
spin_lock(&sbi->fs_lock);
|
||||
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
|
||||
ino->flags |= AUTOFS_INF_EXPIRING;
|
||||
smp_mb();
|
||||
ino->flags &= ~AUTOFS_INF_NO_RCU;
|
||||
init_completion(&ino->expire_complete);
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
return root;
|
||||
}
|
||||
ino->flags &= ~AUTOFS_INF_NO_RCU;
|
||||
}
|
||||
out:
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
@ -339,6 +342,89 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if 'dentry' should expire, or return a nearby
|
||||
* dentry that is suitable.
|
||||
* If returned dentry is different from arg dentry,
|
||||
* then a dget() reference was taken, else not.
|
||||
*/
|
||||
static struct dentry *should_expire(struct dentry *dentry,
|
||||
struct vfsmount *mnt,
|
||||
unsigned long timeout,
|
||||
int how)
|
||||
{
|
||||
int do_now = how & AUTOFS_EXP_IMMEDIATE;
|
||||
int exp_leaves = how & AUTOFS_EXP_LEAVES;
|
||||
struct autofs_info *ino = autofs4_dentry_ino(dentry);
|
||||
unsigned int ino_count;
|
||||
|
||||
/* No point expiring a pending mount */
|
||||
if (ino->flags & AUTOFS_INF_PENDING)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Case 1: (i) indirect mount or top level pseudo direct mount
|
||||
* (autofs-4.1).
|
||||
* (ii) indirect mount with offset mount, check the "/"
|
||||
* offset (autofs-5.0+).
|
||||
*/
|
||||
if (d_mountpoint(dentry)) {
|
||||
DPRINTK("checking mountpoint %p %.*s",
|
||||
dentry, (int)dentry->d_name.len, dentry->d_name.name);
|
||||
|
||||
/* Can we umount this guy */
|
||||
if (autofs4_mount_busy(mnt, dentry))
|
||||
return NULL;
|
||||
|
||||
/* Can we expire this guy */
|
||||
if (autofs4_can_expire(dentry, timeout, do_now))
|
||||
return dentry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
|
||||
DPRINTK("checking symlink %p %.*s",
|
||||
dentry, (int)dentry->d_name.len, dentry->d_name.name);
|
||||
/*
|
||||
* A symlink can't be "busy" in the usual sense so
|
||||
* just check last used for expire timeout.
|
||||
*/
|
||||
if (autofs4_can_expire(dentry, timeout, do_now))
|
||||
return dentry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (simple_empty(dentry))
|
||||
return NULL;
|
||||
|
||||
/* Case 2: tree mount, expire iff entire tree is not busy */
|
||||
if (!exp_leaves) {
|
||||
/* Path walk currently on this dentry? */
|
||||
ino_count = atomic_read(&ino->count) + 1;
|
||||
if (d_count(dentry) > ino_count)
|
||||
return NULL;
|
||||
|
||||
if (!autofs4_tree_busy(mnt, dentry, timeout, do_now))
|
||||
return dentry;
|
||||
/*
|
||||
* Case 3: pseudo direct mount, expire individual leaves
|
||||
* (autofs-4.1).
|
||||
*/
|
||||
} else {
|
||||
/* Path walk currently on this dentry? */
|
||||
struct dentry *expired;
|
||||
ino_count = atomic_read(&ino->count) + 1;
|
||||
if (d_count(dentry) > ino_count)
|
||||
return NULL;
|
||||
|
||||
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
|
||||
if (expired) {
|
||||
if (expired == dentry)
|
||||
dput(dentry);
|
||||
return expired;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Find an eligible tree to time-out
|
||||
* A tree is eligible if :-
|
||||
@ -353,11 +439,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
|
||||
unsigned long timeout;
|
||||
struct dentry *root = sb->s_root;
|
||||
struct dentry *dentry;
|
||||
struct dentry *expired = NULL;
|
||||
int do_now = how & AUTOFS_EXP_IMMEDIATE;
|
||||
int exp_leaves = how & AUTOFS_EXP_LEAVES;
|
||||
struct dentry *expired;
|
||||
struct autofs_info *ino;
|
||||
unsigned int ino_count;
|
||||
|
||||
if (!root)
|
||||
return NULL;
|
||||
@ -369,77 +452,28 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
|
||||
while ((dentry = get_next_positive_subdir(dentry, root))) {
|
||||
spin_lock(&sbi->fs_lock);
|
||||
ino = autofs4_dentry_ino(dentry);
|
||||
/* No point expiring a pending mount */
|
||||
if (ino->flags & AUTOFS_INF_PENDING)
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Case 1: (i) indirect mount or top level pseudo direct mount
|
||||
* (autofs-4.1).
|
||||
* (ii) indirect mount with offset mount, check the "/"
|
||||
* offset (autofs-5.0+).
|
||||
*/
|
||||
if (d_mountpoint(dentry)) {
|
||||
DPRINTK("checking mountpoint %p %.*s",
|
||||
dentry, (int)dentry->d_name.len, dentry->d_name.name);
|
||||
|
||||
/* Can we umount this guy */
|
||||
if (autofs4_mount_busy(mnt, dentry))
|
||||
goto next;
|
||||
|
||||
/* Can we expire this guy */
|
||||
if (autofs4_can_expire(dentry, timeout, do_now)) {
|
||||
expired = dentry;
|
||||
goto found;
|
||||
}
|
||||
goto next;
|
||||
if (ino->flags & AUTOFS_INF_NO_RCU)
|
||||
expired = NULL;
|
||||
else
|
||||
expired = should_expire(dentry, mnt, timeout, how);
|
||||
if (!expired) {
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
|
||||
DPRINTK("checking symlink %p %.*s",
|
||||
dentry, (int)dentry->d_name.len, dentry->d_name.name);
|
||||
/*
|
||||
* A symlink can't be "busy" in the usual sense so
|
||||
* just check last used for expire timeout.
|
||||
*/
|
||||
if (autofs4_can_expire(dentry, timeout, do_now)) {
|
||||
expired = dentry;
|
||||
goto found;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (simple_empty(dentry))
|
||||
goto next;
|
||||
|
||||
/* Case 2: tree mount, expire iff entire tree is not busy */
|
||||
if (!exp_leaves) {
|
||||
/* Path walk currently on this dentry? */
|
||||
ino_count = atomic_read(&ino->count) + 1;
|
||||
if (d_count(dentry) > ino_count)
|
||||
goto next;
|
||||
|
||||
if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
|
||||
expired = dentry;
|
||||
goto found;
|
||||
}
|
||||
/*
|
||||
* Case 3: pseudo direct mount, expire individual leaves
|
||||
* (autofs-4.1).
|
||||
*/
|
||||
} else {
|
||||
/* Path walk currently on this dentry? */
|
||||
ino_count = atomic_read(&ino->count) + 1;
|
||||
if (d_count(dentry) > ino_count)
|
||||
goto next;
|
||||
|
||||
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
|
||||
if (expired) {
|
||||
ino = autofs4_dentry_ino(expired);
|
||||
ino->flags |= AUTOFS_INF_NO_RCU;
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
synchronize_rcu();
|
||||
spin_lock(&sbi->fs_lock);
|
||||
if (should_expire(expired, mnt, timeout, how)) {
|
||||
if (expired != dentry)
|
||||
dput(dentry);
|
||||
goto found;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
next:
|
||||
|
||||
ino->flags &= ~AUTOFS_INF_NO_RCU;
|
||||
if (expired != dentry)
|
||||
dput(expired);
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
}
|
||||
return NULL;
|
||||
@ -447,8 +481,9 @@ next:
|
||||
found:
|
||||
DPRINTK("returning %p %.*s",
|
||||
expired, (int)expired->d_name.len, expired->d_name.name);
|
||||
ino = autofs4_dentry_ino(expired);
|
||||
ino->flags |= AUTOFS_INF_EXPIRING;
|
||||
smp_mb();
|
||||
ino->flags &= ~AUTOFS_INF_NO_RCU;
|
||||
init_completion(&ino->expire_complete);
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
spin_lock(&sbi->lookup_lock);
|
||||
@ -461,13 +496,18 @@ found:
|
||||
return expired;
|
||||
}
|
||||
|
||||
int autofs4_expire_wait(struct dentry *dentry)
|
||||
int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
|
||||
{
|
||||
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
|
||||
struct autofs_info *ino = autofs4_dentry_ino(dentry);
|
||||
int status;
|
||||
|
||||
/* Block on any pending expire */
|
||||
if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)))
|
||||
return 0;
|
||||
if (rcu_walk)
|
||||
return -ECHILD;
|
||||
|
||||
spin_lock(&sbi->fs_lock);
|
||||
if (ino->flags & AUTOFS_INF_EXPIRING) {
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
@ -519,6 +559,8 @@ int autofs4_expire_run(struct super_block *sb,
|
||||
|
||||
spin_lock(&sbi->fs_lock);
|
||||
ino = autofs4_dentry_ino(dentry);
|
||||
/* avoid rapid-fire expire attempts if expiry fails */
|
||||
ino->last_used = now;
|
||||
ino->flags &= ~AUTOFS_INF_EXPIRING;
|
||||
complete_all(&ino->expire_complete);
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
@ -545,6 +587,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
|
||||
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
|
||||
|
||||
spin_lock(&sbi->fs_lock);
|
||||
/* avoid rapid-fire expire attempts if expiry fails */
|
||||
ino->last_used = now;
|
||||
ino->flags &= ~AUTOFS_INF_EXPIRING;
|
||||
complete_all(&ino->expire_complete);
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
|
@ -210,7 +210,8 @@ next:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
|
||||
static struct dentry *autofs4_lookup_expiring(struct dentry *dentry,
|
||||
bool rcu_walk)
|
||||
{
|
||||
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
|
||||
struct dentry *parent = dentry->d_parent;
|
||||
@ -229,6 +230,11 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
|
||||
struct dentry *expiring;
|
||||
struct qstr *qstr;
|
||||
|
||||
if (rcu_walk) {
|
||||
spin_unlock(&sbi->lookup_lock);
|
||||
return ERR_PTR(-ECHILD);
|
||||
}
|
||||
|
||||
ino = list_entry(p, struct autofs_info, expiring);
|
||||
expiring = ino->dentry;
|
||||
|
||||
@ -264,13 +270,15 @@ next:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int autofs4_mount_wait(struct dentry *dentry)
|
||||
static int autofs4_mount_wait(struct dentry *dentry, bool rcu_walk)
|
||||
{
|
||||
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
|
||||
struct autofs_info *ino = autofs4_dentry_ino(dentry);
|
||||
int status = 0;
|
||||
|
||||
if (ino->flags & AUTOFS_INF_PENDING) {
|
||||
if (rcu_walk)
|
||||
return -ECHILD;
|
||||
DPRINTK("waiting for mount name=%.*s",
|
||||
dentry->d_name.len, dentry->d_name.name);
|
||||
status = autofs4_wait(sbi, dentry, NFY_MOUNT);
|
||||
@ -280,20 +288,22 @@ static int autofs4_mount_wait(struct dentry *dentry)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int do_expire_wait(struct dentry *dentry)
|
||||
static int do_expire_wait(struct dentry *dentry, bool rcu_walk)
|
||||
{
|
||||
struct dentry *expiring;
|
||||
|
||||
expiring = autofs4_lookup_expiring(dentry);
|
||||
expiring = autofs4_lookup_expiring(dentry, rcu_walk);
|
||||
if (IS_ERR(expiring))
|
||||
return PTR_ERR(expiring);
|
||||
if (!expiring)
|
||||
return autofs4_expire_wait(dentry);
|
||||
return autofs4_expire_wait(dentry, rcu_walk);
|
||||
else {
|
||||
/*
|
||||
* If we are racing with expire the request might not
|
||||
* be quite complete, but the directory has been removed
|
||||
* so it must have been successful, just wait for it.
|
||||
*/
|
||||
autofs4_expire_wait(expiring);
|
||||
autofs4_expire_wait(expiring, 0);
|
||||
autofs4_del_expiring(expiring);
|
||||
dput(expiring);
|
||||
}
|
||||
@ -345,7 +355,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
||||
* and the directory was removed, so just go ahead and try
|
||||
* the mount.
|
||||
*/
|
||||
status = do_expire_wait(dentry);
|
||||
status = do_expire_wait(dentry, 0);
|
||||
if (status && status != -EAGAIN)
|
||||
return NULL;
|
||||
|
||||
@ -353,7 +363,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
||||
spin_lock(&sbi->fs_lock);
|
||||
if (ino->flags & AUTOFS_INF_PENDING) {
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
status = autofs4_mount_wait(dentry);
|
||||
status = autofs4_mount_wait(dentry, 0);
|
||||
if (status)
|
||||
return ERR_PTR(status);
|
||||
goto done;
|
||||
@ -394,7 +404,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
||||
}
|
||||
ino->flags |= AUTOFS_INF_PENDING;
|
||||
spin_unlock(&sbi->fs_lock);
|
||||
status = autofs4_mount_wait(dentry);
|
||||
status = autofs4_mount_wait(dentry, 0);
|
||||
spin_lock(&sbi->fs_lock);
|
||||
ino->flags &= ~AUTOFS_INF_PENDING;
|
||||
if (status) {
|
||||
@ -423,28 +433,46 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
|
||||
|
||||
/* The daemon never waits. */
|
||||
if (autofs4_oz_mode(sbi)) {
|
||||
if (rcu_walk)
|
||||
return 0;
|
||||
if (!d_mountpoint(dentry))
|
||||
return -EISDIR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need to sleep, so we need pathwalk to be in ref-mode */
|
||||
if (rcu_walk)
|
||||
return -ECHILD;
|
||||
|
||||
/* Wait for pending expires */
|
||||
do_expire_wait(dentry);
|
||||
if (do_expire_wait(dentry, rcu_walk) == -ECHILD)
|
||||
return -ECHILD;
|
||||
|
||||
/*
|
||||
* This dentry may be under construction so wait on mount
|
||||
* completion.
|
||||
*/
|
||||
status = autofs4_mount_wait(dentry);
|
||||
status = autofs4_mount_wait(dentry, rcu_walk);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (rcu_walk) {
|
||||
/* We don't need fs_lock in rcu_walk mode,
|
||||
* just testing 'AUTOFS_INFO_NO_RCU' is enough.
|
||||
* simple_empty() takes a spinlock, so leave it
|
||||
* to last.
|
||||
* We only return -EISDIR when certain this isn't
|
||||
* a mount-trap.
|
||||
*/
|
||||
struct inode *inode;
|
||||
if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
|
||||
return 0;
|
||||
if (d_mountpoint(dentry))
|
||||
return 0;
|
||||
inode = ACCESS_ONCE(dentry->d_inode);
|
||||
if (inode && S_ISLNK(inode->i_mode))
|
||||
return -EISDIR;
|
||||
if (list_empty(&dentry->d_subdirs))
|
||||
return 0;
|
||||
if (!simple_empty(dentry))
|
||||
return -EISDIR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock(&sbi->fs_lock);
|
||||
/*
|
||||
* If the dentry has been selected for expire while we slept
|
||||
|
@ -78,11 +78,11 @@
|
||||
/*
|
||||
* In memory structure of each btree node
|
||||
*/
|
||||
typedef struct {
|
||||
struct befs_btree_node {
|
||||
befs_host_btree_nodehead head; /* head of node converted to cpu byteorder */
|
||||
struct buffer_head *bh;
|
||||
befs_btree_nodehead *od_node; /* on disk node */
|
||||
} befs_btree_node;
|
||||
};
|
||||
|
||||
/* local constants */
|
||||
static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
|
||||
@ -90,27 +90,30 @@ static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
|
||||
/* local functions */
|
||||
static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
|
||||
befs_btree_super * bt_super,
|
||||
befs_btree_node * this_node,
|
||||
struct befs_btree_node *this_node,
|
||||
befs_off_t * node_off);
|
||||
|
||||
static int befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
|
||||
befs_btree_super * sup);
|
||||
|
||||
static int befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
|
||||
befs_btree_node * node, befs_off_t node_off);
|
||||
struct befs_btree_node *node,
|
||||
befs_off_t node_off);
|
||||
|
||||
static int befs_leafnode(befs_btree_node * node);
|
||||
static int befs_leafnode(struct befs_btree_node *node);
|
||||
|
||||
static fs16 *befs_bt_keylen_index(befs_btree_node * node);
|
||||
static fs16 *befs_bt_keylen_index(struct befs_btree_node *node);
|
||||
|
||||
static fs64 *befs_bt_valarray(befs_btree_node * node);
|
||||
static fs64 *befs_bt_valarray(struct befs_btree_node *node);
|
||||
|
||||
static char *befs_bt_keydata(befs_btree_node * node);
|
||||
static char *befs_bt_keydata(struct befs_btree_node *node);
|
||||
|
||||
static int befs_find_key(struct super_block *sb, befs_btree_node * node,
|
||||
static int befs_find_key(struct super_block *sb,
|
||||
struct befs_btree_node *node,
|
||||
const char *findkey, befs_off_t * value);
|
||||
|
||||
static char *befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
|
||||
static char *befs_bt_get_key(struct super_block *sb,
|
||||
struct befs_btree_node *node,
|
||||
int index, u16 * keylen);
|
||||
|
||||
static int befs_compare_strings(const void *key1, int keylen1,
|
||||
@ -191,7 +194,7 @@ befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
|
||||
|
||||
static int
|
||||
befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
|
||||
befs_btree_node * node, befs_off_t node_off)
|
||||
struct befs_btree_node *node, befs_off_t node_off)
|
||||
{
|
||||
uint off = 0;
|
||||
|
||||
@ -247,7 +250,7 @@ int
|
||||
befs_btree_find(struct super_block *sb, befs_data_stream * ds,
|
||||
const char *key, befs_off_t * value)
|
||||
{
|
||||
befs_btree_node *this_node = NULL;
|
||||
struct befs_btree_node *this_node = NULL;
|
||||
befs_btree_super bt_super;
|
||||
befs_off_t node_off;
|
||||
int res;
|
||||
@ -260,11 +263,11 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
|
||||
goto error;
|
||||
}
|
||||
|
||||
this_node = kmalloc(sizeof (befs_btree_node),
|
||||
this_node = kmalloc(sizeof(struct befs_btree_node),
|
||||
GFP_NOFS);
|
||||
if (!this_node) {
|
||||
befs_error(sb, "befs_btree_find() failed to allocate %zu "
|
||||
"bytes of memory", sizeof (befs_btree_node));
|
||||
"bytes of memory", sizeof(struct befs_btree_node));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -333,7 +336,7 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
|
||||
* Use binary search instead of a linear.
|
||||
*/
|
||||
static int
|
||||
befs_find_key(struct super_block *sb, befs_btree_node * node,
|
||||
befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
||||
const char *findkey, befs_off_t * value)
|
||||
{
|
||||
int first, last, mid;
|
||||
@ -417,7 +420,7 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
|
||||
loff_t key_no, size_t bufsize, char *keybuf, size_t * keysize,
|
||||
befs_off_t * value)
|
||||
{
|
||||
befs_btree_node *this_node;
|
||||
struct befs_btree_node *this_node;
|
||||
befs_btree_super bt_super;
|
||||
befs_off_t node_off = 0;
|
||||
int cur_key;
|
||||
@ -436,9 +439,10 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((this_node = kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) {
|
||||
this_node = kmalloc(sizeof(struct befs_btree_node), GFP_NOFS);
|
||||
if (this_node == NULL) {
|
||||
befs_error(sb, "befs_btree_read() failed to allocate %zu "
|
||||
"bytes of memory", sizeof (befs_btree_node));
|
||||
"bytes of memory", sizeof(struct befs_btree_node));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -545,7 +549,8 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
|
||||
*/
|
||||
static int
|
||||
befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
|
||||
befs_btree_super * bt_super, befs_btree_node * this_node,
|
||||
befs_btree_super *bt_super,
|
||||
struct befs_btree_node *this_node,
|
||||
befs_off_t * node_off)
|
||||
{
|
||||
|
||||
@ -600,7 +605,7 @@ befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
|
||||
* Return 1 if leaf, 0 if interior
|
||||
*/
|
||||
static int
|
||||
befs_leafnode(befs_btree_node * node)
|
||||
befs_leafnode(struct befs_btree_node *node)
|
||||
{
|
||||
/* all interior nodes (and only interior nodes) have an overflow node */
|
||||
if (node->head.overflow == befs_bt_inval)
|
||||
@ -623,7 +628,7 @@ befs_leafnode(befs_btree_node * node)
|
||||
* Except that rounding up to 8 works, and rounding up to 4 doesn't.
|
||||
*/
|
||||
static fs16 *
|
||||
befs_bt_keylen_index(befs_btree_node * node)
|
||||
befs_bt_keylen_index(struct befs_btree_node *node)
|
||||
{
|
||||
const int keylen_align = 8;
|
||||
unsigned long int off =
|
||||
@ -644,7 +649,7 @@ befs_bt_keylen_index(befs_btree_node * node)
|
||||
* of the node pointed to by the node header
|
||||
*/
|
||||
static fs64 *
|
||||
befs_bt_valarray(befs_btree_node * node)
|
||||
befs_bt_valarray(struct befs_btree_node *node)
|
||||
{
|
||||
void *keylen_index_start = (void *) befs_bt_keylen_index(node);
|
||||
size_t keylen_index_size = node->head.all_key_count * sizeof (fs16);
|
||||
@ -660,7 +665,7 @@ befs_bt_valarray(befs_btree_node * node)
|
||||
* of the node pointed to by the node header
|
||||
*/
|
||||
static char *
|
||||
befs_bt_keydata(befs_btree_node * node)
|
||||
befs_bt_keydata(struct befs_btree_node *node)
|
||||
{
|
||||
return (char *) ((void *) node->od_node + sizeof (befs_btree_nodehead));
|
||||
}
|
||||
@ -676,7 +681,7 @@ befs_bt_keydata(befs_btree_node * node)
|
||||
* Returns NULL on failure (bad input) and sets *@keylen = 0
|
||||
*/
|
||||
static char *
|
||||
befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
|
||||
befs_bt_get_key(struct super_block *sb, struct befs_btree_node *node,
|
||||
int index, u16 * keylen)
|
||||
{
|
||||
int prev_key_end;
|
||||
|
@ -62,7 +62,22 @@ static struct file_system_type bm_fs_type;
|
||||
static struct vfsmount *bm_mnt;
|
||||
static int entry_count;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Max length of the register string. Determined by:
|
||||
* - 7 delimiters
|
||||
* - name: ~50 bytes
|
||||
* - type: 1 byte
|
||||
* - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
|
||||
* - magic: 128 bytes (512 in escaped form)
|
||||
* - mask: 128 bytes (512 in escaped form)
|
||||
* - interp: ~50 bytes
|
||||
* - flags: 5 bytes
|
||||
* Round that up a bit, and then back off to hold the internal data
|
||||
* (like struct Node).
|
||||
*/
|
||||
#define MAX_REGISTER_LENGTH 1920
|
||||
|
||||
/*
|
||||
* Check if we support the binfmt
|
||||
* if we do, return the node, else NULL
|
||||
* locking is done in load_misc_binary
|
||||
@ -279,7 +294,7 @@ static Node *create_entry(const char __user *buffer, size_t count)
|
||||
|
||||
/* some sanity checks */
|
||||
err = -EINVAL;
|
||||
if ((count < 11) || (count > 256))
|
||||
if ((count < 11) || (count > MAX_REGISTER_LENGTH))
|
||||
goto out;
|
||||
|
||||
err = -ENOMEM;
|
||||
@ -396,12 +411,12 @@ static int parse_command(const char __user *buffer, size_t count)
|
||||
{
|
||||
char s[4];
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
if (count > 3)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(s, buffer, count))
|
||||
return -EFAULT;
|
||||
if (!count)
|
||||
return 0;
|
||||
if (s[count-1] == '\n')
|
||||
count--;
|
||||
if (count == 1 && s[0] == '0')
|
||||
|
@ -1331,8 +1331,8 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
|
||||
for (i = 0; i < BH_LRU_SIZE; i++) {
|
||||
struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
|
||||
|
||||
if (bh && bh->b_bdev == bdev &&
|
||||
bh->b_blocknr == block && bh->b_size == size) {
|
||||
if (bh && bh->b_blocknr == block && bh->b_bdev == bdev &&
|
||||
bh->b_size == size) {
|
||||
if (i) {
|
||||
while (i) {
|
||||
__this_cpu_write(bh_lrus.bhs[i],
|
||||
|
@ -195,15 +195,15 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
|
||||
else
|
||||
noff = tkn_e - (sb_mountdata + off) + 1;
|
||||
|
||||
if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
|
||||
if (strncasecmp(sb_mountdata + off, "unc=", 4) == 0) {
|
||||
off += noff;
|
||||
continue;
|
||||
}
|
||||
if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) {
|
||||
if (strncasecmp(sb_mountdata + off, "ip=", 3) == 0) {
|
||||
off += noff;
|
||||
continue;
|
||||
}
|
||||
if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
|
||||
if (strncasecmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
|
||||
off += noff;
|
||||
continue;
|
||||
}
|
||||
|
@ -1718,7 +1718,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
|
||||
if (strnicmp(string, "default", 7) != 0) {
|
||||
if (strncasecmp(string, "default", 7) != 0) {
|
||||
vol->iocharset = kstrdup(string,
|
||||
GFP_KERNEL);
|
||||
if (!vol->iocharset) {
|
||||
@ -1790,7 +1790,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
|
||||
if (strnicmp(string, "1", 1) == 0) {
|
||||
if (strncasecmp(string, "1", 1) == 0) {
|
||||
/* This is the default */
|
||||
break;
|
||||
}
|
||||
|
@ -199,6 +199,14 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
|
||||
err = cn_printf(cn, "%d",
|
||||
task_tgid_nr(current));
|
||||
break;
|
||||
case 'i':
|
||||
err = cn_printf(cn, "%d",
|
||||
task_pid_vnr(current));
|
||||
break;
|
||||
case 'I':
|
||||
err = cn_printf(cn, "%d",
|
||||
task_pid_nr(current));
|
||||
break;
|
||||
/* uid */
|
||||
case 'u':
|
||||
err = cn_printf(cn, "%d", cred->uid);
|
||||
|
@ -164,8 +164,6 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
/*
|
||||
* The epoch of FAT timestamp is 1980.
|
||||
* : bits : value
|
||||
|
@ -242,8 +242,6 @@ extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
|
||||
/* super.c */
|
||||
extern void hfs_mark_mdb_dirty(struct super_block *sb);
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
/*
|
||||
* There are two time systems. Both are based on seconds since
|
||||
* a particular time/date.
|
||||
|
@ -247,7 +247,7 @@ static int isofs_dentry_cmp_common(
|
||||
}
|
||||
if (alen == blen) {
|
||||
if (ci) {
|
||||
if (strnicmp(name->name, str, alen) == 0)
|
||||
if (strncasecmp(name->name, str, alen) == 0)
|
||||
return 0;
|
||||
} else {
|
||||
if (strncmp(name->name, str, alen) == 0)
|
||||
|
@ -1178,9 +1178,6 @@ static int day_n[] =
|
||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
|
||||
/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
|
||||
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
static int utc2local(int time)
|
||||
{
|
||||
return time - sys_tz.tz_minuteswest * 60;
|
||||
|
@ -56,11 +56,9 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
nilfs = inode->i_sb->s_fs_info;
|
||||
if (!err && nilfs_test_opt(nilfs, BARRIER)) {
|
||||
err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
|
||||
if (err != -EIO)
|
||||
err = 0;
|
||||
}
|
||||
if (!err)
|
||||
err = nilfs_flush_device(nilfs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
|
||||
nilfs_transaction_abort(inode->i_sb);
|
||||
goto out;
|
||||
}
|
||||
nilfs_mark_inode_dirty(inode);
|
||||
nilfs_mark_inode_dirty_sync(inode);
|
||||
nilfs_transaction_commit(inode->i_sb); /* never fails */
|
||||
/* Error handling should be detailed */
|
||||
set_buffer_new(bh_result);
|
||||
@ -672,7 +672,7 @@ void nilfs_write_inode_common(struct inode *inode,
|
||||
for substitutions of appended fields */
|
||||
}
|
||||
|
||||
void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh)
|
||||
void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags)
|
||||
{
|
||||
ino_t ino = inode->i_ino;
|
||||
struct nilfs_inode_info *ii = NILFS_I(inode);
|
||||
@ -683,7 +683,8 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh)
|
||||
|
||||
if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state))
|
||||
memset(raw_inode, 0, NILFS_MDT(ifile)->mi_entry_size);
|
||||
set_bit(NILFS_I_INODE_DIRTY, &ii->i_state);
|
||||
if (flags & I_DIRTY_DATASYNC)
|
||||
set_bit(NILFS_I_INODE_SYNC, &ii->i_state);
|
||||
|
||||
nilfs_write_inode_common(inode, raw_inode, 0);
|
||||
/* XXX: call with has_bmap = 0 is a workaround to avoid
|
||||
@ -939,7 +940,7 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nilfs_mark_inode_dirty(struct inode *inode)
|
||||
int __nilfs_mark_inode_dirty(struct inode *inode, int flags)
|
||||
{
|
||||
struct buffer_head *ibh;
|
||||
int err;
|
||||
@ -950,7 +951,7 @@ int nilfs_mark_inode_dirty(struct inode *inode)
|
||||
"failed to reget inode block.\n");
|
||||
return err;
|
||||
}
|
||||
nilfs_update_inode(inode, ibh);
|
||||
nilfs_update_inode(inode, ibh, flags);
|
||||
mark_buffer_dirty(ibh);
|
||||
nilfs_mdt_mark_dirty(NILFS_I(inode)->i_root->ifile);
|
||||
brelse(ibh);
|
||||
@ -983,7 +984,7 @@ void nilfs_dirty_inode(struct inode *inode, int flags)
|
||||
return;
|
||||
}
|
||||
nilfs_transaction_begin(inode->i_sb, &ti, 0);
|
||||
nilfs_mark_inode_dirty(inode);
|
||||
__nilfs_mark_inode_dirty(inode, flags);
|
||||
nilfs_transaction_commit(inode->i_sb); /* never fails */
|
||||
}
|
||||
|
||||
|
@ -1022,11 +1022,9 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
|
||||
return ret;
|
||||
|
||||
nilfs = inode->i_sb->s_fs_info;
|
||||
if (nilfs_test_opt(nilfs, BARRIER)) {
|
||||
ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
|
||||
if (ret == -EIO)
|
||||
return ret;
|
||||
}
|
||||
ret = nilfs_flush_device(nilfs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (argp != NULL) {
|
||||
down_read(&nilfs->ns_segctor_sem);
|
||||
|
@ -104,7 +104,7 @@ enum {
|
||||
constructor */
|
||||
NILFS_I_COLLECTED, /* All dirty blocks are collected */
|
||||
NILFS_I_UPDATED, /* The file has been written back */
|
||||
NILFS_I_INODE_DIRTY, /* write_inode is requested */
|
||||
NILFS_I_INODE_SYNC, /* dsync is not allowed for inode */
|
||||
NILFS_I_BMAP, /* has bmap and btnode_cache */
|
||||
NILFS_I_GCINODE, /* inode for GC, on memory only */
|
||||
};
|
||||
@ -273,7 +273,7 @@ struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
|
||||
unsigned long ino);
|
||||
extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
|
||||
unsigned long ino, __u64 cno);
|
||||
extern void nilfs_update_inode(struct inode *, struct buffer_head *);
|
||||
extern void nilfs_update_inode(struct inode *, struct buffer_head *, int);
|
||||
extern void nilfs_truncate(struct inode *);
|
||||
extern void nilfs_evict_inode(struct inode *);
|
||||
extern int nilfs_setattr(struct dentry *, struct iattr *);
|
||||
@ -282,10 +282,18 @@ int nilfs_permission(struct inode *inode, int mask);
|
||||
int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh);
|
||||
extern int nilfs_inode_dirty(struct inode *);
|
||||
int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty);
|
||||
extern int nilfs_mark_inode_dirty(struct inode *);
|
||||
extern int __nilfs_mark_inode_dirty(struct inode *, int);
|
||||
extern void nilfs_dirty_inode(struct inode *, int flags);
|
||||
int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
__u64 start, __u64 len);
|
||||
static inline int nilfs_mark_inode_dirty(struct inode *inode)
|
||||
{
|
||||
return __nilfs_mark_inode_dirty(inode, I_DIRTY);
|
||||
}
|
||||
static inline int nilfs_mark_inode_dirty_sync(struct inode *inode)
|
||||
{
|
||||
return __nilfs_mark_inode_dirty(inode, I_DIRTY_SYNC);
|
||||
}
|
||||
|
||||
/* super.c */
|
||||
extern struct inode *nilfs_alloc_inode(struct super_block *);
|
||||
|
@ -930,7 +930,7 @@ static void nilfs_drop_collected_inodes(struct list_head *head)
|
||||
if (!test_and_clear_bit(NILFS_I_COLLECTED, &ii->i_state))
|
||||
continue;
|
||||
|
||||
clear_bit(NILFS_I_INODE_DIRTY, &ii->i_state);
|
||||
clear_bit(NILFS_I_INODE_SYNC, &ii->i_state);
|
||||
set_bit(NILFS_I_UPDATED, &ii->i_state);
|
||||
}
|
||||
}
|
||||
@ -1833,6 +1833,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
|
||||
nilfs_set_next_segment(nilfs, segbuf);
|
||||
|
||||
if (update_sr) {
|
||||
nilfs->ns_flushed_device = 0;
|
||||
nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start,
|
||||
segbuf->sb_sum.seg_seq, nilfs->ns_cno++);
|
||||
|
||||
@ -2194,7 +2195,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
|
||||
nilfs_transaction_lock(sb, &ti, 0);
|
||||
|
||||
ii = NILFS_I(inode);
|
||||
if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) ||
|
||||
if (test_bit(NILFS_I_INODE_SYNC, &ii->i_state) ||
|
||||
nilfs_test_opt(nilfs, STRICT_ORDER) ||
|
||||
test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) ||
|
||||
nilfs_discontinued(nilfs)) {
|
||||
@ -2216,6 +2217,8 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
|
||||
sci->sc_dsync_end = end;
|
||||
|
||||
err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
|
||||
if (!err)
|
||||
nilfs->ns_flushed_device = 0;
|
||||
|
||||
nilfs_transaction_unlock(sb);
|
||||
return err;
|
||||
|
@ -310,6 +310,9 @@ int nilfs_commit_super(struct super_block *sb, int flag)
|
||||
nilfs->ns_sbsize));
|
||||
}
|
||||
clear_nilfs_sb_dirty(nilfs);
|
||||
nilfs->ns_flushed_device = 1;
|
||||
/* make sure store to ns_flushed_device cannot be reordered */
|
||||
smp_wmb();
|
||||
return nilfs_sync_super(sb, flag);
|
||||
}
|
||||
|
||||
@ -514,6 +517,9 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
|
||||
}
|
||||
up_write(&nilfs->ns_sem);
|
||||
|
||||
if (!err)
|
||||
err = nilfs_flush_device(nilfs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ enum {
|
||||
/**
|
||||
* struct the_nilfs - struct to supervise multiple nilfs mount points
|
||||
* @ns_flags: flags
|
||||
* @ns_flushed_device: flag indicating if all volatile data was flushed
|
||||
* @ns_bdev: block device
|
||||
* @ns_sem: semaphore for shared states
|
||||
* @ns_snapshot_mount_mutex: mutex to protect snapshot mounts
|
||||
@ -103,6 +104,7 @@ enum {
|
||||
*/
|
||||
struct the_nilfs {
|
||||
unsigned long ns_flags;
|
||||
int ns_flushed_device;
|
||||
|
||||
struct block_device *ns_bdev;
|
||||
struct rw_semaphore ns_sem;
|
||||
@ -371,4 +373,24 @@ static inline int nilfs_segment_is_active(struct the_nilfs *nilfs, __u64 n)
|
||||
return n == nilfs->ns_segnum || n == nilfs->ns_nextnum;
|
||||
}
|
||||
|
||||
static inline int nilfs_flush_device(struct the_nilfs *nilfs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!nilfs_test_opt(nilfs, BARRIER) || nilfs->ns_flushed_device)
|
||||
return 0;
|
||||
|
||||
nilfs->ns_flushed_device = 1;
|
||||
/*
|
||||
* the store to ns_flushed_device must not be reordered after
|
||||
* blkdev_issue_flush().
|
||||
*/
|
||||
smp_wmb();
|
||||
|
||||
err = blkdev_issue_flush(nilfs->ns_bdev, GFP_KERNEL, NULL);
|
||||
if (err != -EIO)
|
||||
err = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* _THE_NILFS_H */
|
||||
|
@ -2244,7 +2244,7 @@ ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) {
|
||||
if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len))
|
||||
if (strncasecmp(page, o2hb_heartbeat_mode_desc[i], len))
|
||||
continue;
|
||||
|
||||
ret = o2hb_global_heartbeat_mode_set(i);
|
||||
|
@ -49,13 +49,13 @@ static ssize_t mlog_mask_show(u64 mask, char *buf)
|
||||
|
||||
static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count)
|
||||
{
|
||||
if (!strnicmp(buf, "allow", 5)) {
|
||||
if (!strncasecmp(buf, "allow", 5)) {
|
||||
__mlog_set_u64(mask, mlog_and_bits);
|
||||
__mlog_clear_u64(mask, mlog_not_bits);
|
||||
} else if (!strnicmp(buf, "deny", 4)) {
|
||||
} else if (!strncasecmp(buf, "deny", 4)) {
|
||||
__mlog_set_u64(mask, mlog_not_bits);
|
||||
__mlog_clear_u64(mask, mlog_and_bits);
|
||||
} else if (!strnicmp(buf, "off", 3)) {
|
||||
} else if (!strncasecmp(buf, "off", 3)) {
|
||||
__mlog_clear_u64(mask, mlog_not_bits);
|
||||
__mlog_clear_u64(mask, mlog_and_bits);
|
||||
} else
|
||||
|
@ -306,9 +306,7 @@ static const struct super_operations omfs_sops = {
|
||||
*/
|
||||
static int omfs_get_imap(struct super_block *sb)
|
||||
{
|
||||
int bitmap_size;
|
||||
int array_size;
|
||||
int count;
|
||||
unsigned int bitmap_size, count, array_size;
|
||||
struct omfs_sb_info *sbi = OMFS_SB(sb);
|
||||
struct buffer_head *bh;
|
||||
unsigned long **ptr;
|
||||
@ -473,6 +471,12 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sbi->s_sys_blocksize = be32_to_cpu(omfs_sb->s_sys_blocksize);
|
||||
mutex_init(&sbi->s_bitmap_lock);
|
||||
|
||||
if (sbi->s_num_blocks > OMFS_MAX_BLOCKS) {
|
||||
printk(KERN_ERR "omfs: sysblock number (%llx) is out of range\n",
|
||||
(unsigned long long)sbi->s_num_blocks);
|
||||
goto out_brelse_bh;
|
||||
}
|
||||
|
||||
if (sbi->s_sys_blocksize > PAGE_SIZE) {
|
||||
printk(KERN_ERR "omfs: sysblock size (%d) is out of range\n",
|
||||
sbi->s_sys_blocksize);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define OMFS_XOR_COUNT 19
|
||||
#define OMFS_MAX_BLOCK_SIZE 8192
|
||||
#define OMFS_MAX_CLUSTER_SIZE 8
|
||||
#define OMFS_MAX_BLOCKS (1ul << 31)
|
||||
|
||||
struct omfs_super_block {
|
||||
char s_fill1[256];
|
||||
|
@ -827,8 +827,21 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
|
||||
.private = &cp,
|
||||
};
|
||||
down_read(&mm->mmap_sem);
|
||||
if (type == CLEAR_REFS_SOFT_DIRTY)
|
||||
if (type == CLEAR_REFS_SOFT_DIRTY) {
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
if (!(vma->vm_flags & VM_SOFTDIRTY))
|
||||
continue;
|
||||
up_read(&mm->mmap_sem);
|
||||
down_write(&mm->mmap_sem);
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
vma->vm_flags &= ~VM_SOFTDIRTY;
|
||||
vma_set_page_prot(vma);
|
||||
}
|
||||
downgrade_write(&mm->mmap_sem);
|
||||
break;
|
||||
}
|
||||
mmu_notifier_invalidate_range_start(mm, 0, -1);
|
||||
}
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
cp.vma = vma;
|
||||
if (is_vm_hugetlb_page(vma))
|
||||
@ -848,10 +861,6 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
|
||||
continue;
|
||||
if (type == CLEAR_REFS_MAPPED && !vma->vm_file)
|
||||
continue;
|
||||
if (type == CLEAR_REFS_SOFT_DIRTY) {
|
||||
if (vma->vm_flags & VM_SOFTDIRTY)
|
||||
vma->vm_flags &= ~VM_SOFTDIRTY;
|
||||
}
|
||||
walk_page_range(vma->vm_start, vma->vm_end,
|
||||
&clear_refs_walk);
|
||||
}
|
||||
|
@ -699,11 +699,13 @@ static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh,
|
||||
chunk->bh[chunk->nr++] = bh;
|
||||
if (chunk->nr >= CHUNK_SIZE) {
|
||||
ret = 1;
|
||||
if (lock)
|
||||
if (lock) {
|
||||
spin_unlock(lock);
|
||||
fn(chunk);
|
||||
if (lock)
|
||||
fn(chunk);
|
||||
spin_lock(lock);
|
||||
} else {
|
||||
fn(chunk);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -784,7 +784,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
|
||||
0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
|
||||
};
|
||||
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
|
||||
struct ufs_cylinder_group *ucg;
|
||||
unsigned start, length, loc;
|
||||
unsigned pos, want, blockmap, mask, end;
|
||||
u64 result;
|
||||
@ -792,8 +791,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
|
||||
UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
|
||||
(unsigned long long)goal, count);
|
||||
|
||||
ucg = ubh_get_ucg(UCPI_UBH(ucpi));
|
||||
|
||||
if (goal)
|
||||
start = ufs_dtogd(uspi, goal) >> 3;
|
||||
else
|
||||
|
@ -253,6 +253,20 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
|
||||
#define pgprot_device pgprot_noncached
|
||||
#endif
|
||||
|
||||
#ifndef pgprot_modify
|
||||
#define pgprot_modify pgprot_modify
|
||||
static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
|
||||
{
|
||||
if (pgprot_val(oldprot) == pgprot_val(pgprot_noncached(oldprot)))
|
||||
newprot = pgprot_noncached(newprot);
|
||||
if (pgprot_val(oldprot) == pgprot_val(pgprot_writecombine(oldprot)))
|
||||
newprot = pgprot_writecombine(newprot);
|
||||
if (pgprot_val(oldprot) == pgprot_val(pgprot_device(oldprot)))
|
||||
newprot = pgprot_device(newprot);
|
||||
return newprot;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When walking page tables, get the address of the next boundary,
|
||||
* or the end address of the range if that comes earlier. Although no
|
||||
|
@ -22,6 +22,9 @@ extern int __init cma_declare_contiguous(phys_addr_t size,
|
||||
phys_addr_t base, phys_addr_t limit,
|
||||
phys_addr_t alignment, unsigned int order_per_bit,
|
||||
bool fixed, struct cma **res_cma);
|
||||
extern int cma_init_reserved_mem(phys_addr_t size,
|
||||
phys_addr_t base, int order_per_bit,
|
||||
struct cma **res_cma);
|
||||
extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align);
|
||||
extern bool cma_release(struct cma *cma, struct page *pages, int count);
|
||||
#endif
|
||||
|
66
include/linux/compiler-gcc5.h
Normal file
66
include/linux/compiler-gcc5.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef __LINUX_COMPILER_H
|
||||
#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead."
|
||||
#endif
|
||||
|
||||
#define __used __attribute__((__used__))
|
||||
#define __must_check __attribute__((warn_unused_result))
|
||||
#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
|
||||
|
||||
/* Mark functions as cold. gcc will assume any path leading to a call
|
||||
to them will be unlikely. This means a lot of manual unlikely()s
|
||||
are unnecessary now for any paths leading to the usual suspects
|
||||
like BUG(), printk(), panic() etc. [but let's keep them for now for
|
||||
older compilers]
|
||||
|
||||
Early snapshots of gcc 4.3 don't support this and we can't detect this
|
||||
in the preprocessor, but we can live with this because they're unreleased.
|
||||
Maketime probing would be overkill here.
|
||||
|
||||
gcc also has a __attribute__((__hot__)) to move hot functions into
|
||||
a special section, but I don't see any sense in this right now in
|
||||
the kernel context */
|
||||
#define __cold __attribute__((__cold__))
|
||||
|
||||
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
|
||||
|
||||
#ifndef __CHECKER__
|
||||
# define __compiletime_warning(message) __attribute__((warning(message)))
|
||||
# define __compiletime_error(message) __attribute__((error(message)))
|
||||
#endif /* __CHECKER__ */
|
||||
|
||||
/*
|
||||
* Mark a position in code as unreachable. This can be used to
|
||||
* suppress control flow warnings after asm blocks that transfer
|
||||
* control elsewhere.
|
||||
*
|
||||
* Early snapshots of gcc 4.5 don't support this and we can't detect
|
||||
* this in the preprocessor, but we can live with this because they're
|
||||
* unreleased. Really, we need to have autoconf for the kernel.
|
||||
*/
|
||||
#define unreachable() __builtin_unreachable()
|
||||
|
||||
/* Mark a function definition as prohibited from being cloned. */
|
||||
#define __noclone __attribute__((__noclone__))
|
||||
|
||||
/*
|
||||
* Tell the optimizer that something else uses this function or variable.
|
||||
*/
|
||||
#define __visible __attribute__((externally_visible))
|
||||
|
||||
/*
|
||||
* GCC 'asm goto' miscompiles certain code sequences:
|
||||
*
|
||||
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
|
||||
*
|
||||
* Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
|
||||
* Fixed in GCC 4.8.2 and later versions.
|
||||
*
|
||||
* (asm goto is automatically volatile - the naming reflects this.)
|
||||
*/
|
||||
#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
|
||||
#define __HAVE_BUILTIN_BSWAP32__
|
||||
#define __HAVE_BUILTIN_BSWAP64__
|
||||
#define __HAVE_BUILTIN_BSWAP16__
|
||||
#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
|
@ -376,10 +376,6 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int);
|
||||
extern long simple_strtol(const char *,char **,unsigned int);
|
||||
extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
|
||||
extern long long simple_strtoll(const char *,char **,unsigned int);
|
||||
#define strict_strtoul kstrtoul
|
||||
#define strict_strtol kstrtol
|
||||
#define strict_strtoull kstrtoull
|
||||
#define strict_strtoll kstrtoll
|
||||
|
||||
extern int num_to_str(char *buf, int size, unsigned long long num);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user